github.skymusic.top/operator-framework/operator-sdk@v0.8.2/cmd/operator-sdk/build/cmd.go (about) 1 // Copyright 2018 The Operator-SDK Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package build 16 17 import ( 18 "fmt" 19 "os" 20 "os/exec" 21 "path/filepath" 22 "strings" 23 24 "github.com/operator-framework/operator-sdk/internal/pkg/scaffold" 25 "github.com/operator-framework/operator-sdk/internal/util/projutil" 26 27 log "github.com/sirupsen/logrus" 28 "github.com/spf13/cobra" 29 ) 30 31 var ( 32 imageBuildArgs string 33 imageBuilder string 34 ) 35 36 func NewCmd() *cobra.Command { 37 buildCmd := &cobra.Command{ 38 Use: "build <image>", 39 Short: "Compiles code and builds artifacts", 40 Long: `The operator-sdk build command compiles the code, builds the executables, 41 and generates Kubernetes manifests. 42 43 <image> is the container image to be built, e.g. "quay.io/example/operator:v0.0.1". 44 This image will be automatically set in the deployment manifests. 45 46 After build completes, the image would be built locally in docker. Then it needs to 47 be pushed to remote registry. 48 For example: 49 $ operator-sdk build quay.io/example/operator:v0.0.1 50 $ docker push quay.io/example/operator:v0.0.1 51 `, 52 RunE: buildFunc, 53 } 54 buildCmd.Flags().StringVar(&imageBuildArgs, "image-build-args", "", "Extra image build arguments as one string such as \"--build-arg https_proxy=$https_proxy\"") 55 buildCmd.Flags().StringVar(&imageBuilder, "image-builder", "docker", "Tool to build OCI images. One of: [docker, buildah]") 56 return buildCmd 57 } 58 59 func createBuildCommand(imageBuilder, context, dockerFile, image string, imageBuildArgs ...string) (*exec.Cmd, error) { 60 var args []string 61 switch imageBuilder { 62 case "docker": 63 args = append(args, "build", "-f", dockerFile, "-t", image) 64 case "buildah": 65 args = append(args, "bud", "--format=docker", "-f", dockerFile, "-t", image) 66 default: 67 return nil, fmt.Errorf("%s is not supported image builder", imageBuilder) 68 } 69 70 for _, bargs := range imageBuildArgs { 71 if bargs != "" { 72 splitArgs := strings.Fields(bargs) 73 args = append(args, splitArgs...) 74 } 75 } 76 77 args = append(args, context) 78 79 return exec.Command(imageBuilder, args...), nil 80 } 81 82 func buildFunc(cmd *cobra.Command, args []string) error { 83 if len(args) != 1 { 84 return fmt.Errorf("command %s requires exactly one argument", cmd.CommandPath()) 85 } 86 87 projutil.MustInProjectRoot() 88 goBuildEnv := append(os.Environ(), "GOOS=linux", "GOARCH=amd64") 89 90 // If CGO_ENABLED is not set, set it to '0'. 91 if _, ok := os.LookupEnv("CGO_ENABLED"); !ok { 92 goBuildEnv = append(goBuildEnv, "CGO_ENABLED=0") 93 } 94 95 trimPath := os.ExpandEnv("all=-trimpath=${GOPATH}") 96 goTrimFlags := []string{"-gcflags", trimPath, "-asmflags", trimPath} 97 absProjectPath := projutil.MustGetwd() 98 projectName := filepath.Base(absProjectPath) 99 100 // Don't need to build Go code if a non-Go Operator. 101 if projutil.IsOperatorGo() { 102 opts := projutil.GoCmdOptions{ 103 BinName: filepath.Join(absProjectPath, scaffold.BuildBinDir, projectName), 104 PackagePath: filepath.Join(projutil.CheckAndGetProjectGoPkg(), scaffold.ManagerDir), 105 Args: goTrimFlags, 106 Env: goBuildEnv, 107 GoMod: projutil.IsDepManagerGoMod(), 108 } 109 if err := projutil.GoBuild(opts); err != nil { 110 return fmt.Errorf("failed to build operator binary: (%v)", err) 111 } 112 } 113 114 image := args[0] 115 116 log.Infof("Building OCI image %s", image) 117 118 buildCmd, err := createBuildCommand(imageBuilder, ".", "build/Dockerfile", image, imageBuildArgs) 119 if err != nil { 120 return err 121 } 122 123 if err := projutil.ExecCmd(buildCmd); err != nil { 124 return fmt.Errorf("failed to output build image %s: (%v)", image, err) 125 } 126 127 log.Info("Operator build complete.") 128 return nil 129 }