summaryrefslogtreecommitdiff
path: root/pkg/adapter
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/adapter')
-rw-r--r--pkg/adapter/containers.go145
-rw-r--r--pkg/adapter/containers_remote.go2
-rw-r--r--pkg/adapter/pods.go10
-rw-r--r--pkg/adapter/runtime.go18
-rw-r--r--pkg/adapter/runtime_remote.go7
-rw-r--r--pkg/adapter/volumes_remote.go2
6 files changed, 161 insertions, 23 deletions
diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go
index 45a9a54a3..41607145d 100644
--- a/pkg/adapter/containers.go
+++ b/pkg/adapter/containers.go
@@ -342,7 +342,8 @@ func (r *LocalRuntime) Run(ctx context.Context, c *cliconfig.RunValues, exitCode
if err := ctr.Start(ctx, c.IsSet("pod")); err != nil {
// This means the command did not exist
exitCode = 127
- if strings.Contains(err.Error(), "permission denied") || strings.Contains(err.Error(), "file not found") {
+ e := strings.ToLower(err.Error())
+ if strings.Contains(e, "permission denied") || strings.Contains(e, "operation not permitted") || strings.Contains(e, "file not found") || strings.Contains(e, "no such file or directory") {
exitCode = 126
}
return exitCode, err
@@ -405,12 +406,13 @@ func (r *LocalRuntime) Run(ctx context.Context, c *cliconfig.RunValues, exitCode
}
// This means the command did not exist
exitCode = 127
- if strings.Contains(err.Error(), "permission denied") {
+ e := strings.ToLower(err.Error())
+ if strings.Contains(e, "permission denied") || strings.Contains(e, "operation not permitted") {
exitCode = 126
}
if c.IsSet("rm") {
if deleteError := r.Runtime.RemoveContainer(ctx, ctr, true, false); deleteError != nil {
- logrus.Errorf("unable to remove container %s after failing to start and attach to it", ctr.ID())
+ logrus.Debugf("unable to remove container %s after failing to start and attach to it", ctr.ID())
}
}
return exitCode, err
@@ -1092,28 +1094,145 @@ func (r *LocalRuntime) Port(c *cliconfig.PortValues) ([]*Container, error) {
return portContainers, nil
}
-// GenerateSystemd creates a unit file for a container
-func (r *LocalRuntime) GenerateSystemd(c *cliconfig.GenerateSystemdValues) (string, error) {
- ctr, err := r.Runtime.LookupContainer(c.InputArgs[0])
+// generateServiceName generates the container name and the service name for systemd service.
+func generateServiceName(c *cliconfig.GenerateSystemdValues, ctr *libpod.Container, pod *libpod.Pod) (string, string) {
+ var kind, name, ctrName string
+ if pod == nil {
+ kind = "container"
+ name = ctr.ID()
+ if c.Name {
+ name = ctr.Name()
+ }
+ ctrName = name
+ } else {
+ kind = "pod"
+ name = pod.ID()
+ ctrName = ctr.ID()
+ if c.Name {
+ name = pod.Name()
+ ctrName = ctr.Name()
+ }
+ }
+ return ctrName, fmt.Sprintf("%s-%s", kind, name)
+}
+
+// generateSystemdgenContainerInfo is a helper to generate a
+// systemdgen.ContainerInfo for `GenerateSystemd`.
+func (r *LocalRuntime) generateSystemdgenContainerInfo(c *cliconfig.GenerateSystemdValues, nameOrID string, pod *libpod.Pod) (*systemdgen.ContainerInfo, bool, error) {
+ ctr, err := r.Runtime.LookupContainer(nameOrID)
if err != nil {
- return "", err
+ return nil, false, err
}
+
timeout := int(ctr.StopTimeout())
if c.StopTimeout >= 0 {
timeout = c.StopTimeout
}
- name := ctr.ID()
- if c.Name {
- name = ctr.Name()
- }
config := ctr.Config()
conmonPidFile := config.ConmonPidFile
if conmonPidFile == "" {
- return "", errors.Errorf("conmon PID file path is empty, try to recreate the container with --conmon-pidfile flag")
+ return nil, true, errors.Errorf("conmon PID file path is empty, try to recreate the container with --conmon-pidfile flag")
+ }
+
+ name, serviceName := generateServiceName(c, ctr, pod)
+ info := &systemdgen.ContainerInfo{
+ ServiceName: serviceName,
+ ContainerName: name,
+ RestartPolicy: c.RestartPolicy,
+ PIDFile: conmonPidFile,
+ StopTimeout: timeout,
+ GenerateTimestamp: true,
+ }
+
+ return info, true, nil
+}
+
+// GenerateSystemd creates a unit file for a container or pod.
+func (r *LocalRuntime) GenerateSystemd(c *cliconfig.GenerateSystemdValues) (string, error) {
+ // First assume it's a container.
+ if info, found, err := r.generateSystemdgenContainerInfo(c, c.InputArgs[0], nil); found && err != nil {
+ return "", err
+ } else if found && err == nil {
+ return systemdgen.CreateContainerSystemdUnit(info, c.Files)
+ }
+
+ // We're either having a pod or garbage.
+ pod, err := r.Runtime.LookupPod(c.InputArgs[0])
+ if err != nil {
+ return "", err
+ }
+
+ // Error out if the pod has no infra container, which we require to be the
+ // main service.
+ if !pod.HasInfraContainer() {
+ return "", 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
+ }
+ podInfo, _, err := r.generateSystemdgenContainerInfo(c, infraID, pod)
+ if err != nil {
+ return "", nil
+ }
+
+ // Compute the container-dependency graph for the Pod.
+ containers, err := pod.AllContainers()
+ if err != nil {
+ return "", err
+ }
+ if len(containers) == 0 {
+ return "", fmt.Errorf("error generating systemd unit files: Pod %q has no containers", pod.Name())
+ }
+ graph, err := libpod.BuildContainerGraph(containers)
+ if err != nil {
+ return "", err
+ }
+
+ // Traverse the dependency graph and create systemdgen.ContainerInfo's for
+ // each container.
+ containerInfos := []*systemdgen.ContainerInfo{podInfo}
+ for ctr, dependencies := range graph.DependencyMap() {
+ // Skip the infra container as we already generated it.
+ if ctr.ID() == infraID {
+ continue
+ }
+ ctrInfo, _, err := r.generateSystemdgenContainerInfo(c, ctr.ID(), nil)
+ if err != nil {
+ return "", 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(c, dep, nil)
+ 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 := systemdgen.CreateContainerSystemdUnit(info, c.Files)
+ if err != nil {
+ return "", err
+ }
+ builder.WriteString(out)
}
- return systemdgen.CreateSystemdUnitAsString(name, ctr.ID(), c.RestartPolicy, conmonPidFile, timeout)
+ return builder.String(), nil
}
// GetNamespaces returns namespace information about a container for PS
diff --git a/pkg/adapter/containers_remote.go b/pkg/adapter/containers_remote.go
index 5a26f537f..590fef43f 100644
--- a/pkg/adapter/containers_remote.go
+++ b/pkg/adapter/containers_remote.go
@@ -951,7 +951,7 @@ func (r *LocalRuntime) Port(c *cliconfig.PortValues) ([]*Container, error) {
// GenerateSystemd creates a systemd until for a container
func (r *LocalRuntime) GenerateSystemd(c *cliconfig.GenerateSystemdValues) (string, error) {
- return iopodman.GenerateSystemd().Call(r.Conn, c.InputArgs[0], c.RestartPolicy, int64(c.StopTimeout), c.Name)
+ return "", errors.New("systemd generation not supported for remote clients")
}
// GetNamespaces returns namespace information about a container for PS
diff --git a/pkg/adapter/pods.go b/pkg/adapter/pods.go
index 1dd72babf..ded805de2 100644
--- a/pkg/adapter/pods.go
+++ b/pkg/adapter/pods.go
@@ -256,6 +256,10 @@ func (r *LocalRuntime) CreatePod(ctx context.Context, cli *cliconfig.PodCreateVa
options = append(options, libpod.WithPodName(cli.Name))
}
+ if cli.Flag("hostname").Changed {
+ options = append(options, libpod.WithPodHostname(cli.Hostname))
+ }
+
if cli.Infra {
options = append(options, libpod.WithInfraContainer())
nsOptions, err := shared.GetNamespaceOptions(strings.Split(cli.Share, ","))
@@ -476,6 +480,12 @@ func (r *LocalRuntime) PlayKubeYAML(ctx context.Context, c *cliconfig.KubePlayVa
podOptions = append(podOptions, libpod.WithPodName(podName))
// TODO for now we just used the default kernel namespaces; we need to add/subtract this from yaml
+ hostname := podYAML.Spec.Hostname
+ if hostname == "" {
+ hostname = podName
+ }
+ podOptions = append(podOptions, libpod.WithPodHostname(hostname))
+
nsOptions, err := shared.GetNamespaceOptions(strings.Split(shared.DefaultKernelNamespaces, ","))
if err != nil {
return nil, err
diff --git a/pkg/adapter/runtime.go b/pkg/adapter/runtime.go
index ba988aaf7..0537308f8 100644
--- a/pkg/adapter/runtime.go
+++ b/pkg/adapter/runtime.go
@@ -201,16 +201,16 @@ func (r *LocalRuntime) RemoveVolumes(ctx context.Context, c *cliconfig.VolumeRmV
}
// Push is a wrapper to push an image to a registry
-func (r *LocalRuntime) Push(ctx context.Context, srcName, destination, manifestMIMEType, authfile, signaturePolicyPath string, writer io.Writer, forceCompress bool, signingOptions image.SigningOptions, dockerRegistryOptions *image.DockerRegistryOptions, additionalDockerArchiveTags []reference.NamedTagged) error {
+func (r *LocalRuntime) Push(ctx context.Context, srcName, destination, manifestMIMEType, authfile, digestfile, signaturePolicyPath string, writer io.Writer, forceCompress bool, signingOptions image.SigningOptions, dockerRegistryOptions *image.DockerRegistryOptions, additionalDockerArchiveTags []reference.NamedTagged) error {
newImage, err := r.ImageRuntime().NewFromLocal(srcName)
if err != nil {
return err
}
- return newImage.PushImageToHeuristicDestination(ctx, destination, manifestMIMEType, authfile, signaturePolicyPath, writer, forceCompress, signingOptions, dockerRegistryOptions, nil)
+ return newImage.PushImageToHeuristicDestination(ctx, destination, manifestMIMEType, authfile, digestfile, signaturePolicyPath, writer, forceCompress, signingOptions, dockerRegistryOptions, nil)
}
// InspectVolumes returns a slice of volumes based on an arg list or --all
-func (r *LocalRuntime) InspectVolumes(ctx context.Context, c *cliconfig.VolumeInspectValues) ([]*Volume, error) {
+func (r *LocalRuntime) InspectVolumes(ctx context.Context, c *cliconfig.VolumeInspectValues) ([]*libpod.InspectVolumeData, error) {
var (
volumes []*libpod.Volume
err error
@@ -230,7 +230,17 @@ func (r *LocalRuntime) InspectVolumes(ctx context.Context, c *cliconfig.VolumeIn
if err != nil {
return nil, err
}
- return libpodVolumeToVolume(volumes), nil
+
+ inspectVols := make([]*libpod.InspectVolumeData, 0, len(volumes))
+ for _, vol := range volumes {
+ inspectOut, err := vol.Inspect()
+ if err != nil {
+ return nil, errors.Wrapf(err, "error inspecting volume %s", vol.Name())
+ }
+ inspectVols = append(inspectVols, inspectOut)
+ }
+
+ return inspectVols, nil
}
// Volumes returns a slice of localruntime volumes
diff --git a/pkg/adapter/runtime_remote.go b/pkg/adapter/runtime_remote.go
index 420c9d0bb..8588966b6 100644
--- a/pkg/adapter/runtime_remote.go
+++ b/pkg/adapter/runtime_remote.go
@@ -21,7 +21,7 @@ import (
"github.com/containers/image/types"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/remoteclientconfig"
- "github.com/containers/libpod/cmd/podman/varlink"
+ iopodman "github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/libpod/events"
@@ -619,7 +619,7 @@ func (r *LocalRuntime) RemoveVolumes(ctx context.Context, c *cliconfig.VolumeRmV
return iopodman.VolumeRemove().Call(r.Conn, rmOpts)
}
-func (r *LocalRuntime) Push(ctx context.Context, srcName, destination, manifestMIMEType, authfile, signaturePolicyPath string, writer io.Writer, forceCompress bool, signingOptions image.SigningOptions, dockerRegistryOptions *image.DockerRegistryOptions, additionalDockerArchiveTags []reference.NamedTagged) error {
+func (r *LocalRuntime) Push(ctx context.Context, srcName, destination, manifestMIMEType, authfile, digestfile, signaturePolicyPath string, writer io.Writer, forceCompress bool, signingOptions image.SigningOptions, dockerRegistryOptions *image.DockerRegistryOptions, additionalDockerArchiveTags []reference.NamedTagged) error {
reply, err := iopodman.PushImage().Send(r.Conn, varlink.More, srcName, destination, forceCompress, manifestMIMEType, signingOptions.RemoveSignatures, signingOptions.SignBy)
if err != nil {
@@ -669,7 +669,6 @@ func varlinkVolumeToVolume(r *LocalRuntime, volumes []iopodman.Volume) []*Volume
MountPoint: v.MountPoint,
Driver: v.Driver,
Options: v.Options,
- Scope: v.Scope,
}
n := remoteVolume{
Runtime: r,
@@ -813,7 +812,7 @@ func IsImageNotFound(err error) bool {
// HealthCheck executes a container's healthcheck over a varlink connection
func (r *LocalRuntime) HealthCheck(c *cliconfig.HealthCheckValues) (string, error) {
- return "", define.ErrNotImplemented
+ return iopodman.HealthCheckRun().Call(r.Conn, c.InputArgs[0])
}
// Events monitors libpod/podman events over a varlink connection
diff --git a/pkg/adapter/volumes_remote.go b/pkg/adapter/volumes_remote.go
index beacd943a..58f9ba625 100644
--- a/pkg/adapter/volumes_remote.go
+++ b/pkg/adapter/volumes_remote.go
@@ -29,5 +29,5 @@ func (v *Volume) MountPoint() string {
// Scope returns the scope for an adapter.volume
func (v *Volume) Scope() string {
- return v.config.Scope
+ return "local"
}