summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/bindings/images/images.go11
-rw-r--r--pkg/domain/entities/engine_container.go1
-rw-r--r--pkg/domain/entities/engine_image.go2
-rw-r--r--pkg/domain/entities/generate.go22
-rw-r--r--pkg/domain/entities/images.go12
-rw-r--r--pkg/domain/entities/types.go10
-rw-r--r--pkg/domain/infra/abi/generate.go174
-rw-r--r--pkg/domain/infra/abi/images.go33
-rw-r--r--pkg/domain/infra/tunnel/generate.go12
-rw-r--r--pkg/domain/infra/tunnel/images.go14
-rw-r--r--pkg/rootless/rootless_linux.c48
-rw-r--r--pkg/rootlessport/rootlessport_linux.go26
-rw-r--r--pkg/spec/spec.go9
-rw-r--r--pkg/specgen/generate/container_create.go1
-rw-r--r--pkg/specgen/namespaces.go2
15 files changed, 302 insertions, 75 deletions
diff --git a/pkg/bindings/images/images.go b/pkg/bindings/images/images.go
index 06f01c7a0..63fe2556b 100644
--- a/pkg/bindings/images/images.go
+++ b/pkg/bindings/images/images.go
@@ -57,7 +57,7 @@ func List(ctx context.Context, all *bool, filters map[string][]string) ([]*entit
// Get performs an image inspect. To have the on-disk size of the image calculated, you can
// use the optional size parameter.
-func GetImage(ctx context.Context, nameOrID string, size *bool) (*entities.ImageData, error) {
+func GetImage(ctx context.Context, nameOrID string, size *bool) (*entities.ImageInspectReport, error) {
conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
@@ -66,7 +66,7 @@ func GetImage(ctx context.Context, nameOrID string, size *bool) (*entities.Image
if size != nil {
params.Set("size", strconv.FormatBool(*size))
}
- inspectedData := entities.ImageData{}
+ inspectedData := entities.ImageInspectReport{}
response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/json", params, nameOrID)
if err != nil {
return &inspectedData, err
@@ -310,9 +310,10 @@ func Push(ctx context.Context, source string, destination string, options entiti
params := url.Values{}
params.Set("credentials", options.Credentials)
params.Set("destination", destination)
- if options.TLSVerify != types.OptionalBoolUndefined {
- val := bool(options.TLSVerify == types.OptionalBoolTrue)
- params.Set("tlsVerify", strconv.FormatBool(val))
+ if options.SkipTLSVerify != types.OptionalBoolUndefined {
+ // Note: we have to verify if skipped is false.
+ verifyTLS := bool(options.SkipTLSVerify == types.OptionalBoolFalse)
+ params.Set("tlsVerify", strconv.FormatBool(verifyTLS))
}
path := fmt.Sprintf("/images/%s/push", source)
diff --git a/pkg/domain/entities/engine_container.go b/pkg/domain/entities/engine_container.go
index 502279bcf..eebf4c033 100644
--- a/pkg/domain/entities/engine_container.go
+++ b/pkg/domain/entities/engine_container.go
@@ -41,6 +41,7 @@ type ContainerEngine interface {
ContainerUnpause(ctx context.Context, namesOrIds []string, options PauseUnPauseOptions) ([]*PauseUnpauseReport, error)
ContainerWait(ctx context.Context, namesOrIds []string, options WaitOptions) ([]WaitReport, error)
Events(ctx context.Context, opts EventsOptions) error
+ GenerateSystemd(ctx context.Context, nameOrID string, opts GenerateSystemdOptions) (*GenerateSystemdReport, error)
HealthCheckRun(ctx context.Context, nameOrId string, options HealthCheckOptions) (*define.HealthCheckResults, error)
Info(ctx context.Context) (*define.Info, error)
PodCreate(ctx context.Context, opts PodCreateOptions) (*PodCreateReport, error)
diff --git a/pkg/domain/entities/engine_image.go b/pkg/domain/entities/engine_image.go
index b118a4104..46a96ca20 100644
--- a/pkg/domain/entities/engine_image.go
+++ b/pkg/domain/entities/engine_image.go
@@ -13,7 +13,7 @@ type ImageEngine interface {
Exists(ctx context.Context, nameOrId string) (*BoolReport, error)
History(ctx context.Context, nameOrId string, opts ImageHistoryOptions) (*ImageHistoryReport, error)
Import(ctx context.Context, opts ImageImportOptions) (*ImageImportReport, error)
- Inspect(ctx context.Context, names []string, opts InspectOptions) (*ImageInspectReport, error)
+ Inspect(ctx context.Context, namesOrIDs []string, opts InspectOptions) ([]*ImageInspectReport, error)
List(ctx context.Context, opts ImageListOptions) ([]*ImageSummary, error)
Load(ctx context.Context, opts ImageLoadOptions) (*ImageLoadReport, error)
Prune(ctx context.Context, opts ImagePruneOptions) (*ImagePruneReport, error)
diff --git a/pkg/domain/entities/generate.go b/pkg/domain/entities/generate.go
new file mode 100644
index 000000000..6d65b52f8
--- /dev/null
+++ b/pkg/domain/entities/generate.go
@@ -0,0 +1,22 @@
+package entities
+
+// GenerateSystemdOptions control the generation of systemd unit files.
+type GenerateSystemdOptions struct {
+ // Files - generate files instead of printing to stdout.
+ Files bool
+ // Name - use container/pod name instead of its ID.
+ Name bool
+ // New - create a new container instead of starting a new one.
+ New bool
+ // RestartPolicy - systemd restart policy.
+ RestartPolicy string
+ // StopTimeout - time when stopping the container.
+ StopTimeout *uint
+}
+
+// GenerateSystemdReport
+type GenerateSystemdReport struct {
+ // Output of the generate process. Either the generated files or their
+ // entire content.
+ Output string
+}
diff --git a/pkg/domain/entities/images.go b/pkg/domain/entities/images.go
index 460965b34..442b2cf3c 100644
--- a/pkg/domain/entities/images.go
+++ b/pkg/domain/entities/images.go
@@ -183,8 +183,8 @@ type ImagePushOptions struct {
// SignBy adds a signature at the destination using the specified key.
// Ignored for remote calls.
SignBy string
- // TLSVerify to enable/disable HTTPS and certificate verification.
- TLSVerify types.OptionalBool
+ // SkipTLSVerify to skip HTTPS and certificate verification.
+ SkipTLSVerify types.OptionalBool
}
// ImageSearchOptions are the arguments for searching images.
@@ -238,13 +238,9 @@ type ImagePruneReport struct {
type ImageTagOptions struct{}
type ImageUntagOptions struct{}
-type ImageData struct {
- *inspect.ImageData
-}
-
+// ImageInspectReport is the data when inspecting an image.
type ImageInspectReport struct {
- Images []*ImageData
- Errors map[string]error
+ *inspect.ImageData
}
type ImageLoadOptions struct {
diff --git a/pkg/domain/entities/types.go b/pkg/domain/entities/types.go
index d742cc53d..9fbe04c9a 100644
--- a/pkg/domain/entities/types.go
+++ b/pkg/domain/entities/types.go
@@ -47,10 +47,14 @@ type NetOptions struct {
// All CLI inspect commands and inspect sub-commands use the same options
type InspectOptions struct {
+ // Format - change the output to JSON or a Go template.
Format string `json:",omitempty"`
- Latest bool `json:",omitempty"`
- Size bool `json:",omitempty"`
- Type string `json:",omitempty"`
+ // Latest - inspect the latest container Podman is aware of.
+ Latest bool `json:",omitempty"`
+ // Size (containers only) - display total file size.
+ Size bool `json:",omitempty"`
+ // Type -- return JSON for specified type.
+ Type string `json:",omitempty"`
}
// All API and CLI diff commands and diff sub-commands use the same options
diff --git a/pkg/domain/infra/abi/generate.go b/pkg/domain/infra/abi/generate.go
new file mode 100644
index 000000000..f69ba560e
--- /dev/null
+++ b/pkg/domain/infra/abi/generate.go
@@ -0,0 +1,174 @@
+package abi
+
+import (
+ "context"
+ "fmt"
+ "strings"
+
+ "github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/containers/libpod/pkg/systemd/generate"
+ "github.com/pkg/errors"
+)
+
+func (ic *ContainerEngine) GenerateSystemd(ctx context.Context, nameOrID string, options entities.GenerateSystemdOptions) (*entities.GenerateSystemdReport, error) {
+ opts := generate.Options{
+ Files: options.Files,
+ New: options.New,
+ }
+
+ // First assume it's a container.
+ if info, found, err := ic.generateSystemdgenContainerInfo(nameOrID, nil, options); found && err != nil {
+ return nil, err
+ } else if found && err == nil {
+ output, err := generate.CreateContainerSystemdUnit(info, opts)
+ if err != nil {
+ return nil, err
+ }
+ return &entities.GenerateSystemdReport{Output: output}, nil
+ }
+
+ // --new does not support pods.
+ if options.New {
+ return nil, errors.Errorf("error generating systemd unit files: cannot generate generic files for a pod")
+ }
+
+ // We're either having a pod or garbage.
+ pod, err := ic.Libpod.LookupPod(nameOrID)
+ if err != nil {
+ return nil, err
+ }
+
+ // Error out if the pod has no infra container, which we require to be the
+ // main service.
+ if !pod.HasInfraContainer() {
+ return nil, fmt.Errorf("error generating systemd unit files: Pod %q has no infra container", pod.Name())
+ }
+
+ // Generate a systemdgen.ContainerInfo for the infra container. This
+ // ContainerInfo acts as the main service of the pod.
+ infraID, err := pod.InfraContainerID()
+ if err != nil {
+ return nil, nil
+ }
+ podInfo, _, err := ic.generateSystemdgenContainerInfo(infraID, pod, options)
+ if err != nil {
+ return nil, err
+ }
+
+ // Compute the container-dependency graph for the Pod.
+ containers, err := pod.AllContainers()
+ if err != nil {
+ return nil, err
+ }
+ if len(containers) == 0 {
+ return nil, fmt.Errorf("error generating systemd unit files: Pod %q has no containers", pod.Name())
+ }
+ graph, err := libpod.BuildContainerGraph(containers)
+ if err != nil {
+ return nil, err
+ }
+
+ // Traverse the dependency graph and create systemdgen.ContainerInfo's for
+ // each container.
+ containerInfos := []*generate.ContainerInfo{podInfo}
+ for ctr, dependencies := range graph.DependencyMap() {
+ // Skip the infra container as we already generated it.
+ if ctr.ID() == infraID {
+ continue
+ }
+ ctrInfo, _, err := ic.generateSystemdgenContainerInfo(ctr.ID(), nil, options)
+ if err != nil {
+ return nil, err
+ }
+ // Now add the container's dependencies and at the container as a
+ // required service of the infra container.
+ for _, dep := range dependencies {
+ if dep.ID() == infraID {
+ ctrInfo.BoundToServices = append(ctrInfo.BoundToServices, podInfo.ServiceName)
+ } else {
+ _, serviceName := generateServiceName(dep, nil, options)
+ ctrInfo.BoundToServices = append(ctrInfo.BoundToServices, serviceName)
+ }
+ }
+ podInfo.RequiredServices = append(podInfo.RequiredServices, ctrInfo.ServiceName)
+ containerInfos = append(containerInfos, ctrInfo)
+ }
+
+ // Now generate the systemd service for all containers.
+ builder := strings.Builder{}
+ for i, info := range containerInfos {
+ if i > 0 {
+ builder.WriteByte('\n')
+ }
+ out, err := generate.CreateContainerSystemdUnit(info, opts)
+ if err != nil {
+ return nil, err
+ }
+ builder.WriteString(out)
+ }
+
+ return &entities.GenerateSystemdReport{Output: builder.String()}, nil
+}
+
+// generateSystemdgenContainerInfo is a helper to generate a
+// systemdgen.ContainerInfo for `GenerateSystemd`.
+func (ic *ContainerEngine) generateSystemdgenContainerInfo(nameOrID string, pod *libpod.Pod, options entities.GenerateSystemdOptions) (*generate.ContainerInfo, bool, error) {
+ ctr, err := ic.Libpod.LookupContainer(nameOrID)
+ if err != nil {
+ return nil, false, err
+ }
+
+ timeout := ctr.StopTimeout()
+ if options.StopTimeout != nil {
+ timeout = *options.StopTimeout
+ }
+
+ config := ctr.Config()
+ conmonPidFile := config.ConmonPidFile
+ if conmonPidFile == "" {
+ return nil, true, errors.Errorf("conmon PID file path is empty, try to recreate the container with --conmon-pidfile flag")
+ }
+
+ createCommand := []string{}
+ if config.CreateCommand != nil {
+ createCommand = config.CreateCommand
+ } else if options.New {
+ return nil, true, errors.Errorf("cannot use --new on container %q: no create command found", nameOrID)
+ }
+
+ name, serviceName := generateServiceName(ctr, pod, options)
+ info := &generate.ContainerInfo{
+ ServiceName: serviceName,
+ ContainerName: name,
+ RestartPolicy: options.RestartPolicy,
+ PIDFile: conmonPidFile,
+ StopTimeout: timeout,
+ GenerateTimestamp: true,
+ CreateCommand: createCommand,
+ }
+
+ return info, true, nil
+}
+
+// generateServiceName generates the container name and the service name for systemd service.
+func generateServiceName(ctr *libpod.Container, pod *libpod.Pod, options entities.GenerateSystemdOptions) (string, string) {
+ var kind, name, ctrName string
+ if pod == nil {
+ kind = "container"
+ name = ctr.ID()
+ if options.Name {
+ name = ctr.Name()
+ }
+ ctrName = name
+ } else {
+ kind = "pod"
+ name = pod.ID()
+ ctrName = ctr.ID()
+ if options.Name {
+ name = pod.Name()
+ ctrName = ctr.Name()
+ }
+ }
+ return ctrName, fmt.Sprintf("%s-%s", kind, name)
+}
diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go
index 7ac111745..d1245a45c 100644
--- a/pkg/domain/infra/abi/images.go
+++ b/pkg/domain/infra/abi/images.go
@@ -170,29 +170,24 @@ func (ir *ImageEngine) Pull(ctx context.Context, rawImage string, options entiti
return &entities.ImagePullReport{Images: foundIDs}, nil
}
-func (ir *ImageEngine) Inspect(ctx context.Context, names []string, opts entities.InspectOptions) (*entities.ImageInspectReport, error) {
- report := entities.ImageInspectReport{
- Errors: make(map[string]error),
- }
-
- for _, id := range names {
- img, err := ir.Libpod.ImageRuntime().NewFromLocal(id)
+func (ir *ImageEngine) Inspect(ctx context.Context, namesOrIDs []string, opts entities.InspectOptions) ([]*entities.ImageInspectReport, error) {
+ reports := []*entities.ImageInspectReport{}
+ for _, i := range namesOrIDs {
+ img, err := ir.Libpod.ImageRuntime().NewFromLocal(i)
if err != nil {
- report.Errors[id] = err
- continue
+ return nil, err
}
-
- results, err := img.Inspect(ctx)
+ result, err := img.Inspect(ctx)
if err != nil {
- report.Errors[id] = err
- continue
+ return nil, err
}
-
- cookedResults := entities.ImageData{}
- _ = domainUtils.DeepCopy(&cookedResults, results)
- report.Images = append(report.Images, &cookedResults)
+ report := entities.ImageInspectReport{}
+ if err := domainUtils.DeepCopy(&report, result); err != nil {
+ return nil, err
+ }
+ reports = append(reports, &report)
}
- return &report, nil
+ return reports, nil
}
func (ir *ImageEngine) Push(ctx context.Context, source string, destination string, options entities.ImagePushOptions) error {
@@ -226,7 +221,7 @@ func (ir *ImageEngine) Push(ctx context.Context, source string, destination stri
dockerRegistryOptions := image.DockerRegistryOptions{
DockerRegistryCreds: registryCreds,
DockerCertPath: options.CertDir,
- DockerInsecureSkipTLSVerify: options.TLSVerify,
+ DockerInsecureSkipTLSVerify: options.SkipTLSVerify,
}
signOptions := image.SigningOptions{
diff --git a/pkg/domain/infra/tunnel/generate.go b/pkg/domain/infra/tunnel/generate.go
new file mode 100644
index 000000000..3cd483053
--- /dev/null
+++ b/pkg/domain/infra/tunnel/generate.go
@@ -0,0 +1,12 @@
+package tunnel
+
+import (
+ "context"
+
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/pkg/errors"
+)
+
+func (ic *ContainerEngine) GenerateSystemd(ctx context.Context, nameOrID string, options entities.GenerateSystemdOptions) (*entities.GenerateSystemdReport, error) {
+ return nil, errors.New("not implemented for tunnel")
+}
diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go
index 66e4e6e3f..dcc5fc3e7 100644
--- a/pkg/domain/infra/tunnel/images.go
+++ b/pkg/domain/infra/tunnel/images.go
@@ -143,16 +143,16 @@ func (ir *ImageEngine) Untag(ctx context.Context, nameOrId string, tags []string
return nil
}
-func (ir *ImageEngine) Inspect(_ context.Context, names []string, opts entities.InspectOptions) (*entities.ImageInspectReport, error) {
- report := entities.ImageInspectReport{}
- for _, id := range names {
- r, err := images.GetImage(ir.ClientCxt, id, &opts.Size)
+func (ir *ImageEngine) Inspect(ctx context.Context, namesOrIDs []string, opts entities.InspectOptions) ([]*entities.ImageInspectReport, error) {
+ reports := []*entities.ImageInspectReport{}
+ for _, i := range namesOrIDs {
+ r, err := images.GetImage(ir.ClientCxt, i, &opts.Size)
if err != nil {
- report.Errors[id] = err
+ return nil, err
}
- report.Images = append(report.Images, r)
+ reports = append(reports, r)
}
- return &report, nil
+ return reports, nil
}
func (ir *ImageEngine) Load(ctx context.Context, opts entities.ImageLoadOptions) (*entities.ImageLoadReport, error) {
diff --git a/pkg/rootless/rootless_linux.c b/pkg/rootless/rootless_linux.c
index 72d461cdc..716db81dc 100644
--- a/pkg/rootless/rootless_linux.c
+++ b/pkg/rootless/rootless_linux.c
@@ -535,32 +535,30 @@ create_pause_process (const char *pause_pid_file_path, char **argv)
}
}
-static void
-join_namespace_or_die (int pid_to_join, const char *ns_file)
+static int
+open_namespace (int pid_to_join, const char *ns_file)
{
char ns_path[PATH_MAX];
int ret;
- int fd;
ret = snprintf (ns_path, PATH_MAX, "/proc/%d/ns/%s", pid_to_join, ns_file);
if (ret == PATH_MAX)
{
fprintf (stderr, "internal error: namespace path too long\n");
- _exit (EXIT_FAILURE);
+ return -1;
}
- fd = open (ns_path, O_CLOEXEC | O_RDONLY);
- if (fd < 0)
- {
- fprintf (stderr, "cannot open: %s\n", ns_path);
- _exit (EXIT_FAILURE);
- }
- if (setns (fd, 0) < 0)
+ return open (ns_path, O_CLOEXEC | O_RDONLY);
+}
+
+static void
+join_namespace_or_die (const char *name, int ns_fd)
+{
+ if (setns (ns_fd, 0) < 0)
{
- fprintf (stderr, "cannot set namespace to %s: %s\n", ns_path, strerror (errno));
+ fprintf (stderr, "cannot set %s namespace\n", name);
_exit (EXIT_FAILURE);
}
- close (fd);
}
int
@@ -570,6 +568,8 @@ reexec_userns_join (int pid_to_join, char *pause_pid_file_path)
char gid[16];
char **argv;
int pid;
+ int mnt_ns = -1;
+ int user_ns = -1;
char *cwd = getcwd (NULL, 0);
sigset_t sigset, oldsigset;
@@ -589,14 +589,28 @@ reexec_userns_join (int pid_to_join, char *pause_pid_file_path)
_exit (EXIT_FAILURE);
}
+ user_ns = open_namespace (pid_to_join, "user");
+ if (user_ns < 0)
+ return user_ns;
+ mnt_ns = open_namespace (pid_to_join, "mnt");
+ if (mnt_ns < 0)
+ {
+ close (user_ns);
+ return mnt_ns;
+ }
+
pid = fork ();
if (pid < 0)
fprintf (stderr, "cannot fork: %s\n", strerror (errno));
if (pid)
{
- /* We passed down these fds, close them. */
int f;
+
+ /* We passed down these fds, close them. */
+ close (user_ns);
+ close (mnt_ns);
+
for (f = 3; f < open_files_max_fd; f++)
if (open_files_set == NULL || FD_ISSET (f % FD_SETSIZE, &(open_files_set[f / FD_SETSIZE])))
close (f);
@@ -634,8 +648,10 @@ reexec_userns_join (int pid_to_join, char *pause_pid_file_path)
_exit (EXIT_FAILURE);
}
- join_namespace_or_die (pid_to_join, "user");
- join_namespace_or_die (pid_to_join, "mnt");
+ join_namespace_or_die ("user", user_ns);
+ join_namespace_or_die ("mnt", mnt_ns);
+ close (user_ns);
+ close (mnt_ns);
if (syscall_setresgid (0, 0, 0) < 0)
{
diff --git a/pkg/rootlessport/rootlessport_linux.go b/pkg/rootlessport/rootlessport_linux.go
index 1c1ed39df..c686d80fc 100644
--- a/pkg/rootlessport/rootlessport_linux.go
+++ b/pkg/rootlessport/rootlessport_linux.go
@@ -102,25 +102,27 @@ func parent() error {
return err
}
- sigC := make(chan os.Signal, 1)
- signal.Notify(sigC, unix.SIGPIPE)
- defer func() {
- // dummy signal to terminate the goroutine
- sigC <- unix.SIGKILL
- }()
+ exitC := make(chan os.Signal, 1)
+ defer close(exitC)
+
go func() {
+ sigC := make(chan os.Signal, 1)
+ signal.Notify(sigC, unix.SIGPIPE)
defer func() {
signal.Stop(sigC)
close(sigC)
}()
- s := <-sigC
- if s == unix.SIGPIPE {
- if f, err := os.OpenFile("/dev/null", os.O_WRONLY, 0755); err == nil {
- unix.Dup2(int(f.Fd()), 1) // nolint:errcheck
- unix.Dup2(int(f.Fd()), 2) // nolint:errcheck
- f.Close()
+ select {
+ case s := <-sigC:
+ if s == unix.SIGPIPE {
+ if f, err := os.OpenFile("/dev/null", os.O_WRONLY, 0755); err == nil {
+ unix.Dup2(int(f.Fd()), 1) // nolint:errcheck
+ unix.Dup2(int(f.Fd()), 2) // nolint:errcheck
+ f.Close()
+ }
}
+ case <-exitC:
}
}()
diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go
index 7ee2df890..a62344640 100644
--- a/pkg/spec/spec.go
+++ b/pkg/spec/spec.go
@@ -326,10 +326,6 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
}
defaultEnv = env.Join(env.DefaultEnvVariables, defaultEnv)
}
- config.Env = env.Join(defaultEnv, config.Env)
- for name, val := range config.Env {
- g.AddProcessEnv(name, val)
- }
if err := addRlimits(config, &g); err != nil {
return nil, err
@@ -360,6 +356,11 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
if err := config.Cgroup.ConfigureGenerator(&g); err != nil {
return nil, err
}
+
+ config.Env = env.Join(defaultEnv, config.Env)
+ for name, val := range config.Env {
+ g.AddProcessEnv(name, val)
+ }
configSpec := g.Config
// If the container image specifies an label with a
diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go
index bb84f0618..01ddcf9c8 100644
--- a/pkg/specgen/generate/container_create.go
+++ b/pkg/specgen/generate/container_create.go
@@ -76,6 +76,7 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
}
options := []libpod.CtrCreateOption{}
+ options = append(options, libpod.WithCreateCommand())
var newImage *image.Image
if s.Rootfs != "" {
diff --git a/pkg/specgen/namespaces.go b/pkg/specgen/namespaces.go
index f0161a793..396563267 100644
--- a/pkg/specgen/namespaces.go
+++ b/pkg/specgen/namespaces.go
@@ -216,6 +216,8 @@ func ParseNetworkNamespace(ns string) (Namespace, []string, error) {
toReturn := Namespace{}
var cniNetworks []string
switch {
+ case ns == "slirp4netns":
+ toReturn.NSMode = Slirp
case ns == "pod":
toReturn.NSMode = FromPod
case ns == "bridge":