diff options
Diffstat (limited to 'cmd/podman/build.go')
-rw-r--r-- | cmd/podman/build.go | 236 |
1 files changed, 138 insertions, 98 deletions
diff --git a/cmd/podman/build.go b/cmd/podman/build.go index 0cd1bfbe3..e40e35cb5 100644 --- a/cmd/podman/build.go +++ b/cmd/podman/build.go @@ -1,7 +1,6 @@ package main import ( - "io/ioutil" "os" "path/filepath" "strings" @@ -9,39 +8,69 @@ import ( "github.com/containers/buildah" "github.com/containers/buildah/imagebuildah" buildahcli "github.com/containers/buildah/pkg/cli" - "github.com/containers/buildah/pkg/parse" - "github.com/containers/libpod/cmd/podman/libpodruntime" - "github.com/containers/libpod/pkg/rootless" + "github.com/containers/libpod/cmd/podman/cliconfig" + "github.com/containers/libpod/pkg/adapter" + "github.com/docker/go-units" "github.com/pkg/errors" "github.com/sirupsen/logrus" - "github.com/urfave/cli" + "github.com/spf13/cobra" ) var ( - layerFlags = []cli.Flag{ - cli.BoolTFlag{ - Name: "force-rm", - Usage: "Always remove intermediate containers after a build, even if the build is unsuccessful. (default true)", - }, - cli.BoolTFlag{ - Name: "layers", - Usage: "Cache intermediate layers during build. Use BUILDAH_LAYERS environment variable to override. ", - }, - } + buildCommand cliconfig.BuildValues buildDescription = "Builds an OCI or Docker image using instructions from one\n" + "or more Dockerfiles and a specified build context directory." - buildCommand = cli.Command{ - Name: "build", - Usage: "Build an image using instructions from Dockerfiles", - Description: buildDescription, - Flags: sortFlags(append(append(buildahcli.BudFlags, layerFlags...), buildahcli.FromAndBudFlags...)), - Action: buildCmd, - ArgsUsage: "CONTEXT-DIRECTORY | URL", - SkipArgReorder: true, - OnUsageError: usageErrorHandler, + layerValues buildahcli.LayerResults + budFlagsValues buildahcli.BudResults + fromAndBudValues buildahcli.FromAndBudResults + userNSValues buildahcli.UserNSResults + namespaceValues buildahcli.NameSpaceResults + + _buildCommand = &cobra.Command{ + Use: "build", + Short: "Build an image using instructions from Dockerfiles", + Long: buildDescription, + RunE: func(cmd *cobra.Command, args []string) error { + buildCommand.InputArgs = args + buildCommand.GlobalFlags = MainGlobalOpts + buildCommand.BudResults = &budFlagsValues + buildCommand.UserNSResults = &userNSValues + buildCommand.FromAndBudResults = &fromAndBudValues + buildCommand.LayerResults = &layerValues + buildCommand.NameSpaceResults = &namespaceValues + return buildCmd(&buildCommand) + }, + Example: `podman build . + podman build --cert-dir ~/auth --creds=username:password -t imageName -f Dockerfile.simple . + podman build --layers --force-rm --tag imageName .`, } ) +func init() { + buildCommand.Command = _buildCommand + buildCommand.SetUsageTemplate(UsageTemplate()) + flags := buildCommand.Flags() + flags.SetInterspersed(false) + + budFlags := buildahcli.GetBudFlags(&budFlagsValues) + flag := budFlags.Lookup("pull-always") + flag.Value.Set("true") + flag.DefValue = "true" + layerFlags := buildahcli.GetLayerFlags(&layerValues) + flag = layerFlags.Lookup("layers") + flag.Value.Set(useLayers()) + flag.DefValue = (useLayers()) + flag = layerFlags.Lookup("force-rm") + flag.Value.Set("true") + flag.DefValue = "true" + + fromAndBugFlags := buildahcli.GetFromAndBudFlags(&fromAndBudValues, &userNSValues, &namespaceValues) + + flags.AddFlagSet(&budFlags) + flags.AddFlagSet(&layerFlags) + flags.AddFlagSet(&fromAndBugFlags) +} + func getDockerfiles(files []string) []string { var dockerfiles []string for _, f := range files { @@ -54,30 +83,30 @@ func getDockerfiles(files []string) []string { return dockerfiles } -func buildCmd(c *cli.Context) error { +func buildCmd(c *cliconfig.BuildValues) error { // The following was taken directly from containers/buildah/cmd/bud.go // TODO Find a away to vendor more of this in rather than copy from bud - output := "" tags := []string{} - if c.IsSet("tag") || c.IsSet("t") { - tags = c.StringSlice("tag") + if c.Flag("tag").Changed { + tags = c.Tag if len(tags) > 0 { output = tags[0] tags = tags[1:] } } + pullPolicy := imagebuildah.PullNever - if c.BoolT("pull") { + if c.Pull { pullPolicy = imagebuildah.PullIfMissing } - if c.Bool("pull-always") { + if c.PullAlways { pullPolicy = imagebuildah.PullAlways } args := make(map[string]string) - if c.IsSet("build-arg") { - for _, arg := range c.StringSlice("build-arg") { + if c.Flag("build-arg").Changed { + for _, arg := range c.BuildArg { av := strings.SplitN(arg, "=", 2) if len(av) > 1 { args[av[0]] = av[1] @@ -87,15 +116,15 @@ func buildCmd(c *cli.Context) error { } } - dockerfiles := getDockerfiles(c.StringSlice("file")) - format, err := getFormat(c) + dockerfiles := getDockerfiles(c.File) + format, err := getFormat(&c.PodmanCommand) if err != nil { return nil } contextDir := "" - cliArgs := c.Args() + cliArgs := c.InputArgs - layers := c.BoolT("layers") // layers for podman defaults to true + layers := c.Layers // layers for podman defaults to true // Check to see if the BUILDAH_LAYERS environment variable is set and override command-line if _, ok := os.LookupEnv("BUILDAH_LAYERS"); ok { layers = buildahcli.UseLayers() @@ -124,7 +153,7 @@ func buildCmd(c *cli.Context) error { } contextDir = absDir } - cliArgs = cliArgs.Tail() + cliArgs = Tail(cliArgs) } else { // No context directory or URL was specified. Try to use the // home of the first locally-available Dockerfile. @@ -153,30 +182,28 @@ func buildCmd(c *cli.Context) error { if len(dockerfiles) == 0 { dockerfiles = append(dockerfiles, filepath.Join(contextDir, "Dockerfile")) } - if err := parse.ValidateFlags(c, buildahcli.BudFlags); err != nil { - return err + + runtime, err := adapter.GetRuntime(&c.PodmanCommand) + if err != nil { + return errors.Wrapf(err, "could not get runtime") } runtimeFlags := []string{} - for _, arg := range c.StringSlice("runtime-flag") { + for _, arg := range c.RuntimeFlags { runtimeFlags = append(runtimeFlags, "--"+arg) } // end from buildah - runtime, err := libpodruntime.GetRuntime(c) - if err != nil { - return errors.Wrapf(err, "could not get runtime") - } defer runtime.Shutdown(false) var stdout, stderr, reporter *os.File stdout = os.Stdout stderr = os.Stderr reporter = os.Stderr - if c.IsSet("logfile") { - f, err := os.OpenFile(c.String("logfile"), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600) + if c.Flag("logfile").Changed { + f, err := os.OpenFile(c.Logfile, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600) if err != nil { - return errors.Errorf("error opening logfile %q: %v", c.String("logfile"), err) + return errors.Errorf("error opening logfile %q: %v", c.Logfile, err) } defer f.Close() logrus.SetOutput(f) @@ -185,70 +212,83 @@ func buildCmd(c *cli.Context) error { reporter = f } - systemContext, err := parse.SystemContextFromOptions(c) - if err != nil { - return errors.Wrapf(err, "error building system context") - } - systemContext.AuthFilePath = getAuthFile(c.String("authfile")) - commonOpts, err := parse.CommonBuildOptions(c) - if err != nil { - return err + var memoryLimit, memorySwap int64 + if c.Flags().Changed("memory") { + memoryLimit, err = units.RAMInBytes(c.Memory) + if err != nil { + return err + } } - namespaceOptions, networkPolicy, err := parse.NamespaceOptions(c) - if err != nil { - return errors.Wrapf(err, "error parsing namespace-related options") - } - usernsOption, idmappingOptions, err := parse.IDMappingOptions(c) - if err != nil { - return errors.Wrapf(err, "error parsing ID mapping options") + if c.Flags().Changed("memory-swap") { + memorySwap, err = units.RAMInBytes(c.MemorySwap) + if err != nil { + return err + } } - namespaceOptions.AddOrReplace(usernsOption...) - ociruntime := runtime.GetOCIRuntimePath() - if c.IsSet("runtime") { - ociruntime = c.String("runtime") + buildOpts := buildah.CommonBuildOptions{ + AddHost: c.AddHost, + CgroupParent: c.CgroupParent, + CPUPeriod: c.CPUPeriod, + CPUQuota: c.CPUQuota, + CPUShares: c.CPUShares, + CPUSetCPUs: c.CPUSetCPUs, + CPUSetMems: c.CPUSetMems, + Memory: memoryLimit, + MemorySwap: memorySwap, + ShmSize: c.ShmSize, + Ulimit: c.Ulimit, + Volumes: c.Volume, } + options := imagebuildah.BuildOptions{ - ContextDirectory: contextDir, - PullPolicy: pullPolicy, - Compression: imagebuildah.Gzip, - Quiet: c.Bool("quiet"), - SignaturePolicyPath: c.String("signature-policy"), - Args: args, - Output: output, + CommonBuildOpts: &buildOpts, AdditionalTags: tags, - Out: stdout, + Annotations: c.Annotation, + Args: args, + CNIConfigDir: c.CNIConfigDir, + CNIPluginPath: c.CNIPlugInPath, + Compression: imagebuildah.Gzip, + ContextDirectory: contextDir, + DefaultMountsFilePath: c.GlobalFlags.DefaultMountsFile, Err: stderr, + ForceRmIntermediateCtrs: c.ForceRm, + IIDFile: c.Iidfile, + Labels: c.Label, + Layers: layers, + NoCache: c.NoCache, + Out: stdout, + Output: output, + OutputFormat: format, + PullPolicy: pullPolicy, + Quiet: c.Quiet, + RemoveIntermediateCtrs: c.Rm, ReportWriter: reporter, - Runtime: ociruntime, RuntimeArgs: runtimeFlags, - OutputFormat: format, - SystemContext: systemContext, - NamespaceOptions: namespaceOptions, - ConfigureNetwork: networkPolicy, - CNIPluginPath: c.String("cni-plugin-path"), - CNIConfigDir: c.String("cni-config-dir"), - IDMappingOptions: idmappingOptions, - CommonBuildOpts: commonOpts, - DefaultMountsFilePath: c.GlobalString("default-mounts-file"), - IIDFile: c.String("iidfile"), - Squash: c.Bool("squash"), - Labels: c.StringSlice("label"), - Annotations: c.StringSlice("annotation"), - Layers: layers, - NoCache: c.Bool("no-cache"), - RemoveIntermediateCtrs: c.BoolT("rm"), - ForceRmIntermediateCtrs: c.BoolT("force-rm"), + SignaturePolicyPath: c.SignaturePolicy, + Squash: c.Squash, + Target: c.Target, } + return runtime.Build(getContext(), c, options, dockerfiles) +} - if c.Bool("quiet") { - options.ReportWriter = ioutil.Discard +// Tail returns a string slice after the first element unless there are +// not enough elements, then it returns an empty slice. This is to replace +// the urfavecli Tail method for args +func Tail(a []string) []string { + if len(a) >= 2 { + return []string(a)[1:] } + return []string{} +} - if rootless.IsRootless() { - options.Isolation = buildah.IsolationOCIRootless +// useLayers returns false if BUILDAH_LAYERS is set to "0" or "false" +// otherwise it returns true +func useLayers() string { + layers := os.Getenv("BUILDAH_LAYERS") + if strings.ToLower(layers) == "false" || layers == "0" { + return "false" } - - return runtime.Build(getContext(), options, dockerfiles...) + return "true" } |