diff --git a/hack/lib/test_lib.sh b/hack/lib/test_lib.sh index ee68081be8d..c0f12b058a3 100644 --- a/hack/lib/test_lib.sh +++ b/hack/lib/test_lib.sh @@ -48,3 +48,37 @@ function trap_add() { fatal "unable to add to trap ${trap_add_name}" done } + +# add_go_mod_replace adds a "replace" directive from $1 to $2 with an +# optional version version $3 to the current working directory's go.mod file. +function add_go_mod_replace() { + local from_path="${1:?first path in replace statement is required}" + local to_path="${2:?second path in replace statement is required}" + local version="${3:-}" + + if [[ ! -d "$to_path" && -z "$version" ]]; then + echo "second replace path $to_path requires a version be set because it is not a directory" + exit 1 + fi + if [[ ! -e go.mod ]]; then + echo "go.mod file not found in $(pwd)" + exit 1 + fi + + # If $to_path is a directory, it needs a `go.mod` file that specifies the + # module name to make the go toolchain happy. + # + # TODO: remove the below if statement once + # https://github.com/operator-framework/operator-sdk/pull/1566 is merged, + # which updates the SDK to use go modules. + if [[ -d "${to_path}" && ! -e "${to_path}/go.mod" ]]; then + echo "module ${from_path}" > "${to_path}/go.mod" + trap_add "rm ${to_path}/go.mod" EXIT + fi + # Do not use "go mod edit" so formatting stays the same. + local replace="replace ${from_path} => ${to_path}" + if [[ -n "$version" ]]; then + replace="$replace $version" + fi + echo "$replace" >> go.mod +} diff --git a/hack/tests/e2e-ansible.sh b/hack/tests/e2e-ansible.sh index 2f39dabb3a0..4cbaeb7bfb6 100755 --- a/hack/tests/e2e-ansible.sh +++ b/hack/tests/e2e-ansible.sh @@ -133,18 +133,9 @@ then exit 1 fi -# Right now, SDK projects still need a vendor directory, so run `go mod vendor` -# to pull down the deps specified by the scaffolded `go.mod` file. +add_go_mod_replace "github.com/operator-framework/operator-sdk" "$ROOTDIR" go mod vendor -# Use the local operator-sdk directory as the repo. To make the go toolchain -# happy, the directory needs a `go.mod` file that specifies the module name, -# so we need this temporary hack until we update the SDK repo itself to use -# go modules. -echo "module github.com/operator-framework/operator-sdk" > $ROOTDIR/go.mod -trap_add 'rm $ROOTDIR/go.mod' EXIT -go mod edit -replace=github.com/operator-framework/operator-sdk=$ROOTDIR - operator-sdk build "$DEST_IMAGE" deploy_operator diff --git a/hack/tests/e2e-helm.sh b/hack/tests/e2e-helm.sh index d1a8332a735..0cb6f432672 100755 --- a/hack/tests/e2e-helm.sh +++ b/hack/tests/e2e-helm.sh @@ -128,18 +128,9 @@ then exit 1 fi -# Right now, SDK projects still need a vendor directory, so run `go mod vendor` -# to pull down the deps specified by the scaffolded `go.mod` file. +add_go_mod_replace "github.com/operator-framework/operator-sdk" "$ROOTDIR" go mod vendor -# Use the local operator-sdk directory as the repo. To make the go toolchain -# happy, the directory needs a `go.mod` file that specifies the module name, -# so we need this temporary hack until we update the SDK repo itself to use -# go modules. -echo "module github.com/operator-framework/operator-sdk" > $ROOTDIR/go.mod -trap_add 'rm $ROOTDIR/go.mod' EXIT -go mod edit -replace=github.com/operator-framework/operator-sdk=$ROOTDIR - operator-sdk build "$DEST_IMAGE" deploy_operator diff --git a/test/e2e/memcached_test.go b/test/e2e/memcached_test.go index 3660fc27f2e..65040cbf965 100644 --- a/test/e2e/memcached_test.go +++ b/test/e2e/memcached_test.go @@ -17,7 +17,6 @@ package e2e import ( "bytes" "context" - "errors" "fmt" "io/ioutil" "os" @@ -35,8 +34,8 @@ import ( "github.com/operator-framework/operator-sdk/pkg/test/e2eutil" "github.com/ghodss/yaml" + "github.com/pkg/errors" "github.com/prometheus/prometheus/util/promlint" - "github.com/rogpeppe/go-internal/modfile" v1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" @@ -114,18 +113,24 @@ func TestMemcached(t *testing.T) { // stub go.mod into the local SDK repo referred to in // memcached-operator's go.mod, which allows go to recognize // the local SDK repo as a module. - sdkModPath := filepath.Join(replace.repo, "go.mod") - err = ioutil.WriteFile(sdkModPath, []byte("module "+sdkRepo), fileutil.DefaultFileMode) - if err != nil { - t.Fatalf("Failed to write main repo go.mod file: %v", err) - } - defer func() { - if err = os.RemoveAll(sdkModPath); err != nil { - t.Fatalf("Failed to remove %s: %v", sdkModPath, err) + sdkModPath := filepath.Join(filepath.FromSlash(replace.repo), "go.mod") + if _, err = os.Stat(sdkModPath); err != nil && os.IsNotExist(err) { + err = ioutil.WriteFile(sdkModPath, []byte("module "+sdkRepo), fileutil.DefaultFileMode) + if err != nil { + t.Fatalf("Failed to write main repo go.mod file: %v", err) } - }() + defer func() { + if err = os.RemoveAll(sdkModPath); err != nil { + t.Fatalf("Failed to remove %s: %v", sdkModPath, err) + } + }() + } + } + modBytes, err := insertGoModReplace(t, sdkRepo, replace.repo, replace.ref) + if err != nil { + t.Fatalf("Failed to insert go.mod replace: %v", err) } - writeGoModReplace(t, sdkRepo, replace.repo, replace.ref) + t.Logf("go.mod: %v", string(modBytes)) } cmdOut, err = exec.Command("go", "mod", "vendor").CombinedOutput() @@ -306,30 +311,21 @@ func getGoModReplace(t *testing.T, localSDKPath string) goModReplace { } } -func writeGoModReplace(t *testing.T, repo, path, sha string) { +func insertGoModReplace(t *testing.T, repo, path, sha string) ([]byte, error) { modBytes, err := ioutil.ReadFile("go.mod") if err != nil { - t.Fatalf("Failed to read go.mod: %v", err) - } - modFile, err := modfile.Parse("go.mod", modBytes, nil) - if err != nil { - t.Fatalf("Failed to parse go.mod: %v", err) - } - if err = modFile.AddReplace(repo, "", path, sha); err != nil { - s := "" - if sha != "" { - s = " " + sha - } - t.Fatalf(`Failed to add "replace %s => %s%s: %v"`, repo, path, s, err) + return nil, errors.Wrap(err, "failed to read go.mod") } - if modBytes, err = modFile.Format(); err != nil { - t.Fatalf("Failed to format go.mod: %v", err) + sdkReplace := fmt.Sprintf("replace %s => %s", repo, path) + if sha != "" { + sdkReplace = fmt.Sprintf("%s %s", sdkReplace, sha) } + modBytes = append(modBytes, []byte("\n"+sdkReplace)...) err = ioutil.WriteFile("go.mod", modBytes, fileutil.DefaultFileMode) if err != nil { - t.Fatalf("Failed to write updated go.mod: %v", err) + return nil, errors.Wrap(err, "failed to write go.mod before replacing SDK repo") } - t.Logf("go.mod: %v", string(modBytes)) + return modBytes, nil } func memcachedLeaderTest(t *testing.T, f *framework.Framework, ctx *framework.TestCtx) error {