Skip to content

Commit

Permalink
Implement missing arguments for podman build
Browse files Browse the repository at this point in the history
Buildah bud passes a bunch more flags then podman build.

We need to implement hook up all of these flags to get full functionality.

Signed-off-by: Daniel J Walsh <[email protected]>
  • Loading branch information
rhatdan committed Feb 8, 2021
1 parent 69ddbde commit 407e86d
Show file tree
Hide file tree
Showing 7 changed files with 643 additions and 109 deletions.
61 changes: 59 additions & 2 deletions cmd/podman/images/build.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
package images

import (
"io"
"os"
"path/filepath"
"strings"
"time"

"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/common/pkg/completion"
"github.com/containers/common/pkg/config"
encconfig "github.com/containers/ocicrypt/config"
enchelpers "github.com/containers/ocicrypt/helpers"
"github.com/containers/podman/v2/cmd/podman/common"
"github.com/containers/podman/v2/cmd/podman/registry"
"github.com/containers/podman/v2/cmd/podman/utils"
Expand Down Expand Up @@ -78,7 +82,8 @@ func useLayers() string {

func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},

Command: buildCmd,
})
buildFlags(buildCmd)
Expand Down Expand Up @@ -151,8 +156,21 @@ func buildFlags(cmd *cobra.Command) {
// Add the completion functions
fromAndBudFlagsCompletions := buildahCLI.GetFromAndBudFlagsCompletions()
completion.CompleteCommandFlags(cmd, fromAndBudFlagsCompletions)
_ = flags.MarkHidden("signature-policy")
flags.SetNormalizeFunc(buildahCLI.AliasFlags)
if registry.IsRemote() {
flag = flags.Lookup("isolation")
buildOpts.Isolation = buildah.OCI
if err := flag.Value.Set(buildah.OCI); err != nil {
logrus.Errorf("unable to set --isolation to %v: %v", buildah.OCI, err)
}
flag.DefValue = buildah.OCI
_ = flags.MarkHidden("disable-content-trust")
_ = flags.MarkHidden("cache-from")
_ = flags.MarkHidden("sign-by")
_ = flags.MarkHidden("signature-policy")
_ = flags.MarkHidden("tls-verify")
_ = flags.MarkHidden("compress")
}
}

// build executes the build command.
Expand Down Expand Up @@ -308,6 +326,10 @@ func buildFlagsWrapperToOptions(c *cobra.Command, contextDir string, flags *buil
flags.Layers = false
}

var stdin io.Reader
if flags.Stdin {
stdin = os.Stdin
}
var stdout, stderr, reporter *os.File
stdout = os.Stdout
stderr = os.Stderr
Expand Down Expand Up @@ -402,10 +424,21 @@ func buildFlagsWrapperToOptions(c *cobra.Command, contextDir string, flags *buil
runtimeFlags = append(runtimeFlags, "--systemd-cgroup")
}

imageOS, arch, err := parse.PlatformFromOptions(c)
if err != nil {
return nil, err
}

decConfig, err := getDecryptConfig(flags.DecryptionKeys)
if err != nil {
return nil, errors.Wrapf(err, "unable to obtain decrypt config")
}

