mirror of
https://github.com/containers/podman
synced 2024-10-19 00:34:18 +00:00
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:
parent
fa3b91dc12
commit
ef85dd7950
95
API.md
95
API.md
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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...)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue