mukan-ibc/e2e/testsuite/diagnostics/diagnostics.go
Mukan Erkin Törük 6852832fe8
Some checks failed
CodeQL / Analyze (push) Waiting to run
Docker Build & Push Simapp (main) / docker-build (push) Waiting to run
golangci-lint / lint (push) Waiting to run
Tests / Code Coverage / build (amd64) (push) Waiting to run
Tests / Code Coverage / build (arm64) (push) Waiting to run
Tests / Code Coverage / unit-tests (map[additional-args:-tags="test_e2e" name:e2e path:./e2e]) (push) Waiting to run
Tests / Code Coverage / unit-tests (map[name:08-wasm path:./modules/light-clients/08-wasm]) (push) Waiting to run
Tests / Code Coverage / unit-tests (map[name:ibc-go path:.]) (push) Waiting to run
Deploy to GitHub Pages / Deploy to GitHub Pages (push) Has been cancelled
Buf-Push / push (push) Has been cancelled
initial: sovereign Mukan Network fork
2026-05-11 03:18:28 +03:00

163 lines
5.5 KiB
Go

package diagnostics
import (
"context"
"encoding/json"
"fmt"
"os"
ospath "path"
"strings"
"testing"
dockertypes "github.com/docker/docker/api/types"
mobycli "github.com/moby/moby/client"
"github.com/cosmos/ibc-go/e2e/dockerutil"
"github.com/cosmos/ibc-go/e2e/internal/directories"
)
const (
dockerInspectFileName = "docker-inspect.json"
defaultFilePerm = 0o750
)
// Collect can be used in `t.Cleanup` and will copy all the of the container logs and relevant files
// into e2e/<test-suite>/<test-name>.log. These log files will be uploaded to GH upon test failure.
func Collect(t *testing.T, dc *mobycli.Client, debugModeEnabled bool, suiteName string, chainNames ...string) {
t.Helper()
if !debugModeEnabled {
// when we are not forcing log collection, we only upload upon test failing.
if !t.Failed() {
t.Logf("test passed, not uploading logs")
return
}
}
t.Logf("writing logs for test: %s", t.Name())
ctx := context.TODO()
e2eDir, err := directories.E2E()
if err != nil {
t.Logf("failed finding log directory: %s", err)
return
}
logsDir := fmt.Sprintf("%s/diagnostics", e2eDir)
if err := os.MkdirAll(fmt.Sprintf("%s/%s", logsDir, t.Name()), defaultFilePerm); err != nil {
t.Logf("failed creating logs directory in test cleanup: %s", err)
return
}
testContainers, err := dockerutil.GetTestContainers(ctx, suiteName, dc)
if err != nil {
t.Logf("failed listing containers during test cleanup: %s", err)
return
}
for _, container := range testContainers {
containerName := getContainerName(t, container)
containerDir := fmt.Sprintf("%s/%s/%s", logsDir, t.Name(), containerName)
if err := os.MkdirAll(containerDir, defaultFilePerm); err != nil {
t.Logf("failed creating logs directory for container %s: %s", containerDir, err)
continue
}
logsBz, err := dockerutil.GetContainerLogs(ctx, dc, container.ID)
if err != nil {
t.Logf("failed reading logs in test cleanup: %s", err)
continue
}
logFile := fmt.Sprintf("%s/%s.log", containerDir, containerName)
if err := os.WriteFile(logFile, logsBz, defaultFilePerm); err != nil {
continue
}
t.Logf("successfully wrote log file %s", logFile)
var diagnosticFiles []string
for _, chainName := range chainNames {
diagnosticFiles = append(diagnosticFiles, chainDiagnosticAbsoluteFilePaths(chainName)...)
}
diagnosticFiles = append(diagnosticFiles, relayerDiagnosticAbsoluteFilePaths()...)
for _, absoluteFilePathInContainer := range diagnosticFiles {
localFilePath := ospath.Join(containerDir, ospath.Base(absoluteFilePathInContainer))
if err := fetchAndWriteDiagnosticsFile(ctx, dc, container.ID, localFilePath, absoluteFilePathInContainer); err != nil {
continue
}
t.Logf("successfully wrote diagnostics file %s", absoluteFilePathInContainer)
}
localFilePath := ospath.Join(containerDir, dockerInspectFileName)
if err := fetchAndWriteDockerInspectOutput(ctx, dc, container.ID, localFilePath); err != nil {
continue
}
t.Logf("successfully wrote docker inspect output")
}
}
// getContainerName returns an either the ID of the container or stripped down human-readable
// version of the name if the name is non-empty.
//
// Note: You should still always use the ID when interacting with the docker client.
func getContainerName(t *testing.T, container dockertypes.Container) string {
t.Helper()
// container will always have an id, by may not have a name.
containerName := container.ID
if len(container.Names) > 0 {
containerName = container.Names[0]
// remove the test name from the container as the folder structure will provide this
// information already.
containerName = strings.TrimRight(containerName, "-"+t.Name())
containerName = strings.TrimLeft(containerName, "/")
}
return containerName
}
// fetchAndWriteDiagnosticsFile fetches the contents of a single file from the given container id and writes
// the contents of the file to a local path provided.
func fetchAndWriteDiagnosticsFile(ctx context.Context, dc *mobycli.Client, containerID, localPath, absoluteFilePathInContainer string) error {
fileBz, err := dockerutil.GetFileContentsFromContainer(ctx, dc, containerID, absoluteFilePathInContainer)
if err != nil {
return err
}
return os.WriteFile(localPath, fileBz, defaultFilePerm)
}
// fetchAndWriteDockerInspectOutput writes the contents of docker inspect to the specified file.
func fetchAndWriteDockerInspectOutput(ctx context.Context, dc *mobycli.Client, containerID, localPath string) error {
containerJSON, err := dc.ContainerInspect(ctx, containerID)
if err != nil {
return err
}
fileBz, err := json.MarshalIndent(containerJSON, "", "\t")
if err != nil {
return err
}
return os.WriteFile(localPath, fileBz, defaultFilePerm)
}
// chainDiagnosticAbsoluteFilePaths returns a slice of absolute file paths (in the containers) which are the files that should be
// copied locally when fetching diagnostics.
func chainDiagnosticAbsoluteFilePaths(chainName string) []string {
return []string{
fmt.Sprintf("/var/cosmos-chain/%s/config/genesis.json", chainName),
fmt.Sprintf("/var/cosmos-chain/%s/config/app.toml", chainName),
fmt.Sprintf("/var/cosmos-chain/%s/config/config.toml", chainName),
fmt.Sprintf("/var/cosmos-chain/%s/config/client.toml", chainName),
}
}
// relayerDiagnosticAbsoluteFilePaths returns a slice of absolute file paths (in the containers) which are the files that should be
// copied locally when fetching diagnostics.
func relayerDiagnosticAbsoluteFilePaths() []string {
return []string{
"/home/hermes/.hermes/config.toml",
}
}