opts := imagebuildah.BuildOptions{
AddCapabilities: flags.CapAdd,
AdditionalTags: tags,
Annotations: flags.Annotation,
Architecture: arch,
Args: args,
BlobDirectory: flags.BlobCache,
CNIConfigDir: flags.CNIConfigDir,
Expand Down Expand Up @@ -433,17 +466,26 @@ func buildFlagsWrapperToOptions(c *cobra.Command, contextDir string, flags *buil
DropCapabilities: flags.CapDrop,
Err: stderr,
ForceRmIntermediateCtrs: flags.ForceRm,
From: flags.From,
IDMappingOptions: idmappingOptions,
IIDFile: flags.Iidfile,
In: stdin,
Isolation: isolation,
Jobs: &flags.Jobs,
Labels: flags.Label,
Layers: flags.Layers,
LogRusage: flags.LogRusage,
Manifest: flags.Manifest,
MaxPullPushRetries: 3,
NamespaceOptions: nsValues,
NoCache: flags.NoCache,
OS: imageOS,
OciDecryptConfig: decConfig,
Out: stdout,
Output: output,
OutputFormat: format,
PullPolicy: pullPolicy,
PullPushRetryDelay: 2 * time.Second,
Quiet: flags.Quiet,
RemoveIntermediateCtrs: flags.Rm,
ReportWriter: reporter,
Expand All @@ -459,3 +501,18 @@ func buildFlagsWrapperToOptions(c *cobra.Command, contextDir string, flags *buil

return &entities.BuildOptions{BuildOptions: opts}, nil
}

func getDecryptConfig(decryptionKeys []string) (*encconfig.DecryptConfig, error) {
decConfig := &encconfig.DecryptConfig{}
if len(decryptionKeys) > 0 {
// decryption
dcc, err := enchelpers.CreateCryptoConfig([]string{}, decryptionKeys)
if err != nil {
return nil, errors.Wrapf(err, "invalid decryption keys")
}
cc := encconfig.CombineCryptoConfigs([]encconfig.CryptoConfig{dcc})
decConfig = cc.DecryptConfig
}

return decConfig, nil
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ require (
github.com/containers/common v0.33.1
github.com/containers/conmon v2.0.20+incompatible
github.com/containers/image/v5 v5.10.1
github.com/containers/ocicrypt v1.0.3
github.com/containers/psgo v1.5.2
github.com/containers/storage v1.25.0
github.com/coreos/go-systemd/v22 v22.1.0
Expand Down
183 changes: 126 additions & 57 deletions pkg/api/handlers/compat/images_build.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,29 +60,39 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
}()

query := struct {
BuildArgs string `schema:"buildargs"`
CacheFrom string `schema:"cachefrom"`
CpuPeriod uint64 `schema:"cpuperiod"` // nolint
CpuQuota int64 `schema:"cpuquota"` // nolint
CpuSetCpus string `schema:"cpusetcpus"` // nolint
CpuShares uint64 `schema:"cpushares"` // nolint
Dockerfile string `schema:"dockerfile"`
ExtraHosts string `schema:"extrahosts"`
ForceRm bool `schema:"forcerm"`
HTTPProxy bool `schema:"httpproxy"`
Labels string `schema:"labels"`
Layers bool `schema:"layers"`
MemSwap int64 `schema:"memswap"`
Memory int64 `schema:"memory"`
NetworkMode string `schema:"networkmode"`
NoCache bool `schema:"nocache"`
Outputs string `schema:"outputs"`
Platform string `schema:"platform"`
Pull bool `schema:"pull"`
Quiet bool `schema:"q"`
Registry string `schema:"registry"`
Remote string `schema:"remote"`
Rm bool `schema:"rm"`
AddHosts string `schema:"extrahosts"`
AdditionalCapabilities string `schema:"addcaps"`
Annotations string `schema:"annotations"`
BuildArgs string `schema:"buildargs"`
CacheFrom string `schema:"cachefrom"`
ConfigureNetwork int64 `schema:"networkmode"`
CpuPeriod uint64 `schema:"cpuperiod"` // nolint
CpuQuota int64 `schema:"cpuquota"` // nolint
CpuSetCpus string `schema:"cpusetcpus"` // nolint
CpuShares uint64 `schema:"cpushares"` // nolint
Devices string `schema:"devices"`
Dockerfile string `schema:"dockerfile"`
DropCapabilities string `schema:"dropcaps"`
ForceRm bool `schema:"forcerm"`
From string `schema:"from"`
HTTPProxy bool `schema:"httpproxy"`
Isolation int64 `schema:"isolation"`
Jobs uint64 `schema:"jobs"` // nolint
Labels string `schema:"labels"`
Layers bool `schema:"layers"`
LogRusage bool `schema:"rusage"`
Manifest string `schema:"manifest"`
MemSwap int64 `schema:"memswap"`
Memory int64 `schema:"memory"`
NoCache bool `schema:"nocache"`
OutputFormat string `schema:"outputformat"`
Platform string `schema:"platform"`
Pull bool `schema:"pull"`
Quiet bool `schema:"q"`
Registry string `schema:"registry"`
Rm bool `schema:"rm"`
//FIXME SecurityOpt in remote API is not handled
SecurityOpt string `schema:"securityopt"`
ShmSize int `schema:"shmsize"`
Squash bool `schema:"squash"`
Tag []string `schema:"t"`
Expand All @@ -101,14 +111,57 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
return
}

// convert label formats
var addCaps = []string{}
if _, found := r.URL.Query()["addcaps"]; found {
var m = []string{}
if err := json.Unmarshal([]byte(query.AdditionalCapabilities), &m); err != nil {
utils.BadRequest(w, "addcaps", query.AdditionalCapabilities, err)
return
}
addCaps = m
}
addhosts := []string{}
if _, found := r.URL.Query()["extrahosts"]; found {
if err := json.Unmarshal([]byte(query.AddHosts), &addhosts); err != nil {
utils.BadRequest(w, "extrahosts", query.AddHosts, err)
return
}
}

// convert label formats
var dropCaps = []string{}
if _, found := r.URL.Query()["dropcaps"]; found {
var m = []string{}
if err := json.Unmarshal([]byte(query.DropCapabilities), &m); err != nil {
utils.BadRequest(w, "dropcaps", query.DropCapabilities, err)
return
}
dropCaps = m
}

// convert label formats
var devices = []string{}
if _, found := r.URL.Query()["devices"]; found {
var m = []string{}
if err := json.Unmarshal([]byte(query.DropCapabilities), &m); err != nil {
utils.BadRequest(w, "devices", query.DropCapabilities, err)
return
}
devices = m
}

var output string
if len(query.Tag) > 0 {
output = query.Tag[0]
}

var additionalNames []string
format := buildah.Dockerv2ImageManifest
if utils.IsLibpodRequest(r) {
format = query.OutputFormat
}
var additionalTags []string
if len(query.Tag) > 1 {
additionalNames = query.Tag[1:]
additionalTags = query.Tag[1:]
}

var buildArgs = map[string]string{}
Expand All @@ -119,18 +172,22 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
}
}

// convert label formats
var annotations = []string{}
if _, found := r.URL.Query()["annotations"]; found {
if err := json.Unmarshal([]byte(query.Annotations), &annotations); err != nil {
utils.BadRequest(w, "annotations", query.Annotations, err)
return
}
}

// convert label formats
var labels = []string{}
if _, found := r.URL.Query()["labels"]; found {
var m = map[string]string{}
if err := json.Unmarshal([]byte(query.Labels), &m); err != nil {
if err := json.Unmarshal([]byte(query.Labels), &labels); err != nil {
utils.BadRequest(w, "labels", query.Labels, err)
return
}

for k, v := range m {
labels = append(labels, k+"="+v)
}
}

pullPolicy := buildah.PullIfMissing
Expand Down Expand Up @@ -160,27 +217,14 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {

reporter := channel.NewWriter(make(chan []byte, 1))
defer reporter.Close()

buildOptions := imagebuildah.BuildOptions{
ContextDirectory: contextDirectory,
PullPolicy: pullPolicy,
Registry: query.Registry,
IgnoreUnrecognizedInstructions: true,
Quiet: query.Quiet,
Layers: query.Layers,
Isolation: buildah.IsolationChroot,
Compression: archive.Gzip,
Args: buildArgs,
Output: output,
AdditionalTags: additionalNames,
Out: stdout,
Err: auxout,
ReportWriter: reporter,
OutputFormat: buildah.Dockerv2ImageManifest,
SystemContext: &types.SystemContext{
AuthFilePath: authfile,
DockerAuthConfig: creds,
},
AddCapabilities: addCaps,
AdditionalTags: additionalTags,
Annotations: annotations,
Args: buildArgs,
CommonBuildOpts: &buildah.CommonBuildOptions{
AddHost: addhosts,
CPUPeriod: query.CpuPeriod,
CPUQuota: query.CpuQuota,
CPUShares: query.CpuShares,
Expand All @@ -190,12 +234,37 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
MemorySwap: query.MemSwap,
ShmSize: strconv.Itoa(query.ShmSize),
},
Squash: query.Squash,
Labels: labels,
NoCache: query.NoCache,
RemoveIntermediateCtrs: query.Rm,
ForceRmIntermediateCtrs: query.ForceRm,
Target: query.Target,
Compression: archive.Gzip,
ConfigureNetwork: buildah.NetworkConfigurationPolicy(query.ConfigureNetwork),
ContextDirectory: contextDirectory,
Devices: devices,
DropCapabilities: dropCaps,
Err: auxout,
ForceRmIntermediateCtrs: query.ForceRm,
From: query.From,
IgnoreUnrecognizedInstructions: true,
// FIXME, This is very broken. Buildah will only work with chroot
// Isolation: buildah.Isolation(query.Isolation),
Isolation: buildah.IsolationChroot,

Labels: labels,
Layers: query.Layers,
Manifest: query.Manifest,
NoCache: query.NoCache,
Out: stdout,
Output: output,
OutputFormat: format,
PullPolicy: pullPolicy,
Quiet: query.Quiet,
Registry: query.Registry,
RemoveIntermediateCtrs: query.Rm,
ReportWriter: reporter,
Squash: query.Squash,
SystemContext: &types.SystemContext{
AuthFilePath: authfile,
DockerAuthConfig: creds,
},
Target: query.Target,
}

runtime := r.Context().Value("runtime").(*libpod.Runtime)
Expand Down
Loading

0 comments on commit 407e86d

Please sign in to comment.