From 222b8688d8e27bbe7809f313f4a757845d0e4e7a Mon Sep 17 00:00:00 2001 From: vimystic <122659254+vimystic@users.noreply.github.com> Date: Mon, 28 Aug 2023 03:05:08 -0600 Subject: [PATCH 1/3] Use unique names for relayer images & cleanup when purpose served --- interchaintest/client_threshold_test.go | 13 +++++++----- interchaintest/docker.go | 28 ++++++++++++++++++++++--- interchaintest/ibc_test.go | 24 +++++++++++++-------- interchaintest/multi_channel_test.go | 6 ++++-- interchaintest/relayer_override_test.go | 6 ++++-- 5 files changed, 56 insertions(+), 21 deletions(-) diff --git a/interchaintest/client_threshold_test.go b/interchaintest/client_threshold_test.go index bc6e22a12..3791a11ab 100644 --- a/interchaintest/client_threshold_test.go +++ b/interchaintest/client_threshold_test.go @@ -42,7 +42,8 @@ func TestScenarioClientThresholdUpdate(t *testing.T) { g0, g1 := chains[0], chains[1] client, network := interchaintest.DockerSetup(t) - relayerinterchaintest.BuildRelayerImage(t) + uuid := relayerinterchaintest.UniqueRelayerImageName() + relayerinterchaintest.BuildRelayerImage(t, uuid) // Relayer is set with "--time-threshold 5m" // The client being created below also has a trusting period of 5m. @@ -50,7 +51,7 @@ func TestScenarioClientThresholdUpdate(t *testing.T) { r := interchaintest.NewBuiltinRelayerFactory( ibc.CosmosRly, zaptest.NewLogger(t), - interchaintestrelayer.CustomDockerImage(relayerinterchaintest.RelayerImageName, "latest", "100:1000"), + interchaintestrelayer.CustomDockerImage(uuid, "latest", "100:1000"), interchaintestrelayer.ImagePull(false), interchaintestrelayer.StartupFlags("--time-threshold", "20s"), ).Build(t, client, network) @@ -102,6 +103,7 @@ func TestScenarioClientThresholdUpdate(t *testing.T) { require.NoError(t, r.StartRelayer(ctx, eRep, ibcPath)) t.Cleanup(func() { _ = r.StopRelayer(ctx, eRep) + relayerinterchaintest.DestroyRelayerImage(t, uuid) }) const heightOffset = 10 @@ -164,15 +166,16 @@ func TestScenarioClientTrustingPeriodUpdate(t *testing.T) { g0, g1 := chains[0], chains[1] client, network := interchaintest.DockerSetup(t) - relayerinterchaintest.BuildRelayerImage(t) + uuid := relayerinterchaintest.UniqueRelayerImageName() + relayerinterchaintest.BuildRelayerImage(t, uuid) logger := zaptest.NewLogger(t) // Relayer is set with "--time-threshold 0" // The Relayer should NOT continuously update clients r := interchaintest.NewBuiltinRelayerFactory( ibc.CosmosRly, - logger, - interchaintestrelayer.CustomDockerImage(relayerinterchaintest.RelayerImageName, "latest", "100:1000"), + zaptest.NewLogger(t), + interchaintestrelayer.CustomDockerImage(uuid, "latest", "100:1000"), interchaintestrelayer.ImagePull(false), ).Build(t, client, network) diff --git a/interchaintest/docker.go b/interchaintest/docker.go index d44f35cc7..26d3d0f71 100644 --- a/interchaintest/docker.go +++ b/interchaintest/docker.go @@ -12,11 +12,12 @@ import ( dockertypes "github.com/docker/docker/api/types" "github.com/docker/docker/pkg/archive" + "github.com/google/uuid" "github.com/moby/moby/client" "github.com/stretchr/testify/require" ) -const RelayerImageName = "interchaintestrelayer" +const RelayerImagePrefix = "interchaintestrelayer" type dockerLogLine struct { Stream string `json:"stream"` @@ -29,7 +30,15 @@ type dockerErrorDetail struct { Message string `json:"message"` } -func BuildRelayerImage(t *testing.T) { +func UniqueRelayerImageName() string { + uuid, err := uuid.NewRandom() + if err != nil { + fmt.Printf("Failed to generate UUID: %v\n", err) + } + return RelayerImagePrefix + uuid.String()[:6] +} + +func BuildRelayerImage(t *testing.T, uniquestr string) { _, b, _, _ := runtime.Caller(0) basepath := filepath.Join(filepath.Dir(b), "..") @@ -41,7 +50,7 @@ func BuildRelayerImage(t *testing.T) { res, err := cli.ImageBuild(context.Background(), tar, dockertypes.ImageBuildOptions{ Dockerfile: "local.Dockerfile", - Tags: []string{RelayerImageName}, + Tags: []string{uniquestr}, }) require.NoError(t, err, "error building docker image") @@ -49,6 +58,19 @@ func BuildRelayerImage(t *testing.T) { handleDockerBuildOutput(t, res.Body) } +func DestroyRelayerImage(t *testing.T, uniquestr string) { + // Create a Docker client + cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) + require.NoError(t, err, "error building docker client") + + // Remove the Docker image using the provided tag (uniquestr) + _, err = cli.ImageRemove(context.Background(), uniquestr, dockertypes.ImageRemoveOptions{ + Force: true, // Force remove the image + PruneChildren: true, // Remove all child images + }) + require.NoError(t, err, "error removing docker image") +} + func handleDockerBuildOutput(t *testing.T, body io.Reader) { var logLine dockerLogLine diff --git a/interchaintest/ibc_test.go b/interchaintest/ibc_test.go index 6ee722104..75b2b2556 100644 --- a/interchaintest/ibc_test.go +++ b/interchaintest/ibc_test.go @@ -21,7 +21,7 @@ import ( // so it uses only one pair of chains. // // The canonical set of test chains are defined in the interchaintest repository. -func interchaintestConformance(t *testing.T, rf interchaintest.RelayerFactory) { +func interchaintestConformance(t *testing.T, rf interchaintest.RelayerFactory, uuid string) { cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{ {Name: "gaia", Version: "v7.0.1", ChainConfig: ibc.ChainConfig{ChainID: "cosmoshub-1004"}}, {Name: "osmosis", Version: "v7.2.0", ChainConfig: ibc.ChainConfig{ChainID: "osmosis-1001"}}, @@ -33,13 +33,16 @@ func interchaintestConformance(t *testing.T, rf interchaintest.RelayerFactory) { []interchaintest.RelayerFactory{rf}, testreporter.NewNopReporter(), ) + if uuid != "" { + relayerinterchaintest.DestroyRelayerImage(t, uuid) + } } // TestRelayerInProcess runs the interchaintest conformance tests against // the current state of this relayer implementation running in process. func TestRelayerInProcess(t *testing.T) { t.Parallel() - interchaintestConformance(t, relayerinterchaintest.RelayerFactory{}) + interchaintestConformance(t, relayerinterchaintest.RelayerFactory{}, "") } // TestRelayerDockerEventProcessor runs the interchaintest conformance tests against @@ -48,15 +51,17 @@ func TestRelayerInProcess(t *testing.T) { func TestRelayerDockerEventProcessor(t *testing.T) { t.Parallel() + uuid := relayerinterchaintest.UniqueRelayerImageName() + relayerinterchaintest.BuildRelayerImage(t, uuid) rf := interchaintest.NewBuiltinRelayerFactory( ibc.CosmosRly, zaptest.NewLogger(t), - interchaintestrelayer.CustomDockerImage(relayerinterchaintest.RelayerImageName, "latest", "100:1000"), + interchaintestrelayer.CustomDockerImage(uuid, "latest", "100:1000"), interchaintestrelayer.ImagePull(false), interchaintestrelayer.StartupFlags("--processor", "events", "--block-history", "100"), ) - interchaintestConformance(t, rf) + interchaintestConformance(t, rf, uuid) } // TestRelayerDockerLegacyProcessor runs the interchaintest conformance tests against @@ -64,17 +69,18 @@ func TestRelayerDockerEventProcessor(t *testing.T) { // Relayer runs using the legacy processor. func TestRelayerDockerLegacyProcessor(t *testing.T) { t.Parallel() - relayerinterchaintest.BuildRelayerImage(t) + uuid := relayerinterchaintest.UniqueRelayerImageName() + relayerinterchaintest.BuildRelayerImage(t, uuid) rf := interchaintest.NewBuiltinRelayerFactory( ibc.CosmosRly, zaptest.NewLogger(t), - interchaintestrelayer.CustomDockerImage(relayerinterchaintest.RelayerImageName, "latest", "100:1000"), + interchaintestrelayer.CustomDockerImage(uuid, "latest", "100:1000"), interchaintestrelayer.ImagePull(false), interchaintestrelayer.StartupFlags("--processor", "legacy"), ) - interchaintestConformance(t, rf) + interchaintestConformance(t, rf, uuid) } // TestRelayerEventProcessor runs the interchaintest conformance tests against @@ -86,7 +92,7 @@ func TestRelayerEventProcessor(t *testing.T) { interchaintestConformance(t, relayerinterchaintest.NewRelayerFactory(relayerinterchaintest.RelayerConfig{ Processor: relayer.ProcessorEvents, InitialBlockHistory: 0, - })) + }), "") } // TestRelayerLegacyProcessor runs the interchaintest conformance tests against @@ -97,5 +103,5 @@ func TestRelayerLegacyProcessor(t *testing.T) { interchaintestConformance(t, relayerinterchaintest.NewRelayerFactory(relayerinterchaintest.RelayerConfig{ Processor: relayer.ProcessorLegacy, - })) + }), "") } diff --git a/interchaintest/multi_channel_test.go b/interchaintest/multi_channel_test.go index 6904f5751..6a5ed136c 100644 --- a/interchaintest/multi_channel_test.go +++ b/interchaintest/multi_channel_test.go @@ -18,13 +18,14 @@ import ( ) func TestMultipleChannelsOneConnection(t *testing.T) { - relayerinterchaintest.BuildRelayerImage(t) + uuid := relayerinterchaintest.UniqueRelayerImageName() + relayerinterchaintest.BuildRelayerImage(t, uuid) client, network := interchaintest.DockerSetup(t) r := interchaintest.NewBuiltinRelayerFactory( ibc.CosmosRly, zaptest.NewLogger(t), - interchaintestrelayer.CustomDockerImage(relayerinterchaintest.RelayerImageName, "latest", "100:1000"), + interchaintestrelayer.CustomDockerImage(uuid, "latest", "100:1000"), interchaintestrelayer.ImagePull(false), ).Build(t, client, network) @@ -109,6 +110,7 @@ func TestMultipleChannelsOneConnection(t *testing.T) { if err != nil { t.Logf("an error occured while stopping the relayer: %s", err) } + relayerinterchaintest.DestroyRelayerImage(t, uuid) }, ) diff --git a/interchaintest/relayer_override_test.go b/interchaintest/relayer_override_test.go index 2885c21ff..8f663c957 100644 --- a/interchaintest/relayer_override_test.go +++ b/interchaintest/relayer_override_test.go @@ -23,13 +23,14 @@ import ( // is a client-id present in the relative path config. If the override flag is present, the relayer should always // attempt to create a new light client and then overwrite the config file if successful. func TestClientOverrideFlag(t *testing.T) { - relayerinterchaintest.BuildRelayerImage(t) + uuid := relayerinterchaintest.UniqueRelayerImageName() + relayerinterchaintest.BuildRelayerImage(t, uuid) client, network := interchaintest.DockerSetup(t) r := interchaintest.NewBuiltinRelayerFactory( ibc.CosmosRly, zaptest.NewLogger(t), - interchaintestrelayer.CustomDockerImage(relayerinterchaintest.RelayerImageName, "latest", "100:1000"), + interchaintestrelayer.CustomDockerImage(uuid, "latest", "100:1000"), interchaintestrelayer.ImagePull(false), ).Build(t, client, network) @@ -95,6 +96,7 @@ func TestClientOverrideFlag(t *testing.T) { if err != nil { t.Logf("an error occured while stopping the relayer: %s", err) } + relayerinterchaintest.DestroyRelayerImage(t, uuid) }, ) From 920d6b1d43ae1e9fd5775f3880a9422eac1b52ed Mon Sep 17 00:00:00 2001 From: vimystic <122659254+vimystic@users.noreply.github.com> Date: Tue, 29 Aug 2023 09:36:16 -0600 Subject: [PATCH 2/3] move random tag generation and teardown image to within BuildRelayerImage --- interchaintest/client_threshold_test.go | 13 +++++-------- interchaintest/docker.go | 21 ++++++++++++++------- interchaintest/ibc_test.go | 25 ++++++++++--------------- interchaintest/multi_channel_test.go | 6 ++---- interchaintest/relayer_override_test.go | 6 ++---- 5 files changed, 33 insertions(+), 38 deletions(-) diff --git a/interchaintest/client_threshold_test.go b/interchaintest/client_threshold_test.go index 3791a11ab..fd77f70db 100644 --- a/interchaintest/client_threshold_test.go +++ b/interchaintest/client_threshold_test.go @@ -42,8 +42,7 @@ func TestScenarioClientThresholdUpdate(t *testing.T) { g0, g1 := chains[0], chains[1] client, network := interchaintest.DockerSetup(t) - uuid := relayerinterchaintest.UniqueRelayerImageName() - relayerinterchaintest.BuildRelayerImage(t, uuid) + image := relayerinterchaintest.BuildRelayerImage(t) // Relayer is set with "--time-threshold 5m" // The client being created below also has a trusting period of 5m. @@ -51,7 +50,7 @@ func TestScenarioClientThresholdUpdate(t *testing.T) { r := interchaintest.NewBuiltinRelayerFactory( ibc.CosmosRly, zaptest.NewLogger(t), - interchaintestrelayer.CustomDockerImage(uuid, "latest", "100:1000"), + interchaintestrelayer.CustomDockerImage(image, "latest", "100:1000"), interchaintestrelayer.ImagePull(false), interchaintestrelayer.StartupFlags("--time-threshold", "20s"), ).Build(t, client, network) @@ -103,7 +102,6 @@ func TestScenarioClientThresholdUpdate(t *testing.T) { require.NoError(t, r.StartRelayer(ctx, eRep, ibcPath)) t.Cleanup(func() { _ = r.StopRelayer(ctx, eRep) - relayerinterchaintest.DestroyRelayerImage(t, uuid) }) const heightOffset = 10 @@ -166,16 +164,15 @@ func TestScenarioClientTrustingPeriodUpdate(t *testing.T) { g0, g1 := chains[0], chains[1] client, network := interchaintest.DockerSetup(t) - uuid := relayerinterchaintest.UniqueRelayerImageName() - relayerinterchaintest.BuildRelayerImage(t, uuid) + image := relayerinterchaintest.BuildRelayerImage(t) logger := zaptest.NewLogger(t) // Relayer is set with "--time-threshold 0" // The Relayer should NOT continuously update clients r := interchaintest.NewBuiltinRelayerFactory( ibc.CosmosRly, - zaptest.NewLogger(t), - interchaintestrelayer.CustomDockerImage(uuid, "latest", "100:1000"), + logger, + interchaintestrelayer.CustomDockerImage(image, "latest", "100:1000"), interchaintestrelayer.ImagePull(false), ).Build(t, client, network) diff --git a/interchaintest/docker.go b/interchaintest/docker.go index 26d3d0f71..3b98aea1c 100644 --- a/interchaintest/docker.go +++ b/interchaintest/docker.go @@ -30,15 +30,15 @@ type dockerErrorDetail struct { Message string `json:"message"` } -func UniqueRelayerImageName() string { +func uniqueRelayerImageName() (string, error) { uuid, err := uuid.NewRandom() if err != nil { fmt.Printf("Failed to generate UUID: %v\n", err) + return "", err } - return RelayerImagePrefix + uuid.String()[:6] + return RelayerImagePrefix + uuid.String()[:6], nil } - -func BuildRelayerImage(t *testing.T, uniquestr string) { +func BuildRelayerImage(t *testing.T) string { _, b, _, _ := runtime.Caller(0) basepath := filepath.Join(filepath.Dir(b), "..") @@ -48,23 +48,30 @@ func BuildRelayerImage(t *testing.T, uniquestr string) { cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) require.NoError(t, err, "error building docker client") + image, err := uniqueRelayerImageName() + require.NoError(t, err, "error generating unique tag for docker image") + res, err := cli.ImageBuild(context.Background(), tar, dockertypes.ImageBuildOptions{ Dockerfile: "local.Dockerfile", - Tags: []string{uniquestr}, + Tags: []string{image}, }) require.NoError(t, err, "error building docker image") defer res.Body.Close() + t.Cleanup(func() { + destroyRelayerImage(t, image) + }) handleDockerBuildOutput(t, res.Body) + return image } -func DestroyRelayerImage(t *testing.T, uniquestr string) { +func destroyRelayerImage(t *testing.T, image string) { // Create a Docker client cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) require.NoError(t, err, "error building docker client") // Remove the Docker image using the provided tag (uniquestr) - _, err = cli.ImageRemove(context.Background(), uniquestr, dockertypes.ImageRemoveOptions{ + _, err = cli.ImageRemove(context.Background(), image, dockertypes.ImageRemoveOptions{ Force: true, // Force remove the image PruneChildren: true, // Remove all child images }) diff --git a/interchaintest/ibc_test.go b/interchaintest/ibc_test.go index 75b2b2556..81140ba74 100644 --- a/interchaintest/ibc_test.go +++ b/interchaintest/ibc_test.go @@ -21,7 +21,7 @@ import ( // so it uses only one pair of chains. // // The canonical set of test chains are defined in the interchaintest repository. -func interchaintestConformance(t *testing.T, rf interchaintest.RelayerFactory, uuid string) { +func interchaintestConformance(t *testing.T, rf interchaintest.RelayerFactory) { cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{ {Name: "gaia", Version: "v7.0.1", ChainConfig: ibc.ChainConfig{ChainID: "cosmoshub-1004"}}, {Name: "osmosis", Version: "v7.2.0", ChainConfig: ibc.ChainConfig{ChainID: "osmosis-1001"}}, @@ -33,16 +33,13 @@ func interchaintestConformance(t *testing.T, rf interchaintest.RelayerFactory, u []interchaintest.RelayerFactory{rf}, testreporter.NewNopReporter(), ) - if uuid != "" { - relayerinterchaintest.DestroyRelayerImage(t, uuid) - } } // TestRelayerInProcess runs the interchaintest conformance tests against // the current state of this relayer implementation running in process. func TestRelayerInProcess(t *testing.T) { t.Parallel() - interchaintestConformance(t, relayerinterchaintest.RelayerFactory{}, "") + interchaintestConformance(t, relayerinterchaintest.RelayerFactory{}) } // TestRelayerDockerEventProcessor runs the interchaintest conformance tests against @@ -51,17 +48,16 @@ func TestRelayerInProcess(t *testing.T) { func TestRelayerDockerEventProcessor(t *testing.T) { t.Parallel() - uuid := relayerinterchaintest.UniqueRelayerImageName() - relayerinterchaintest.BuildRelayerImage(t, uuid) + image := relayerinterchaintest.BuildRelayerImage(t) rf := interchaintest.NewBuiltinRelayerFactory( ibc.CosmosRly, zaptest.NewLogger(t), - interchaintestrelayer.CustomDockerImage(uuid, "latest", "100:1000"), + interchaintestrelayer.CustomDockerImage(image, "latest", "100:1000"), interchaintestrelayer.ImagePull(false), interchaintestrelayer.StartupFlags("--processor", "events", "--block-history", "100"), ) - interchaintestConformance(t, rf, uuid) + interchaintestConformance(t, rf) } // TestRelayerDockerLegacyProcessor runs the interchaintest conformance tests against @@ -69,18 +65,17 @@ func TestRelayerDockerEventProcessor(t *testing.T) { // Relayer runs using the legacy processor. func TestRelayerDockerLegacyProcessor(t *testing.T) { t.Parallel() - uuid := relayerinterchaintest.UniqueRelayerImageName() - relayerinterchaintest.BuildRelayerImage(t, uuid) + image := relayerinterchaintest.BuildRelayerImage(t) rf := interchaintest.NewBuiltinRelayerFactory( ibc.CosmosRly, zaptest.NewLogger(t), - interchaintestrelayer.CustomDockerImage(uuid, "latest", "100:1000"), + interchaintestrelayer.CustomDockerImage(image, "latest", "100:1000"), interchaintestrelayer.ImagePull(false), interchaintestrelayer.StartupFlags("--processor", "legacy"), ) - interchaintestConformance(t, rf, uuid) + interchaintestConformance(t, rf) } // TestRelayerEventProcessor runs the interchaintest conformance tests against @@ -92,7 +87,7 @@ func TestRelayerEventProcessor(t *testing.T) { interchaintestConformance(t, relayerinterchaintest.NewRelayerFactory(relayerinterchaintest.RelayerConfig{ Processor: relayer.ProcessorEvents, InitialBlockHistory: 0, - }), "") + })) } // TestRelayerLegacyProcessor runs the interchaintest conformance tests against @@ -103,5 +98,5 @@ func TestRelayerLegacyProcessor(t *testing.T) { interchaintestConformance(t, relayerinterchaintest.NewRelayerFactory(relayerinterchaintest.RelayerConfig{ Processor: relayer.ProcessorLegacy, - }), "") + })) } diff --git a/interchaintest/multi_channel_test.go b/interchaintest/multi_channel_test.go index 6a5ed136c..ad123f756 100644 --- a/interchaintest/multi_channel_test.go +++ b/interchaintest/multi_channel_test.go @@ -18,14 +18,13 @@ import ( ) func TestMultipleChannelsOneConnection(t *testing.T) { - uuid := relayerinterchaintest.UniqueRelayerImageName() - relayerinterchaintest.BuildRelayerImage(t, uuid) + image := relayerinterchaintest.BuildRelayerImage(t) client, network := interchaintest.DockerSetup(t) r := interchaintest.NewBuiltinRelayerFactory( ibc.CosmosRly, zaptest.NewLogger(t), - interchaintestrelayer.CustomDockerImage(uuid, "latest", "100:1000"), + interchaintestrelayer.CustomDockerImage(image, "latest", "100:1000"), interchaintestrelayer.ImagePull(false), ).Build(t, client, network) @@ -110,7 +109,6 @@ func TestMultipleChannelsOneConnection(t *testing.T) { if err != nil { t.Logf("an error occured while stopping the relayer: %s", err) } - relayerinterchaintest.DestroyRelayerImage(t, uuid) }, ) diff --git a/interchaintest/relayer_override_test.go b/interchaintest/relayer_override_test.go index 8f663c957..d729cc719 100644 --- a/interchaintest/relayer_override_test.go +++ b/interchaintest/relayer_override_test.go @@ -23,14 +23,13 @@ import ( // is a client-id present in the relative path config. If the override flag is present, the relayer should always // attempt to create a new light client and then overwrite the config file if successful. func TestClientOverrideFlag(t *testing.T) { - uuid := relayerinterchaintest.UniqueRelayerImageName() - relayerinterchaintest.BuildRelayerImage(t, uuid) + image := relayerinterchaintest.BuildRelayerImage(t) client, network := interchaintest.DockerSetup(t) r := interchaintest.NewBuiltinRelayerFactory( ibc.CosmosRly, zaptest.NewLogger(t), - interchaintestrelayer.CustomDockerImage(uuid, "latest", "100:1000"), + interchaintestrelayer.CustomDockerImage(image, "latest", "100:1000"), interchaintestrelayer.ImagePull(false), ).Build(t, client, network) @@ -96,7 +95,6 @@ func TestClientOverrideFlag(t *testing.T) { if err != nil { t.Logf("an error occured while stopping the relayer: %s", err) } - relayerinterchaintest.DestroyRelayerImage(t, uuid) }, ) From 6d1b60141ca89999a131a2c76e438a61aebee805 Mon Sep 17 00:00:00 2001 From: vimystic <122659254+vimystic@users.noreply.github.com> Date: Tue, 29 Aug 2023 11:29:25 -0600 Subject: [PATCH 3/3] fix return line --- interchaintest/docker.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interchaintest/docker.go b/interchaintest/docker.go index 3b98aea1c..384b5e4c1 100644 --- a/interchaintest/docker.go +++ b/interchaintest/docker.go @@ -33,8 +33,7 @@ type dockerErrorDetail struct { func uniqueRelayerImageName() (string, error) { uuid, err := uuid.NewRandom() if err != nil { - fmt.Printf("Failed to generate UUID: %v\n", err) - return "", err + return "", fmt.Errorf("failed to generate uuid %v", err) } return RelayerImagePrefix + uuid.String()[:6], nil }