podman-remote build

add the ability to build images using files local to the remote-client
but over a varlink interface to a "remote" server.

Signed-off-by: baude <bbaude@redhat.com>
This commit is contained in:
baude 2019-02-06 09:44:16 -06:00
parent fa3b91dc12
commit ef85dd7950
8 changed files with 436 additions and 216 deletions

95
API.md
View file

@ -135,6 +135,8 @@ in the [API.md](https://github.com/containers/libpod/blob/master/API.md) file in
[type BuildInfo](#BuildInfo)
[type BuildOptions](#BuildOptions)
[type Container](#Container)
[type ContainerChanges](#ContainerChanges)
@ -972,53 +974,84 @@ a [ContainerNotFound](#ContainerNotFound) error is returned.
BuildInfo is used to describe user input for building images
dockerfile [[]string](#[]string)
additionalTags [[]string](#[]string)
tags [[]string](#[]string)
annotations [[]string](#[]string)
add_hosts [[]string](#[]string)
buildArgs [map[string]](#map[string])
cgroup_parent [string](https://godoc.org/builtin#string)
buildOptions [BuildOptions](#BuildOptions)
cpu_period [int](https://godoc.org/builtin#int)
cniConfigDir [string](https://godoc.org/builtin#string)
cpu_quota [int](https://godoc.org/builtin#int)
cniPluginDir [string](https://godoc.org/builtin#string)
cpu_shares [int](https://godoc.org/builtin#int)
compression [string](https://godoc.org/builtin#string)
cpuset_cpus [string](https://godoc.org/builtin#string)
contextDir [string](https://godoc.org/builtin#string)
cpuset_mems [string](https://godoc.org/builtin#string)
defaultsMountFilePath [string](https://godoc.org/builtin#string)
memory [string](https://godoc.org/builtin#string)
dockerfiles [[]string](#[]string)
memory_swap [string](https://godoc.org/builtin#string)
err [string](https://godoc.org/builtin#string)
security_opts [[]string](#[]string)
forceRmIntermediateCtrs [bool](https://godoc.org/builtin#bool)
shm_size [string](https://godoc.org/builtin#string)
iidfile [string](https://godoc.org/builtin#string)
label [[]string](#[]string)
layers [bool](https://godoc.org/builtin#bool)
nocache [bool](https://godoc.org/builtin#bool)
out [string](https://godoc.org/builtin#string)
output [string](https://godoc.org/builtin#string)
outputFormat [string](https://godoc.org/builtin#string)
pullPolicy [string](https://godoc.org/builtin#string)
quiet [bool](https://godoc.org/builtin#bool)
remoteIntermediateCtrs [bool](https://godoc.org/builtin#bool)
reportWriter [string](https://godoc.org/builtin#string)
runtimeArgs [[]string](#[]string)
signaturePolicyPath [string](https://godoc.org/builtin#string)
squash [bool](https://godoc.org/builtin#bool)
### <a name="BuildOptions"></a>type BuildOptions
BuildOptions are are used to describe describe physical attributes of the build
addHosts [[]string](#[]string)
cgroupParent [string](https://godoc.org/builtin#string)
cpuPeriod [int](https://godoc.org/builtin#int)
cpuQuota [int](https://godoc.org/builtin#int)
cpuShares [int](https://godoc.org/builtin#int)
cpusetCpus [string](https://godoc.org/builtin#string)
cpusetMems [string](https://godoc.org/builtin#string)
memory [int](https://godoc.org/builtin#int)
memorySwap [int](https://godoc.org/builtin#int)
shmSize [string](https://godoc.org/builtin#string)
ulimit [[]string](#[]string)
volume [[]string](#[]string)
squash [bool](https://godoc.org/builtin#bool)
pull [bool](https://godoc.org/builtin#bool)
pull_always [bool](https://godoc.org/builtin#bool)
force_rm [bool](https://godoc.org/builtin#bool)
rm [bool](https://godoc.org/builtin#bool)
label [[]string](#[]string)
annotations [[]string](#[]string)
build_args [map[string]](#map[string])
image_format [string](https://godoc.org/builtin#string)
### <a name="Container"></a>type Container

View file

@ -1,7 +1,6 @@
package main
import (
"io/ioutil"
"os"
"path/filepath"
"strings"
@ -9,10 +8,9 @@ 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/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/pkg/rootless"
"github.com/containers/libpod/libpod/adapter"
"github.com/docker/go-units"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
@ -76,7 +74,6 @@ func getDockerfiles(files []string) []string {
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.Flag("tag").Changed {
@ -86,6 +83,7 @@ func buildCmd(c *cliconfig.BuildValues) error {
tags = tags[1:]
}
}
pullPolicy := imagebuildah.PullNever
if c.Pull {
pullPolicy = imagebuildah.PullIfMissing
@ -173,16 +171,17 @@ func buildCmd(c *cliconfig.BuildValues) error {
dockerfiles = append(dockerfiles, filepath.Join(contextDir, "Dockerfile"))
}
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
runtimeFlags := []string{}
for _, arg := range c.RuntimeOpts {
runtimeFlags = append(runtimeFlags, "--"+arg)
}
// end from buildah
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
defer runtime.Shutdown(false)
var stdout, stderr, reporter *os.File
@ -201,72 +200,64 @@ func buildCmd(c *cliconfig.BuildValues) error {
reporter = f
}
systemContext, err := parse.SystemContextFromOptions(c.PodmanCommand.Command)
if err != nil {
return errors.Wrapf(err, "error building system context")
}
systemContext.AuthFilePath = getAuthFile(c.Authfile)
commonOpts, err := parse.CommonBuildOptions(c.PodmanCommand.Command)
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.PodmanCommand.Command)
if err != nil {
return errors.Wrapf(err, "error parsing namespace-related options")
if c.Flags().Changed("memory-swap") {
memorySwap, err = units.RAMInBytes(c.MemorySwap)
if err != nil {
return err
}
}
usernsOption, idmappingOptions, err := parse.IDMappingOptions(c.PodmanCommand.Command)
if err != nil {
return errors.Wrapf(err, "error parsing ID mapping options")
}
namespaceOptions.AddOrReplace(usernsOption...)
ociruntime := runtime.GetOCIRuntimePath()
if c.Flag("runtime").Changed {
ociruntime = c.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.Quiet,
SignaturePolicyPath: c.SignaturePolicy,
Args: args,
Output: output,
CommonBuildOpts: &buildOpts,
AdditionalTags: tags,
Out: stdout,
Err: stderr,
ReportWriter: reporter,
Runtime: ociruntime,
RuntimeArgs: runtimeFlags,
OutputFormat: format,
SystemContext: systemContext,
NamespaceOptions: namespaceOptions,
ConfigureNetwork: networkPolicy,
CNIPluginPath: c.CNIPlugInPath,
CNIConfigDir: c.CNIConfigDir,
IDMappingOptions: idmappingOptions,
CommonBuildOpts: commonOpts,
DefaultMountsFilePath: c.GlobalFlags.DefaultMountsFile,
IIDFile: c.Iidfile,
Squash: c.Squash,
Labels: c.Label,
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,
ForceRmIntermediateCtrs: c.ForceRm,
ReportWriter: reporter,
RuntimeArgs: runtimeFlags,
SignaturePolicyPath: c.SignaturePolicy,
Squash: c.Squash,
}
if c.Quiet {
options.ReportWriter = ioutil.Discard
}
if rootless.IsRootless() {
options.Isolation = buildah.IsolationOCIRootless
}
return runtime.Build(getContext(), options, dockerfiles...)
return runtime.Build(getContext(), c, options, dockerfiles)
}
// Tail returns a string slice after the first element unless there are

View file

@ -311,33 +311,50 @@ type IDMap (
size: int
)
# BuildOptions are are used to describe describe physical attributes of the build
type BuildOptions (
addHosts: []string,
cgroupParent: string,
cpuPeriod: int,
cpuQuota: int,
cpuShares: int,
cpusetCpus: string,
cpusetMems: string,
memory: int,
memorySwap: int,
shmSize: string,
ulimit: []string,
volume: []string
)
# BuildInfo is used to describe user input for building images
type BuildInfo (
# paths to one or more dockerfiles
dockerfile: []string,
tags: []string,
add_hosts: []string,
cgroup_parent: string,
cpu_period: int,
cpu_quota: int,
cpu_shares: int,
cpuset_cpus: string,
cpuset_mems: string,
memory: string,
memory_swap: string,
security_opts: []string,
shm_size: string,
ulimit: []string,
volume: []string,
squash: bool,
pull: bool,
pull_always: bool,
force_rm: bool,
rm: bool,
label: []string,
additionalTags: []string,
annotations: []string,
build_args: [string]string,
image_format: string
buildArgs: [string]string,
buildOptions: BuildOptions,
cniConfigDir: string,
cniPluginDir: string,
compression: string,
contextDir: string,
defaultsMountFilePath: string,
dockerfiles: []string,
err: string,
forceRmIntermediateCtrs: bool,
iidfile: string,
label: []string,
layers: bool,
nocache: bool,
out: string,
output: string,
outputFormat: string,
pullPolicy: string,
quiet: bool,
remoteIntermediateCtrs: bool,
reportWriter: string,
runtimeArgs: []string,
signaturePolicyPath: string,
squash: bool
)
# MoreResponse is a struct for when responses from varlink requires longer output

View file

@ -9,6 +9,9 @@ import (
"os"
"strconv"
"github.com/containers/buildah"
"github.com/containers/buildah/imagebuildah"
"github.com/containers/buildah/pkg/parse"
"github.com/containers/image/docker/reference"
"github.com/containers/image/types"
"github.com/containers/libpod/cmd/podman/cliconfig"
@ -254,3 +257,51 @@ func libpodVolumeToVolume(volumes []*libpod.Volume) []*Volume {
}
return vols
}
// Build is the wrapper to build images
func (r *LocalRuntime) Build(ctx context.Context, c *cliconfig.BuildValues, options imagebuildah.BuildOptions, dockerfiles []string) error {
namespaceOptions, networkPolicy, err := parse.NamespaceOptions(c.PodmanCommand.Command)
if err != nil {
return errors.Wrapf(err, "error parsing namespace-related options")
}
usernsOption, idmappingOptions, err := parse.IDMappingOptions(c.PodmanCommand.Command)
if err != nil {
return errors.Wrapf(err, "error parsing ID mapping options")
}
namespaceOptions.AddOrReplace(usernsOption...)
systemContext, err := parse.SystemContextFromOptions(c.PodmanCommand.Command)
if err != nil {
return errors.Wrapf(err, "error building system context")
}
authfile := c.Authfile
if len(c.Authfile) == 0 {
authfile = os.Getenv("REGISTRY_AUTH_FILE")
}
systemContext.AuthFilePath = authfile
commonOpts, err := parse.CommonBuildOptions(c.PodmanCommand.Command)
if err != nil {
return err
}
options.NamespaceOptions = namespaceOptions
options.ConfigureNetwork = networkPolicy
options.IDMappingOptions = idmappingOptions
options.CommonBuildOpts = commonOpts
options.SystemContext = systemContext
if c.Flag("runtime").Changed {
options.Runtime = r.GetOCIRuntimePath()
}
if c.Quiet {
options.ReportWriter = ioutil.Discard
}
if rootless.IsRootless() {
options.Isolation = buildah.IsolationOCIRootless
}
return r.Runtime.Build(ctx, options, dockerfiles...)
}

View file

@ -7,19 +7,22 @@ import (
"context"
"encoding/json"
"fmt"
"github.com/pkg/errors"
"io"
"io/ioutil"
"os"
"strings"
"time"
"github.com/containers/buildah/imagebuildah"
"github.com/containers/image/docker/reference"
"github.com/containers/image/types"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/image"
"github.com/containers/storage/pkg/archive"
"github.com/opencontainers/go-digest"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/varlink/go/varlink"
)
@ -376,6 +379,108 @@ func (r *LocalRuntime) Export(name string, path string) error {
// Import implements the remote calls required to import a container image to the store
func (r *LocalRuntime) Import(ctx context.Context, source, reference string, changes []string, history string, quiet bool) (string, error) {
// First we send the file to the host
tempFile, err := r.SendFileOverVarlink(source)
if err != nil {
return "", err
}
return iopodman.ImportImage().Call(r.Conn, strings.TrimRight(tempFile, ":"), reference, history, changes, true)
}
func (r *LocalRuntime) Build(ctx context.Context, c *cliconfig.BuildValues, options imagebuildah.BuildOptions, dockerfiles []string) error {
buildOptions := iopodman.BuildOptions{
AddHosts: options.CommonBuildOpts.AddHost,
CgroupParent: options.CommonBuildOpts.CgroupParent,
CpuPeriod: int64(options.CommonBuildOpts.CPUPeriod),
CpuQuota: options.CommonBuildOpts.CPUQuota,
CpuShares: int64(options.CommonBuildOpts.CPUShares),
CpusetCpus: options.CommonBuildOpts.CPUSetMems,
CpusetMems: options.CommonBuildOpts.CPUSetMems,
Memory: options.CommonBuildOpts.Memory,
MemorySwap: options.CommonBuildOpts.MemorySwap,
ShmSize: options.CommonBuildOpts.ShmSize,
Ulimit: options.CommonBuildOpts.Ulimit,
Volume: options.CommonBuildOpts.Volumes,
}
buildinfo := iopodman.BuildInfo{
AdditionalTags: options.AdditionalTags,
Annotations: options.Annotations,
BuildArgs: options.Args,
BuildOptions: buildOptions,
CniConfigDir: options.CNIConfigDir,
CniPluginDir: options.CNIPluginPath,
Compression: string(options.Compression),
DefaultsMountFilePath: options.DefaultMountsFilePath,
Dockerfiles: dockerfiles,
//Err: string(options.Err),
ForceRmIntermediateCtrs: options.ForceRmIntermediateCtrs,
Iidfile: options.IIDFile,
Label: options.Labels,
Layers: options.Layers,
Nocache: options.NoCache,
//Out:
Output: options.Output,
OutputFormat: options.OutputFormat,
PullPolicy: options.PullPolicy.String(),
Quiet: options.Quiet,
RemoteIntermediateCtrs: options.RemoveIntermediateCtrs,
//ReportWriter:
RuntimeArgs: options.RuntimeArgs,
SignaturePolicyPath: options.SignaturePolicyPath,
Squash: options.Squash,
}
// tar the file
logrus.Debugf("creating tarball of context dir %s", options.ContextDirectory)
input, err := archive.Tar(options.ContextDirectory, archive.Uncompressed)
if err != nil {
return errors.Wrapf(err, "unable to create tarball of context dir %s", options.ContextDirectory)
}
// Write the tarball to the fs
// TODO we might considering sending this without writing to the fs for the sake of performance
// under given conditions like memory availability.
outputFile, err := ioutil.TempFile("", "varlink_tar_send")
if err != nil {
return err
}
defer outputFile.Close()
logrus.Debugf("writing context dir tarball to %s", outputFile.Name())
_, err = io.Copy(outputFile, input)
if err != nil {
return err
}
logrus.Debugf("completed writing context dir tarball %s", outputFile.Name())
// Send the context dir tarball over varlink.
tempFile, err := r.SendFileOverVarlink(outputFile.Name())
if err != nil {
return err
}
buildinfo.ContextDir = strings.Replace(tempFile, ":", "", -1)
reply, err := iopodman.BuildImage().Send(r.Conn, varlink.More, buildinfo)
if err != nil {
return err
}
for {
responses, flags, err := reply()
if err != nil {
return err
}
for _, line := range responses.Logs {
fmt.Print(line)
}
if flags&varlink.Continues == 0 {
break
}
}
return err
}
// SendFileOverVarlink sends a file over varlink in an upgraded connection
func (r *LocalRuntime) SendFileOverVarlink(source string) (string, error) {
fs, err := os.Open(source)
if err != nil {
return "", err
@ -385,6 +490,7 @@ func (r *LocalRuntime) Import(ctx context.Context, source, reference string, cha
if err != nil {
return "", err
}
logrus.Debugf("sending %s over varlink connection", source)
reply, err := iopodman.SendFile().Send(r.Conn, varlink.Upgrade, "", int64(fileInfo.Size()))
if err != nil {
return "", err
@ -399,6 +505,7 @@ func (r *LocalRuntime) Import(ctx context.Context, source, reference string, cha
if err != nil {
return "", err
}
logrus.Debugf("file transfer complete for %s", source)
r.Conn.Writer.Flush()
// All was sent, wait for the ACK from the server
@ -412,7 +519,8 @@ func (r *LocalRuntime) Import(ctx context.Context, source, reference string, cha
return "", err
}
return iopodman.ImportImage().Call(r.Conn, strings.TrimRight(tempFile, ":"), reference, history, changes, true)
return tempFile, nil
}
// GetAllVolumes retrieves all the volumes

View file

@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"strings"
@ -24,7 +25,7 @@ import (
sysreg "github.com/containers/libpod/pkg/registries"
"github.com/containers/libpod/pkg/util"
"github.com/containers/libpod/utils"
"github.com/docker/go-units"
"github.com/containers/storage/pkg/archive"
"github.com/opencontainers/image-spec/specs-go/v1"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
@ -110,83 +111,46 @@ func (i *LibpodAPI) GetImage(call iopodman.VarlinkCall, id string) error {
// BuildImage ...
func (i *LibpodAPI) BuildImage(call iopodman.VarlinkCall, config iopodman.BuildInfo) error {
var (
memoryLimit int64
memorySwap int64
namespace []buildah.NamespaceOption
err error
namespace []buildah.NamespaceOption
err error
)
systemContext := types.SystemContext{}
dockerfiles := config.Dockerfile
contextDir := ""
contextDir := config.ContextDir
for i := range dockerfiles {
if strings.HasPrefix(dockerfiles[i], "http://") ||
strings.HasPrefix(dockerfiles[i], "https://") ||
strings.HasPrefix(dockerfiles[i], "git://") ||
strings.HasPrefix(dockerfiles[i], "github.com/") {
continue
}
absFile, err := filepath.Abs(dockerfiles[i])
if err != nil {
return errors.Wrapf(err, "error determining path to file %q", dockerfiles[i])
}
contextDir = filepath.Dir(absFile)
dockerfiles[i], err = filepath.Rel(contextDir, absFile)
if err != nil {
return errors.Wrapf(err, "error determining path to file %q", dockerfiles[i])
}
break
newContextDir, err := ioutil.TempDir("", "buildTarball")
if err != nil {
call.ReplyErrorOccurred("unable to create tempdir")
}
logrus.Debugf("created new context dir at %s", newContextDir)
pullPolicy := imagebuildah.PullNever
if config.Pull {
pullPolicy = imagebuildah.PullIfMissing
}
if config.Pull_always {
pullPolicy = imagebuildah.PullAlways
}
manifestType := "oci" //nolint
if config.Image_format != "" {
manifestType = config.Image_format
}
if strings.HasPrefix(manifestType, "oci") {
manifestType = buildah.OCIv1ImageManifest
} else if strings.HasPrefix(manifestType, "docker") {
manifestType = buildah.Dockerv2ImageManifest
} else {
return call.ReplyErrorOccurred(fmt.Sprintf("unrecognized image type %q", manifestType))
}
if config.Memory != "" {
memoryLimit, err = units.RAMInBytes(config.Memory)
if err != nil {
return call.ReplyErrorOccurred(err.Error())
}
}
if config.Memory_swap != "" {
memorySwap, err = units.RAMInBytes(config.Memory_swap)
if err != nil {
return call.ReplyErrorOccurred(err.Error())
}
reader, err := os.Open(contextDir)
if err != nil {
logrus.Errorf("failed to open the context dir tar file %s", contextDir)
return call.ReplyErrorOccurred(fmt.Sprintf("unable to open context dir tar file %s", contextDir))
}
defer reader.Close()
if err := archive.Untar(reader, newContextDir, &archive.TarOptions{}); err != nil {
logrus.Errorf("fail to untar the context dir tarball (%s) to the context dir (%s)", contextDir, newContextDir)
return call.ReplyErrorOccurred(fmt.Sprintf("unable to untar context dir %s", contextDir))
}
logrus.Debugf("untar of %s successful", contextDir)
// All output (stdout, stderr) is captured in output as well
output := bytes.NewBuffer([]byte{})
commonOpts := &buildah.CommonBuildOptions{
AddHost: config.Add_hosts,
CgroupParent: config.Cgroup_parent,
CPUPeriod: uint64(config.Cpu_period),
CPUQuota: config.Cpu_quota,
CPUSetCPUs: config.Cpuset_cpus,
CPUSetMems: config.Cpuset_mems,
Memory: memoryLimit,
MemorySwap: memorySwap,
ShmSize: config.Shm_size,
Ulimit: config.Ulimit,
Volumes: config.Volume,
AddHost: config.BuildOptions.AddHosts,
CgroupParent: config.BuildOptions.CgroupParent,
CPUPeriod: uint64(config.BuildOptions.CpuPeriod),
CPUQuota: config.BuildOptions.CpuQuota,
CPUSetCPUs: config.BuildOptions.CpusetCpus,
CPUSetMems: config.BuildOptions.CpusetMems,
Memory: config.BuildOptions.Memory,
MemorySwap: config.BuildOptions.MemorySwap,
ShmSize: config.BuildOptions.ShmSize,
Ulimit: config.BuildOptions.Ulimit,
Volumes: config.BuildOptions.Volume,
}
hostNetwork := buildah.NamespaceOption{
@ -197,37 +161,68 @@ func (i *LibpodAPI) BuildImage(call iopodman.VarlinkCall, config iopodman.BuildI
namespace = append(namespace, hostNetwork)
options := imagebuildah.BuildOptions{
ContextDirectory: contextDir,
PullPolicy: pullPolicy,
Compression: imagebuildah.Gzip,
Quiet: false,
//SignaturePolicyPath:
Args: config.Build_args,
//Output:
AdditionalTags: config.Tags,
//Runtime: runtime.
//RuntimeArgs: ,
OutputFormat: manifestType,
SystemContext: &systemContext,
CommonBuildOpts: commonOpts,
Squash: config.Squash,
Labels: config.Label,
Annotations: config.Annotations,
ReportWriter: output,
NamespaceOptions: namespace,
CommonBuildOpts: commonOpts,
AdditionalTags: config.AdditionalTags,
Annotations: config.Annotations,
Args: config.BuildArgs,
CNIConfigDir: config.CniConfigDir,
CNIPluginPath: config.CniPluginDir,
Compression: stringCompressionToArchiveType(config.Compression),
ContextDirectory: newContextDir,
DefaultMountsFilePath: config.DefaultsMountFilePath,
Err: output,
ForceRmIntermediateCtrs: config.ForceRmIntermediateCtrs,
IIDFile: config.Iidfile,
Labels: config.Label,
Layers: config.Layers,
NoCache: config.Nocache,
Out: output,
Output: config.Output,
NamespaceOptions: namespace,
OutputFormat: config.OutputFormat,
PullPolicy: stringPullPolicyToType(config.PullPolicy),
Quiet: config.Quiet,
RemoveIntermediateCtrs: config.RemoteIntermediateCtrs,
ReportWriter: output,
RuntimeArgs: config.RuntimeArgs,
SignaturePolicyPath: config.SignaturePolicyPath,
Squash: config.Squash,
SystemContext: &systemContext,
}
if call.WantsMore() {
call.Continues = true
}
c := build(i.Runtime, options, config.Dockerfile)
var newPathDockerFiles []string
for _, d := range config.Dockerfiles {
if strings.HasPrefix(d, "http://") ||
strings.HasPrefix(d, "https://") ||
strings.HasPrefix(d, "git://") ||
strings.HasPrefix(d, "github.com/") {
newPathDockerFiles = append(newPathDockerFiles, d)
continue
}
base := filepath.Base(d)
newPathDockerFiles = append(newPathDockerFiles, filepath.Join(newContextDir, base))
}
c := build(i.Runtime, options, newPathDockerFiles)
var log []string
done := false
for {
line, err := output.ReadString('\n')
outputLine, err := output.ReadString('\n')
if err == nil {
log = append(log, line)
log = append(log, outputLine)
if call.WantsMore() {
// we want to reply with what we have
br := iopodman.MoreResponse{
Logs: log,
}
call.ReplyBuildImage(br)
log = []string{}
}
continue
} else if err == io.EOF {
select {
@ -237,15 +232,10 @@ func (i *LibpodAPI) BuildImage(call iopodman.VarlinkCall, config iopodman.BuildI
}
done = true
default:
if !call.WantsMore() {
if call.WantsMore() {
time.Sleep(1 * time.Second)
break
}
br := iopodman.MoreResponse{
Logs: log,
}
call.ReplyBuildImage(br)
log = []string{}
}
} else {
return call.ReplyErrorOccurred(err.Error())
@ -255,7 +245,8 @@ func (i *LibpodAPI) BuildImage(call iopodman.VarlinkCall, config iopodman.BuildI
}
}
call.Continues = false
newImage, err := i.Runtime.ImageRuntime().NewFromLocal(config.Tags[0])
newImage, err := i.Runtime.ImageRuntime().NewFromLocal(config.Output)
if err != nil {
return call.ReplyErrorOccurred(err.Error())
}

View file

@ -8,6 +8,7 @@ import (
"os"
"github.com/containers/libpod/cmd/podman/varlink"
"github.com/sirupsen/logrus"
)
// SendFile allows a client to send a file to the varlink server
@ -34,6 +35,7 @@ func (i *LibpodAPI) SendFile(call iopodman.VarlinkCall, ftype string, length int
return err
}
logrus.Debugf("successfully received %s", outputFile.Name())
// Send an ACK to the client
call.Call.Writer.WriteString(fmt.Sprintf("%s:", outputFile.Name()))
call.Call.Writer.Flush()

View file

@ -3,11 +3,14 @@ package varlinkapi
import (
"context"
"strconv"
"strings"
"time"
"github.com/containers/buildah"
"github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/libpod"
"github.com/containers/storage/pkg/archive"
)
// getContext returns a non-nil, empty context
@ -133,3 +136,27 @@ func handlePodCall(call iopodman.VarlinkCall, pod *libpod.Pod, ctrErrs map[strin
return nil
}
func stringCompressionToArchiveType(s string) archive.Compression {
switch strings.ToUpper(s) {
case "BZIP2":
return archive.Bzip2
case "GZIP":
return archive.Gzip
case "XZ":
return archive.Xz
}
return archive.Uncompressed
}
func stringPullPolicyToType(s string) buildah.PullPolicy {
switch strings.ToUpper(s) {
case "PULLIFMISSING":
return buildah.PullIfMissing
case "PULLALWAYS":
return buildah.PullAlways
case "PULLNEVER":
return buildah.PullNever
}
return buildah.PullIfMissing
}