mirror of
https://github.com/containers/podman.git
synced 2025-06-18 15:39:08 +08:00
Implement missing arguments for podman build
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 <dwalsh@redhat.com>
This commit is contained in:
@ -1,9 +1,11 @@
|
||||
package images
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/containers/buildah"
|
||||
"github.com/containers/buildah/imagebuildah"
|
||||
@ -11,6 +13,8 @@ import (
|
||||
"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"
|
||||
@ -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)
|
||||
@ -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.
|
||||
@ -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
|
||||
@ -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,
|
||||
@ -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,
|
||||
@ -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
go.mod
1
go.mod
@ -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
|
||||
|
@ -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"`
|
||||
@ -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{}
|
||||
@ -120,16 +173,20 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// 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 {
|
||||
utils.BadRequest(w, "labels", query.Labels, err)
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range m {
|
||||
labels = append(labels, k+"="+v)
|
||||
// convert label formats
|
||||
var labels = []string{}
|
||||
if _, found := r.URL.Query()["labels"]; found {
|
||||
if err := json.Unmarshal([]byte(query.Labels), &labels); err != nil {
|
||||
utils.BadRequest(w, "labels", query.Labels, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@ -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,
|
||||
@ -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)
|
||||
|
@ -31,36 +31,31 @@ import (
|
||||
func Build(ctx context.Context, containerFiles []string, options entities.BuildOptions) (*entities.BuildReport, error) {
|
||||
params := url.Values{}
|
||||
|
||||
if t := options.Output; len(t) > 0 {
|
||||
params.Set("t", t)
|
||||
if caps := options.AddCapabilities; len(caps) > 0 {
|
||||
c, err := jsoniter.MarshalToString(caps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
params.Add("addcaps", c)
|
||||
}
|
||||
|
||||
if annotations := options.Annotations; len(annotations) > 0 {
|
||||
l, err := jsoniter.MarshalToString(annotations)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
params.Set("annotations", l)
|
||||
}
|
||||
params.Add("t", options.Output)
|
||||
for _, tag := range options.AdditionalTags {
|
||||
params.Add("t", tag)
|
||||
}
|
||||
if options.Quiet {
|
||||
params.Set("q", "1")
|
||||
}
|
||||
if options.NoCache {
|
||||
params.Set("nocache", "1")
|
||||
}
|
||||
if options.Layers {
|
||||
params.Set("layers", "1")
|
||||
}
|
||||
// TODO cachefrom
|
||||
if options.PullPolicy == buildah.PullAlways {
|
||||
params.Set("pull", "1")
|
||||
}
|
||||
if options.RemoveIntermediateCtrs {
|
||||
params.Set("rm", "1")
|
||||
}
|
||||
if options.ForceRmIntermediateCtrs {
|
||||
params.Set("forcerm", "1")
|
||||
}
|
||||
if mem := options.CommonBuildOpts.Memory; mem > 0 {
|
||||
params.Set("memory", strconv.Itoa(int(mem)))
|
||||
}
|
||||
if memSwap := options.CommonBuildOpts.MemorySwap; memSwap > 0 {
|
||||
params.Set("memswap", strconv.Itoa(int(memSwap)))
|
||||
if buildArgs := options.Args; len(buildArgs) > 0 {
|
||||
bArgs, err := jsoniter.MarshalToString(buildArgs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
params.Set("buildargs", bArgs)
|
||||
}
|
||||
if cpuShares := options.CommonBuildOpts.CPUShares; cpuShares > 0 {
|
||||
params.Set("cpushares", strconv.Itoa(int(cpuShares)))
|
||||
@ -74,12 +69,95 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO
|
||||
if cpuQuota := options.CommonBuildOpts.CPUQuota; cpuQuota > 0 {
|
||||
params.Set("cpuquota", strconv.Itoa(int(cpuQuota)))
|
||||
}
|
||||
if buildArgs := options.Args; len(buildArgs) > 0 {
|
||||
bArgs, err := jsoniter.MarshalToString(buildArgs)
|
||||
params.Set("networkmode", strconv.Itoa(int(options.ConfigureNetwork)))
|
||||
params.Set("outputformat", options.OutputFormat)
|
||||
|
||||
if devices := options.Devices; len(devices) > 0 {
|
||||
d, err := jsoniter.MarshalToString(devices)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
params.Set("buildargs", bArgs)
|
||||
params.Add("devices", d)
|
||||
}
|
||||
|
||||
if caps := options.DropCapabilities; len(caps) > 0 {
|
||||
c, err := jsoniter.MarshalToString(caps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
params.Add("dropcaps", c)
|
||||
}
|
||||
|
||||
if options.ForceRmIntermediateCtrs {
|
||||
params.Set("forcerm", "1")
|
||||
}
|
||||
if len(options.From) > 0 {
|
||||
params.Set("from", options.From)
|
||||
}
|
||||
|
||||
params.Set("isolation", strconv.Itoa(int(options.Isolation)))
|
||||
if options.CommonBuildOpts.HTTPProxy {
|
||||
params.Set("httpproxy", "1")
|
||||
}
|
||||
if options.Jobs != nil {
|
||||
params.Set("jobs", strconv.FormatUint(uint64(*options.Jobs), 10))
|
||||
}
|
||||
if labels := options.Labels; len(labels) > 0 {
|
||||
l, err := jsoniter.MarshalToString(labels)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
params.Set("labels", l)
|
||||
}
|
||||
if options.Layers {
|
||||
params.Set("layers", "1")
|
||||
}
|
||||
if options.LogRusage {
|
||||
params.Set("rusage", "1")
|
||||
}
|
||||
if len(options.Manifest) > 0 {
|
||||
params.Set("manifest", options.Manifest)
|
||||
}
|
||||
if memSwap := options.CommonBuildOpts.MemorySwap; memSwap > 0 {
|
||||
params.Set("memswap", strconv.Itoa(int(memSwap)))
|
||||
}
|
||||
if mem := options.CommonBuildOpts.Memory; mem > 0 {
|
||||
params.Set("memory", strconv.Itoa(int(mem)))
|
||||
}
|
||||
if options.NoCache {
|
||||
params.Set("nocache", "1")
|
||||
}
|
||||
if t := options.Output; len(t) > 0 {
|
||||
params.Set("output", t)
|
||||
}
|
||||
var platform string
|
||||
if len(options.OS) > 0 {
|
||||
platform = options.OS
|
||||
}
|
||||
if len(options.Architecture) > 0 {
|
||||
if len(platform) == 0 {
|
||||
platform = "linux"
|
||||
}
|
||||
platform += "/" + options.Architecture
|
||||
}
|
||||
if len(platform) > 0 {
|
||||
params.Set("platform", platform)
|
||||
}
|
||||
if options.PullPolicy == buildah.PullAlways {
|
||||
params.Set("pull", "1")
|
||||
}
|
||||
if options.Quiet {
|
||||
params.Set("q", "1")
|
||||
}
|
||||
if options.RemoveIntermediateCtrs {
|
||||
params.Set("rm", "1")
|
||||
}
|
||||
if hosts := options.CommonBuildOpts.AddHost; len(hosts) > 0 {
|
||||
h, err := jsoniter.MarshalToString(hosts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
params.Set("extrahosts", h)
|
||||
}
|
||||
if shmSize := options.CommonBuildOpts.ShmSize; len(shmSize) > 0 {
|
||||
shmBytes, err := units.RAMInBytes(shmSize)
|
||||
@ -91,17 +169,6 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO
|
||||
if options.Squash {
|
||||
params.Set("squash", "1")
|
||||
}
|
||||
if labels := options.Labels; len(labels) > 0 {
|
||||
l, err := jsoniter.MarshalToString(labels)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
params.Set("labels", l)
|
||||
}
|
||||
if options.CommonBuildOpts.HTTPProxy {
|
||||
params.Set("httpproxy", "1")
|
||||
}
|
||||
|
||||
var (
|
||||
headers map[string]string
|
||||
err error
|
||||
@ -124,19 +191,6 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO
|
||||
stdout = options.Out
|
||||
}
|
||||
|
||||
// TODO network?
|
||||
|
||||
var platform string
|
||||
if OS := options.OS; len(OS) > 0 {
|
||||
platform += OS
|
||||
}
|
||||
if arch := options.Architecture; len(arch) > 0 {
|
||||
platform += "/" + arch
|
||||
}
|
||||
if len(platform) > 0 {
|
||||
params.Set("platform", platform)
|
||||
}
|
||||
|
||||
entries := make([]string, len(containerFiles))
|
||||
copy(entries, containerFiles)
|
||||
entries = append(entries, options.ContextDirectory)
|
||||
|
@ -458,4 +458,55 @@ RUN [[ -L /test/dummy-symlink ]] && echo SYMLNKOK || echo SYMLNKERR`
|
||||
Expect(ok).To(BeTrue())
|
||||
})
|
||||
|
||||
It("podman build --from, --add-host, --cap-drop, --cap-add", func() {
|
||||
targetPath, err := CreateTempDirInTempDir()
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
containerFile := filepath.Join(targetPath, "Containerfile")
|
||||
content := `FROM scratch
|
||||
RUN cat /etc/hosts
|
||||
RUN grep CapEff /proc/self/status`
|
||||
|
||||
Expect(ioutil.WriteFile(containerFile, []byte(content), 0755)).To(BeNil())
|
||||
|
||||
defer func() {
|
||||
Expect(os.RemoveAll(containerFile)).To(BeNil())
|
||||
}()
|
||||
|
||||
// When
|
||||
session := podmanTest.Podman([]string{
|
||||
"build", "--cap-drop=all", "--cap-add=net_bind_service", "--add-host", "testhost:1.2.3.4", "--from", "alpine", targetPath,
|
||||
})
|
||||
session.WaitWithDefaultTimeout()
|
||||
|
||||
// Then
|
||||
Expect(session.ExitCode()).To(Equal(0))
|
||||
Expect(strings.Fields(session.OutputToString())).
|
||||
To(ContainElement("alpine"))
|
||||
Expect(strings.Fields(session.OutputToString())).
|
||||
To(ContainElement("testhost"))
|
||||
Expect(strings.Fields(session.OutputToString())).
|
||||
To(ContainElement("0000000000000400"))
|
||||
})
|
||||
|
||||
It("podman build --arch", func() {
|
||||
targetPath, err := CreateTempDirInTempDir()
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
containerFile := filepath.Join(targetPath, "Containerfile")
|
||||
Expect(ioutil.WriteFile(containerFile, []byte("FROM alpine"), 0755)).To(BeNil())
|
||||
|
||||
defer func() {
|
||||
Expect(os.RemoveAll(containerFile)).To(BeNil())
|
||||
}()
|
||||
|
||||
// When
|
||||
session := podmanTest.Podman([]string{
|
||||
"build", "--arch", "arm64", targetPath,
|
||||
})
|
||||
session.WaitWithDefaultTimeout()
|
||||
|
||||
// Then
|
||||
Expect(session.ExitCode()).To(Equal(0))
|
||||
})
|
||||
})
|
||||
|
301
vendor/github.com/containers/ocicrypt/helpers/parse_helpers.go
generated
vendored
Normal file
301
vendor/github.com/containers/ocicrypt/helpers/parse_helpers.go
generated
vendored
Normal file
@ -0,0 +1,301 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/ocicrypt"
|
||||
encconfig "github.com/containers/ocicrypt/config"
|
||||
encutils "github.com/containers/ocicrypt/utils"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// processRecipientKeys sorts the array of recipients by type. Recipients may be either
|
||||
// x509 certificates, public keys, or PGP public keys identified by email address or name
|
||||
func processRecipientKeys(recipients []string) ([][]byte, [][]byte, [][]byte, error) {
|
||||
var (
|
||||
gpgRecipients [][]byte
|
||||
pubkeys [][]byte
|
||||
x509s [][]byte
|
||||
)
|
||||
for _, recipient := range recipients {
|
||||
|
||||
idx := strings.Index(recipient, ":")
|
||||
if idx < 0 {
|
||||
return nil, nil, nil, errors.New("Invalid recipient format")
|
||||
}
|
||||
|
||||
protocol := recipient[:idx]
|
||||
value := recipient[idx+1:]
|
||||
|
||||
switch protocol {
|
||||
case "pgp":
|
||||
gpgRecipients = append(gpgRecipients, []byte(value))
|
||||
|
||||
case "jwe":
|
||||
tmp, err := ioutil.ReadFile(value)
|
||||
if err != nil {
|
||||
return nil, nil, nil, errors.Wrap(err, "Unable to read file")
|
||||
}
|
||||
if !encutils.IsPublicKey(tmp) {
|
||||
return nil, nil, nil, errors.New("File provided is not a public key")
|
||||
}
|
||||
pubkeys = append(pubkeys, tmp)
|
||||
|
||||
case "pkcs7":
|
||||
tmp, err := ioutil.ReadFile(value)
|
||||
if err != nil {
|
||||
return nil, nil, nil, errors.Wrap(err, "Unable to read file")
|
||||
}
|
||||
if !encutils.IsCertificate(tmp) {
|
||||
return nil, nil, nil, errors.New("File provided is not an x509 cert")
|
||||
}
|
||||
x509s = append(x509s, tmp)
|
||||
|
||||
default:
|
||||
return nil, nil, nil, errors.New("Provided protocol not recognized")
|
||||
}
|
||||
}
|
||||
return gpgRecipients, pubkeys, x509s, nil
|
||||
}
|
||||
|
||||
// processx509Certs processes x509 certificate files
|
||||
func processx509Certs(keys []string) ([][]byte, error) {
|
||||
var x509s [][]byte
|
||||
for _, key := range keys {
|
||||
tmp, err := ioutil.ReadFile(key)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Unable to read file")
|
||||
}
|
||||
if !encutils.IsCertificate(tmp) {
|
||||
continue
|
||||
}
|
||||
x509s = append(x509s, tmp)
|
||||
|
||||
}
|
||||
return x509s, nil
|
||||
}
|
||||
|
||||
// processPwdString process a password that may be in any of the following formats:
|
||||
// - file=<passwordfile>
|
||||
// - pass=<password>
|
||||
// - fd=<filedescriptor>
|
||||
// - <password>
|
||||
func processPwdString(pwdString string) ([]byte, error) {
|
||||
if strings.HasPrefix(pwdString, "file=") {
|
||||
return ioutil.ReadFile(pwdString[5:])
|
||||
} else if strings.HasPrefix(pwdString, "pass=") {
|
||||
return []byte(pwdString[5:]), nil
|
||||
} else if strings.HasPrefix(pwdString, "fd=") {
|
||||
fdStr := pwdString[3:]
|
||||
fd, err := strconv.Atoi(fdStr)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not parse file descriptor %s", fdStr)
|
||||
}
|
||||
f := os.NewFile(uintptr(fd), "pwdfile")
|
||||
if f == nil {
|
||||
return nil, fmt.Errorf("%s is not a valid file descriptor", fdStr)
|
||||
}
|
||||
defer f.Close()
|
||||
pwd := make([]byte, 64)
|
||||
n, err := f.Read(pwd)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not read from file descriptor")
|
||||
}
|
||||
return pwd[:n], nil
|
||||
}
|
||||
return []byte(pwdString), nil
|
||||
}
|
||||
|
||||
// processPrivateKeyFiles sorts the different types of private key files; private key files may either be
|
||||
// private keys or GPG private key ring files. The private key files may include the password for the
|
||||
// private key and take any of the following forms:
|
||||
// - <filename>
|
||||
// - <filename>:file=<passwordfile>
|
||||
// - <filename>:pass=<password>
|
||||
// - <filename>:fd=<filedescriptor>
|
||||
// - <filename>:<password>
|
||||
func processPrivateKeyFiles(keyFilesAndPwds []string) ([][]byte, [][]byte, [][]byte, [][]byte, error) {
|
||||
var (
|
||||
gpgSecretKeyRingFiles [][]byte
|
||||
gpgSecretKeyPasswords [][]byte
|
||||
privkeys [][]byte
|
||||
privkeysPasswords [][]byte
|
||||
err error
|
||||
)
|
||||
// keys needed for decryption in case of adding a recipient
|
||||
for _, keyfileAndPwd := range keyFilesAndPwds {
|
||||
var password []byte
|
||||
|
||||
parts := strings.Split(keyfileAndPwd, ":")
|
||||
if len(parts) == 2 {
|
||||
password, err = processPwdString(parts[1])
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
keyfile := parts[0]
|
||||
tmp, err := ioutil.ReadFile(keyfile)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
isPrivKey, err := encutils.IsPrivateKey(tmp, password)
|
||||
if encutils.IsPasswordError(err) {
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
if isPrivKey {
|
||||
privkeys = append(privkeys, tmp)
|
||||
privkeysPasswords = append(privkeysPasswords, password)
|
||||
} else if encutils.IsGPGPrivateKeyRing(tmp) {
|
||||
gpgSecretKeyRingFiles = append(gpgSecretKeyRingFiles, tmp)
|
||||
gpgSecretKeyPasswords = append(gpgSecretKeyPasswords, password)
|
||||
} else {
|
||||
// ignore if file is not recognized, so as not to error if additional
|
||||
// metadata/cert files exists
|
||||
continue
|
||||
}
|
||||
}
|
||||
return gpgSecretKeyRingFiles, gpgSecretKeyPasswords, privkeys, privkeysPasswords, nil
|
||||
}
|
||||
|
||||
// CreateDecryptCryptoConfig creates the CryptoConfig object that contains the necessary
|
||||
// information to perform decryption from command line options and possibly
|
||||
// LayerInfos describing the image and helping us to query for the PGP decryption keys
|
||||
func CreateDecryptCryptoConfig(keys []string, decRecipients []string) (encconfig.CryptoConfig, error) {
|
||||
ccs := []encconfig.CryptoConfig{}
|
||||
|
||||
// x509 cert is needed for PKCS7 decryption
|
||||
_, _, x509s, err := processRecipientKeys(decRecipients)
|
||||
if err != nil {
|
||||
return encconfig.CryptoConfig{}, err
|
||||
}
|
||||
|
||||
// x509 certs can also be passed in via keys
|
||||
x509FromKeys, err := processx509Certs(keys)
|
||||
if err != nil {
|
||||
return encconfig.CryptoConfig{}, err
|
||||
}
|
||||
x509s = append(x509s, x509FromKeys...)
|
||||
|
||||
gpgSecretKeyRingFiles, gpgSecretKeyPasswords, privKeys, privKeysPasswords, err := processPrivateKeyFiles(keys)
|
||||
if err != nil {
|
||||
return encconfig.CryptoConfig{}, err
|
||||
}
|
||||
|
||||
if len(gpgSecretKeyRingFiles) > 0 {
|
||||
gpgCc, err := encconfig.DecryptWithGpgPrivKeys(gpgSecretKeyRingFiles, gpgSecretKeyPasswords)
|
||||
if err != nil {
|
||||
return encconfig.CryptoConfig{}, err
|
||||
}
|
||||
ccs = append(ccs, gpgCc)
|
||||
}
|
||||
|
||||
/* TODO: Add in GPG client query for secret keys in the future.
|
||||
_, err = createGPGClient(context)
|
||||
gpgInstalled := err == nil
|
||||
if gpgInstalled {
|
||||
if len(gpgSecretKeyRingFiles) == 0 && len(privKeys) == 0 && descs != nil {
|
||||
// Get pgp private keys from keyring only if no private key was passed
|
||||
gpgPrivKeys, gpgPrivKeyPasswords, err := getGPGPrivateKeys(context, gpgSecretKeyRingFiles, descs, true)
|
||||
if err != nil {
|
||||
return encconfig.CryptoConfig{}, err
|
||||
}
|
||||
|
||||
gpgCc, err := encconfig.DecryptWithGpgPrivKeys(gpgPrivKeys, gpgPrivKeyPasswords)
|
||||
if err != nil {
|
||||
return encconfig.CryptoConfig{}, err
|
||||
}
|
||||
ccs = append(ccs, gpgCc)
|
||||
|
||||
} else if len(gpgSecretKeyRingFiles) > 0 {
|
||||
gpgCc, err := encconfig.DecryptWithGpgPrivKeys(gpgSecretKeyRingFiles, gpgSecretKeyPasswords)
|
||||
if err != nil {
|
||||
return encconfig.CryptoConfig{}, err
|
||||
}
|
||||
ccs = append(ccs, gpgCc)
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
x509sCc, err := encconfig.DecryptWithX509s(x509s)
|
||||
if err != nil {
|
||||
return encconfig.CryptoConfig{}, err
|
||||
}
|
||||
ccs = append(ccs, x509sCc)
|
||||
|
||||
privKeysCc, err := encconfig.DecryptWithPrivKeys(privKeys, privKeysPasswords)
|
||||
if err != nil {
|
||||
return encconfig.CryptoConfig{}, err
|
||||
}
|
||||
ccs = append(ccs, privKeysCc)
|
||||
|
||||
return encconfig.CombineCryptoConfigs(ccs), nil
|
||||
}
|
||||
|
||||
// CreateCryptoConfig from the list of recipient strings and list of key paths of private keys
|
||||
func CreateCryptoConfig(recipients []string, keys []string) (encconfig.CryptoConfig, error) {
|
||||
var decryptCc *encconfig.CryptoConfig
|
||||
ccs := []encconfig.CryptoConfig{}
|
||||
if len(keys) > 0 {
|
||||
dcc, err := CreateDecryptCryptoConfig(keys, []string{})
|
||||
if err != nil {
|
||||
return encconfig.CryptoConfig{}, err
|
||||
}
|
||||
decryptCc = &dcc
|
||||
ccs = append(ccs, dcc)
|
||||
}
|
||||
|
||||
if len(recipients) > 0 {
|
||||
gpgRecipients, pubKeys, x509s, err := processRecipientKeys(recipients)
|
||||
if err != nil {
|
||||
return encconfig.CryptoConfig{}, err
|
||||
}
|
||||
encryptCcs := []encconfig.CryptoConfig{}
|
||||
|
||||
// Create GPG client with guessed GPG version and default homedir
|
||||
gpgClient, err := ocicrypt.NewGPGClient("", "")
|
||||
gpgInstalled := err == nil
|
||||
if len(gpgRecipients) > 0 && gpgInstalled {
|
||||
gpgPubRingFile, err := gpgClient.ReadGPGPubRingFile()
|
||||
if err != nil {
|
||||
return encconfig.CryptoConfig{}, err
|
||||
}
|
||||
|
||||
gpgCc, err := encconfig.EncryptWithGpg(gpgRecipients, gpgPubRingFile)
|
||||
if err != nil {
|
||||
return encconfig.CryptoConfig{}, err
|
||||
}
|
||||
encryptCcs = append(encryptCcs, gpgCc)
|
||||
}
|
||||
|
||||
// Create Encryption Crypto Config
|
||||
pkcs7Cc, err := encconfig.EncryptWithPkcs7(x509s)
|
||||
if err != nil {
|
||||
return encconfig.CryptoConfig{}, err
|
||||
}
|
||||
encryptCcs = append(encryptCcs, pkcs7Cc)
|
||||
|
||||
jweCc, err := encconfig.EncryptWithJwe(pubKeys)
|
||||
if err != nil {
|
||||
return encconfig.CryptoConfig{}, err
|
||||
}
|
||||
encryptCcs = append(encryptCcs, jweCc)
|
||||
ecc := encconfig.CombineCryptoConfigs(encryptCcs)
|
||||
if decryptCc != nil {
|
||||
ecc.EncryptConfig.AttachDecryptConfig(decryptCc.DecryptConfig)
|
||||
}
|
||||
ccs = append(ccs, ecc)
|
||||
}
|
||||
|
||||
if len(ccs) > 0 {
|
||||
return encconfig.CombineCryptoConfigs(ccs), nil
|
||||
} else {
|
||||
return encconfig.CryptoConfig{}, nil
|
||||
}
|
||||
}
|
1
vendor/modules.txt
vendored
1
vendor/modules.txt
vendored
@ -159,6 +159,7 @@ github.com/containers/libtrust
|
||||
github.com/containers/ocicrypt
|
||||
github.com/containers/ocicrypt/blockcipher
|
||||
github.com/containers/ocicrypt/config
|
||||
github.com/containers/ocicrypt/helpers
|
||||
github.com/containers/ocicrypt/keywrap
|
||||
github.com/containers/ocicrypt/keywrap/jwe
|
||||
github.com/containers/ocicrypt/keywrap/pgp
|
||||
|
Reference in New Issue
Block a user