From cf4b48ed6b7a064e8ca6f9b818982d7c77941875 Mon Sep 17 00:00:00 2001 From: Alexander Pavel Date: Tue, 2 Oct 2018 14:04:47 -0700 Subject: [PATCH 1/4] commands/{build,cmdutil},pkg/generator: remove build.sh This commit moves all functionality of build.sh into the build.go file to embed the functionality into the binary. It also allows the binary to generate the files needed when making tests (Dockerfile and go-test.sh) in case someone tries to build testing enabled images using a project made before that functionality was added. See #541 --- commands/operator-sdk/cmd/build.go | 27 +++++++++++++++++++---- commands/operator-sdk/cmd/cmdutil/util.go | 24 ++++++++++++++++++++ pkg/generator/generator.go | 10 +++++++-- 3 files changed, 55 insertions(+), 6 deletions(-) diff --git a/commands/operator-sdk/cmd/build.go b/commands/operator-sdk/cmd/build.go index 11269d671f..c33b640b5a 100644 --- a/commands/operator-sdk/cmd/build.go +++ b/commands/operator-sdk/cmd/build.go @@ -22,6 +22,7 @@ import ( "log" "os" "os/exec" + "path/filepath" "strings" "github.com/operator-framework/operator-sdk/commands/operator-sdk/cmd/cmdutil" @@ -144,12 +145,18 @@ func buildFunc(cmd *cobra.Command, args []string) { cmdError.ExitWithError(cmdError.ExitBadArgs, fmt.Errorf("build command needs exactly 1 argument")) } + cmdutil.MustInProjectRoot() + goBuildEnv := append(os.Environ(), "GOOS=linux", "GOARCH=amd64", "CGO_ENABLED=0") + wd, err := os.Getwd() + if err != nil { + cmdError.ExitWithError(cmdError.ExitError, fmt.Errorf("could not identify current working directory: %v", err)) + } + // Don't need to buld go code if Ansible Operator if mainExists() { - bcmd := exec.Command(build) - bcmd.Env = append(os.Environ(), fmt.Sprintf("TEST_LOCATION=%v", testLocationBuild)) - bcmd.Env = append(bcmd.Env, fmt.Sprintf("ENABLE_TESTS=%v", enableTests)) - o, err := bcmd.CombinedOutput() + buildCmd := exec.Command("go", "build", "-o", filepath.Join(wd, "tmp/_output/bin", filepath.Base(wd)), filepath.Join(cmdutil.GetCurrPkg(), "cmd", filepath.Base(wd))) + buildCmd.Env = goBuildEnv + o, err := buildCmd.CombinedOutput() if err != nil { cmdError.ExitWithError(cmdError.ExitError, fmt.Errorf("failed to build: (%v)", string(o))) } @@ -173,6 +180,18 @@ func buildFunc(cmd *cobra.Command, args []string) { fmt.Fprintln(os.Stdout, string(o)) if enableTests { + buildTestCmd := exec.Command("go", "test", "-c", "-o", filepath.Join(wd, "tmp/_output/bin", filepath.Base(wd)+"-test"), testLocationBuild+"/...") + buildTestCmd.Env = goBuildEnv + o, err := buildTestCmd.CombinedOutput() + if err != nil { + cmdError.ExitWithError(cmdError.ExitError, fmt.Errorf("failed to build: (%v)", string(o))) + } + fmt.Fprintln(os.Stdout, string(o)) + // if a user is using an older sdk repo as their library, make sure they have required build files + _, err = os.Stat("tmp/build/test-framework/Dockerfile") + if err != nil { + generator.RenderTestingContainerFiles(filepath.Join(wd, "tmp/build"), filepath.Base(wd)) + } testDbcmd := exec.Command("docker", "build", ".", "-f", "tmp/build/test-framework/Dockerfile", "-t", image, "--build-arg", "NAMESPACEDMAN="+namespacedManBuild, "--build-arg", "BASEIMAGE="+baseImageName) o, err = testDbcmd.CombinedOutput() if err != nil { diff --git a/commands/operator-sdk/cmd/cmdutil/util.go b/commands/operator-sdk/cmd/cmdutil/util.go index 29816eefc8..b109799d7e 100644 --- a/commands/operator-sdk/cmd/cmdutil/util.go +++ b/commands/operator-sdk/cmd/cmdutil/util.go @@ -15,9 +15,13 @@ package cmdutil import ( + "errors" "fmt" + gobuild "go/build" "io/ioutil" "os" + "path/filepath" + "strings" cmdError "github.com/operator-framework/operator-sdk/commands/operator-sdk/error" "github.com/operator-framework/operator-sdk/pkg/generator" @@ -49,3 +53,23 @@ func GetConfig() *generator.Config { } return c } + +// GetCurrPkg returns the current directory's import path +// e.g: "github.com/example-inc/app-operator" +func GetCurrPkg() string { + gopath := os.Getenv("GOPATH") + if len(gopath) == 0 { + gopath = gobuild.Default.GOPATH + } + goSrc := filepath.Join(gopath, "src") + + wd, err := os.Getwd() + if err != nil { + cmdError.ExitWithError(cmdError.ExitError, fmt.Errorf("failed to get working directory: (%v)", err)) + } + if !strings.HasPrefix(filepath.Dir(wd), goSrc) { + cmdError.ExitWithError(cmdError.ExitError, errors.New("must run from gopath")) + } + currPkg := strings.Replace(wd, goSrc+string(filepath.Separator), "", 1) + return currPkg +} diff --git a/pkg/generator/generator.go b/pkg/generator/generator.go index a10eb5999a..c320e5b570 100644 --- a/pkg/generator/generator.go +++ b/pkg/generator/generator.go @@ -532,11 +532,17 @@ func renderBuildFiles(buildDir, repoPath, projectName, operatorType string, gene return err } + return RenderTestingContainerFiles(buildDir, projectName) +} + +func RenderTestingContainerFiles(buildDir, projectName string) error { + dTd := tmplData{ + ProjectName: projectName, + } if err := renderWriteFile(filepath.Join(buildDir, "test-framework", testingDockerfile), "tmp/build/test-framework/Dockerfile", testingDockerFileTmpl, dTd); err != nil { return err } - - buf = &bytes.Buffer{} + buf := &bytes.Buffer{} if err := renderFile(buf, filepath.Join(buildDir, goTest), goTestScript, tmplData{}); err != nil { return err } From 038cfcff6eaa45127a1643bd371907f116ecfa99 Mon Sep 17 00:00:00 2001 From: Alexander Pavel Date: Tue, 2 Oct 2018 14:12:06 -0700 Subject: [PATCH 2/4] pkg/generator: remove build.sh generation --- pkg/generator/generator.go | 12 ------------ pkg/generator/templates.go | 24 ------------------------ 2 files changed, 36 deletions(-) diff --git a/pkg/generator/generator.go b/pkg/generator/generator.go index c320e5b570..1d11ffc142 100644 --- a/pkg/generator/generator.go +++ b/pkg/generator/generator.go @@ -503,22 +503,10 @@ func (g *Generator) renderVersion() error { } func renderBuildFiles(buildDir, repoPath, projectName, operatorType string, generatePlaybook bool) error { - buf := &bytes.Buffer{} - bTd := tmplData{ - ProjectName: projectName, - RepoPath: repoPath, - } - var dockerFileTmplName string switch operatorType { case goOperatorType: dockerFileTmplName = dockerFileTmpl - if err := renderFile(buf, "tmp/build/build.sh", buildTmpl, bTd); err != nil { - return err - } - if err := writeFileAndPrint(filepath.Join(buildDir, build), buf.Bytes(), defaultExecFileMode); err != nil { - return err - } case ansibleOperatorType: dockerFileTmplName = dockerFileAnsibleTmpl } diff --git a/pkg/generator/templates.go b/pkg/generator/templates.go index 5e4126849c..f1774af24a 100644 --- a/pkg/generator/templates.go +++ b/pkg/generator/templates.go @@ -551,30 +551,6 @@ deepcopy \ {{.APIDirName}}:{{.Version}} \ --go-header-file "./tmp/codegen/boilerplate.go.txt" ` -const buildTmpl = `#!/usr/bin/env bash - -set -o errexit -set -o nounset -set -o pipefail - -if ! which go > /dev/null; then - echo "golang needs to be installed" - exit 1 -fi - -BIN_DIR="$(pwd)/tmp/_output/bin" -mkdir -p ${BIN_DIR} -PROJECT_NAME="{{.ProjectName}}" -REPO_PATH="{{.RepoPath}}" -BUILD_PATH="${REPO_PATH}/cmd/${PROJECT_NAME}" -TEST_PATH="${REPO_PATH}/${TEST_LOCATION}" -echo "building "${PROJECT_NAME}"..." -GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o ${BIN_DIR}/${PROJECT_NAME} $BUILD_PATH -if $ENABLE_TESTS ; then - echo "building "${PROJECT_NAME}-test"..." - GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go test -c -o ${BIN_DIR}/${PROJECT_NAME}-test $TEST_PATH -fi -` const goTestScript = `#!/bin/sh From f045683758ed789bb98145595dbfd8dab4e96b16 Mon Sep 17 00:00:00 2001 From: Alexander Pavel Date: Tue, 2 Oct 2018 14:17:18 -0700 Subject: [PATCH 3/4] pkg/generator: fix unit tests --- pkg/generator/generator_test.go | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/pkg/generator/generator_test.go b/pkg/generator/generator_test.go index b5a619ff06..17e1655eea 100644 --- a/pkg/generator/generator_test.go +++ b/pkg/generator/generator_test.go @@ -593,21 +593,6 @@ COPY watches.yaml ${HOME}/watches.yaml func TestGenBuild(t *testing.T) { buf := &bytes.Buffer{} - bTd := tmplData{ - ProjectName: appProjectName, - RepoPath: appRepoPath, - } - if err := renderFile(buf, "tmp/build/build.sh", buildTmpl, bTd); err != nil { - t.Error(err) - return - } - if buildExp != buf.String() { - dmp := diffmatchpatch.New() - diffs := dmp.DiffMain(buildExp, buf.String(), false) - t.Errorf("\nTest failed. Below is the diff of the expected vs actual results.\nRed text is missing and green text is extra.\n\n" + dmp.DiffPrettyText(diffs)) - } - - buf = &bytes.Buffer{} dTd := tmplData{ ProjectName: appProjectName, } From 37acb8059905afb3788c09e0499affdf2189b561 Mon Sep 17 00:00:00 2001 From: Alexander Pavel Date: Tue, 2 Oct 2018 15:49:15 -0700 Subject: [PATCH 4/4] commands/.../build.go: use log.fatal for build errors --- commands/operator-sdk/cmd/build.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/commands/operator-sdk/cmd/build.go b/commands/operator-sdk/cmd/build.go index c33b640b5a..a060c7e876 100644 --- a/commands/operator-sdk/cmd/build.go +++ b/commands/operator-sdk/cmd/build.go @@ -158,7 +158,7 @@ func buildFunc(cmd *cobra.Command, args []string) { buildCmd.Env = goBuildEnv o, err := buildCmd.CombinedOutput() if err != nil { - cmdError.ExitWithError(cmdError.ExitError, fmt.Errorf("failed to build: (%v)", string(o))) + log.Fatalf("failed to build operator binary: %v (%v)", err, string(o)) } fmt.Fprintln(os.Stdout, string(o)) } @@ -184,7 +184,7 @@ func buildFunc(cmd *cobra.Command, args []string) { buildTestCmd.Env = goBuildEnv o, err := buildTestCmd.CombinedOutput() if err != nil { - cmdError.ExitWithError(cmdError.ExitError, fmt.Errorf("failed to build: (%v)", string(o))) + log.Fatalf("failed to build test binary: %v (%v)", err, string(o)) } fmt.Fprintln(os.Stdout, string(o)) // if a user is using an older sdk repo as their library, make sure they have required build files