summaryrefslogtreecommitdiff
path: root/pkg/domain
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/domain')
-rw-r--r--pkg/domain/entities/engine_container.go2
-rw-r--r--pkg/domain/entities/play.go16
-rw-r--r--pkg/domain/entities/system.go5
-rw-r--r--pkg/domain/entities/types/auth.go3
-rw-r--r--pkg/domain/entities/types/types.go3
-rw-r--r--pkg/domain/filters/volumes.go20
-rw-r--r--pkg/domain/infra/abi/containers.go14
-rw-r--r--pkg/domain/infra/abi/containers_runlabel.go25
-rw-r--r--pkg/domain/infra/abi/generate.go172
-rw-r--r--pkg/domain/infra/abi/play.go127
-rw-r--r--pkg/domain/infra/abi/system.go26
-rw-r--r--pkg/domain/infra/abi/terminal/terminal_linux.go4
-rw-r--r--pkg/domain/infra/tunnel/containers.go2
-rw-r--r--pkg/domain/infra/tunnel/network.go3
-rw-r--r--pkg/domain/infra/tunnel/play.go2
-rw-r--r--pkg/domain/infra/tunnel/system.go2
16 files changed, 325 insertions, 101 deletions
diff --git a/pkg/domain/entities/engine_container.go b/pkg/domain/entities/engine_container.go
index bcab617af..f695d32fd 100644
--- a/pkg/domain/entities/engine_container.go
+++ b/pkg/domain/entities/engine_container.go
@@ -88,7 +88,7 @@ type ContainerEngine interface {
SecretRm(ctx context.Context, nameOrID []string, opts SecretRmOptions) ([]*SecretRmReport, error)
Shutdown(ctx context.Context)
SystemDf(ctx context.Context, options SystemDfOptions) (*SystemDfReport, error)
- Unshare(ctx context.Context, args []string) error
+ Unshare(ctx context.Context, args []string, options SystemUnshareOptions) error
Version(ctx context.Context) (*SystemVersionReport, error)
VolumeCreate(ctx context.Context, opts VolumeCreateOptions) (*IDOrNameResponse, error)
VolumeExists(ctx context.Context, namesOrID string) (*BoolReport, error)
diff --git a/pkg/domain/entities/play.go b/pkg/domain/entities/play.go
index 6883fe6c5..c69bb0867 100644
--- a/pkg/domain/entities/play.go
+++ b/pkg/domain/entities/play.go
@@ -1,6 +1,10 @@
package entities
-import "github.com/containers/image/v5/types"
+import (
+ "net"
+
+ "github.com/containers/image/v5/types"
+)
// PlayKubeOptions controls playing kube YAML files.
type PlayKubeOptions struct {
@@ -24,6 +28,8 @@ type PlayKubeOptions struct {
// SeccompProfileRoot - path to a directory containing seccomp
// profiles.
SeccompProfileRoot string
+ // StaticIPs - Static IP address used by the pod(s).
+ StaticIPs []net.IP
// ConfigMaps - slice of pathnames to kubernetes configmap YAMLs.
ConfigMaps []string
// LogDriver for the container. For example: journald
@@ -45,8 +51,16 @@ type PlayKubePod struct {
ContainerErrors []string
}
+// PlayKubeVolume represents a single volume created by play kube.
+type PlayKubeVolume struct {
+ // Name - Name of the volume created by play kube.
+ Name string
+}
+
// PlayKubeReport contains the results of running play kube.
type PlayKubeReport struct {
// Pods - pods created by play kube.
Pods []PlayKubePod
+ // Volumes - volumes created by play kube.
+ Volumes []PlayKubeVolume
}
diff --git a/pkg/domain/entities/system.go b/pkg/domain/entities/system.go
index 1a671d59e..31a6185dc 100644
--- a/pkg/domain/entities/system.go
+++ b/pkg/domain/entities/system.go
@@ -98,6 +98,11 @@ type SystemVersionReport struct {
Server *define.Version `json:",omitempty"`
}
+// SystemUnshareOptions describes the options for the unshare command
+type SystemUnshareOptions struct {
+ RootlessCNI bool
+}
+
type ComponentVersion struct {
types.Version
}
diff --git a/pkg/domain/entities/types/auth.go b/pkg/domain/entities/types/auth.go
index ddf15bb18..7f2480173 100644
--- a/pkg/domain/entities/types/auth.go
+++ b/pkg/domain/entities/types/auth.go
@@ -1,4 +1,5 @@
-package types // import "github.com/docker/docker/api/types"
+// copied from github.com/docker/docker/api/types
+package types
// AuthConfig contains authorization information for connecting to a Registry
type AuthConfig struct {
diff --git a/pkg/domain/entities/types/types.go b/pkg/domain/entities/types/types.go
index 77834c0cb..7dc785078 100644
--- a/pkg/domain/entities/types/types.go
+++ b/pkg/domain/entities/types/types.go
@@ -1,4 +1,5 @@
-package types // import "github.com/docker/docker/api/types"
+// copied from github.com/docker/docker/api/types
+package types
// ComponentVersion describes the version information for a specific component.
type ComponentVersion struct {
diff --git a/pkg/domain/filters/volumes.go b/pkg/domain/filters/volumes.go
index 9b2fc5280..9a08adf82 100644
--- a/pkg/domain/filters/volumes.go
+++ b/pkg/domain/filters/volumes.go
@@ -75,7 +75,25 @@ func GenerateVolumeFilters(filters url.Values) ([]libpod.VolumeFilter, error) {
return dangling
})
default:
- return nil, errors.Errorf("%q is in an invalid volume filter", filter)
+ return nil, errors.Errorf("%q is an invalid volume filter", filter)
+ }
+ }
+ }
+ return vf, nil
+}
+
+func GeneratePruneVolumeFilters(filters url.Values) ([]libpod.VolumeFilter, error) {
+ var vf []libpod.VolumeFilter
+ for filter, v := range filters {
+ for _, val := range v {
+ switch filter {
+ case "label":
+ filter := val
+ vf = append(vf, func(v *libpod.Volume) bool {
+ return util.MatchLabelFilters([]string{filter}, v.Labels())
+ })
+ default:
+ return nil, errors.Errorf("%q is an invalid volume filter", filter)
}
}
}
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go
index 24261e5ed..6f8845f10 100644
--- a/pkg/domain/infra/abi/containers.go
+++ b/pkg/domain/infra/abi/containers.go
@@ -585,7 +585,7 @@ func (ic *ContainerEngine) ContainerAttach(ctx context.Context, nameOrID string,
}
// If the container is in a pod, also set to recursively start dependencies
- err = terminal.StartAttachCtr(ctx, ctr, options.Stdout, options.Stderr, options.Stdin, options.DetachKeys, options.SigProxy, false, ctr.PodID() != "")
+ err = terminal.StartAttachCtr(ctx, ctr, options.Stdout, options.Stderr, options.Stdin, options.DetachKeys, options.SigProxy, false)
if err != nil && errors.Cause(err) != define.ErrDetach {
return errors.Wrapf(err, "error attaching to container %s", ctr.ID())
}
@@ -708,7 +708,7 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri
ctrRunning := ctrState == define.ContainerStateRunning
if options.Attach {
- err = terminal.StartAttachCtr(ctx, ctr, options.Stdout, options.Stderr, options.Stdin, options.DetachKeys, options.SigProxy, !ctrRunning, ctr.PodID() != "")
+ err = terminal.StartAttachCtr(ctx, ctr, options.Stdout, options.Stderr, options.Stdin, options.DetachKeys, options.SigProxy, !ctrRunning)
if errors.Cause(err) == define.ErrDetach {
// User manually detached
// Exit cleanly immediately
@@ -784,7 +784,7 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri
RawInput: rawInput,
ExitCode: 125,
}
- if err := ctr.Start(ctx, ctr.PodID() != ""); err != nil {
+ if err := ctr.Start(ctx, true); err != nil {
// if lastError != nil {
// fmt.Fprintln(os.Stderr, lastError)
// }
@@ -845,10 +845,6 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta
}
}
- var joinPod bool
- if len(ctr.PodID()) > 0 {
- joinPod = true
- }
report := entities.ContainerRunReport{Id: ctr.ID()}
if logrus.GetLevel() == logrus.DebugLevel {
@@ -859,7 +855,7 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta
}
if opts.Detach {
// if the container was created as part of a pod, also start its dependencies, if any.
- if err := ctr.Start(ctx, joinPod); err != nil {
+ if err := ctr.Start(ctx, true); err != nil {
// This means the command did not exist
report.ExitCode = define.ExitCode(err)
return &report, err
@@ -869,7 +865,7 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta
}
// if the container was created as part of a pod, also start its dependencies, if any.
- if err := terminal.StartAttachCtr(ctx, ctr, opts.OutputStream, opts.ErrorStream, opts.InputStream, opts.DetachKeys, opts.SigProxy, true, joinPod); err != nil {
+ if err := terminal.StartAttachCtr(ctx, ctr, opts.OutputStream, opts.ErrorStream, opts.InputStream, opts.DetachKeys, opts.SigProxy, true); err != nil {
// We've manually detached from the container
// Do not perform cleanup, or wait for container exit code
// Just exit immediately
diff --git a/pkg/domain/infra/abi/containers_runlabel.go b/pkg/domain/infra/abi/containers_runlabel.go
index 8de383926..2cabab988 100644
--- a/pkg/domain/infra/abi/containers_runlabel.go
+++ b/pkg/domain/infra/abi/containers_runlabel.go
@@ -177,6 +177,16 @@ func generateRunlabelCommand(runlabel string, img *image.Image, args []string, o
return cmd, env, nil
}
+func replaceName(arg, name string) string {
+ newarg := strings.ReplaceAll(arg, "$NAME", name)
+ return strings.ReplaceAll(newarg, "${NAME}", name)
+}
+
+func replaceImage(arg, image string) string {
+ newarg := strings.ReplaceAll(arg, "$IMAGE", image)
+ return strings.ReplaceAll(newarg, "${IMAGE}", image)
+}
+
// generateCommand takes a label (string) and converts it to an executable command
func generateCommand(command, imageName, name, globalOpts string) ([]string, error) {
if name == "" {
@@ -196,26 +206,15 @@ func generateCommand(command, imageName, name, globalOpts string) ([]string, err
for _, arg := range cmd[1:] {
var newArg string
switch arg {
- case "IMAGE":
- newArg = imageName
- case "$IMAGE":
- newArg = imageName
case "IMAGE=IMAGE":
newArg = fmt.Sprintf("IMAGE=%s", imageName)
- case "IMAGE=$IMAGE":
- newArg = fmt.Sprintf("IMAGE=%s", imageName)
- case "NAME":
- newArg = name
case "NAME=NAME":
newArg = fmt.Sprintf("NAME=%s", name)
- case "NAME=$NAME":
- newArg = fmt.Sprintf("NAME=%s", name)
- case "$NAME":
- newArg = name
case "$GLOBAL_OPTS":
newArg = globalOpts
default:
- newArg = arg
+ newArg = replaceName(arg, name)
+ newArg = replaceImage(newArg, imageName)
}
newCommand = append(newCommand, newArg)
}
diff --git a/pkg/domain/infra/abi/generate.go b/pkg/domain/infra/abi/generate.go
index 94f649e15..b0853b554 100644
--- a/pkg/domain/infra/abi/generate.go
+++ b/pkg/domain/infra/abi/generate.go
@@ -4,6 +4,7 @@ import (
"bytes"
"context"
"fmt"
+ "strings"
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/libpod/define"
@@ -43,120 +44,174 @@ func (ic *ContainerEngine) GenerateSystemd(ctx context.Context, nameOrID string,
func (ic *ContainerEngine) GenerateKube(ctx context.Context, nameOrIDs []string, options entities.GenerateKubeOptions) (*entities.GenerateKubeReport, error) {
var (
- pods []*libpod.Pod
- ctrs []*libpod.Container
- kubePods []*k8sAPI.Pod
- kubeServices []k8sAPI.Service
- content []byte
+ pods []*libpod.Pod
+ ctrs []*libpod.Container
+ vols []*libpod.Volume
+ podContent [][]byte
+ content [][]byte
)
+
+ // Lookup for podman objects.
for _, nameOrID := range nameOrIDs {
- // Get the container in question
+ // Let's assume it's a container, so get the container.
ctr, err := ic.Libpod.LookupContainer(nameOrID)
if err != nil {
- pod, err := ic.Libpod.LookupPod(nameOrID)
- if err != nil {
+ if !strings.Contains(err.Error(), "no such container") {
return nil, err
}
- pods = append(pods, pod)
} else {
if len(ctr.Dependencies()) > 0 {
return nil, errors.Wrapf(define.ErrNotImplemented, "containers with dependencies")
}
- // we cannot deal with ctrs already in a pod
+ // we cannot deal with ctrs already in a pod.
if len(ctr.PodID()) > 0 {
return nil, errors.Errorf("container %s is associated with pod %s: use generate on the pod itself", ctr.ID(), ctr.PodID())
}
ctrs = append(ctrs, ctr)
+ continue
+ }
+
+ // Maybe it's a pod.
+ pod, err := ic.Libpod.LookupPod(nameOrID)
+ if err != nil {
+ if !strings.Contains(err.Error(), "no such pod") {
+ return nil, err
+ }
+ } else {
+ pods = append(pods, pod)
+ continue
+ }
+
+ // Or volume.
+ vol, err := ic.Libpod.LookupVolume(nameOrID)
+ if err != nil {
+ if !strings.Contains(err.Error(), "no such volume") {
+ return nil, err
+ }
+ } else {
+ vols = append(vols, vol)
+ continue
}
+
+ // If it reaches here is because the name or id did not exist.
+ return nil, errors.Errorf("Name or ID %q not found", nameOrID)
}
- // check our inputs
- if len(pods) > 0 && len(ctrs) > 0 {
- return nil, errors.New("cannot generate pods and containers at the same time")
+ // Generate kube persistent volume claims from volumes.
+ if len(vols) >= 1 {
+ pvs, err := getKubePVCs(vols)
+ if err != nil {
+ return nil, err
+ }
+
+ content = append(content, pvs...)
}
+ // Generate kube pods and services from pods.
if len(pods) >= 1 {
pos, svcs, err := getKubePods(pods, options.Service)
if err != nil {
return nil, err
}
- kubePods = append(kubePods, pos...)
+ podContent = append(podContent, pos...)
if options.Service {
- kubeServices = append(kubeServices, svcs...)
+ content = append(content, svcs...)
}
- } else {
+ }
+
+ // Generate the kube pods from containers.
+ if len(ctrs) >= 1 {
po, err := libpod.GenerateForKube(ctrs)
if err != nil {
return nil, err
}
- kubePods = append(kubePods, po)
+ b, err := generateKubeYAML(po)
+ if err != nil {
+ return nil, err
+ }
+
+ podContent = append(podContent, b)
if options.Service {
- kubeServices = append(kubeServices, libpod.GenerateKubeServiceFromV1Pod(po, []k8sAPI.ServicePort{}))
+ b, err := generateKubeYAML(libpod.GenerateKubeServiceFromV1Pod(po, []k8sAPI.ServicePort{}))
+ if err != nil {
+ return nil, err
+ }
+ content = append(content, b)
}
}
- content, err := generateKubeOutput(kubePods, kubeServices, options.Service)
+ // Content order is based on helm install order (secret, persistentVolumeClaim, service, pod).
+ content = append(content, podContent...)
+
+ // Generate kube YAML file from all kube kinds.
+ k, err := generateKubeOutput(content)
if err != nil {
return nil, err
}
- return &entities.GenerateKubeReport{Reader: bytes.NewReader(content)}, nil
+ return &entities.GenerateKubeReport{Reader: bytes.NewReader(k)}, nil
}
-func getKubePods(pods []*libpod.Pod, getService bool) ([]*k8sAPI.Pod, []k8sAPI.Service, error) {
- kubePods := make([]*k8sAPI.Pod, 0)
- kubeServices := make([]k8sAPI.Service, 0)
+// getKubePods returns kube pod and service YAML files from podman pods.
+func getKubePods(pods []*libpod.Pod, getService bool) ([][]byte, [][]byte, error) {
+ pos := [][]byte{}
+ svcs := [][]byte{}
for _, p := range pods {
- po, svc, err := p.GenerateForKube()
+ po, sp, err := p.GenerateForKube()
+ if err != nil {
+ return nil, nil, err
+ }
+
+ b, err := generateKubeYAML(po)
if err != nil {
return nil, nil, err
}
+ pos = append(pos, b)
- kubePods = append(kubePods, po)
if getService {
- kubeServices = append(kubeServices, libpod.GenerateKubeServiceFromV1Pod(po, svc))
+ b, err := generateKubeYAML(libpod.GenerateKubeServiceFromV1Pod(po, sp))
+ if err != nil {
+ return nil, nil, err
+ }
+ svcs = append(svcs, b)
}
}
- return kubePods, kubeServices, nil
+ return pos, svcs, nil
}
-func generateKubeOutput(kubePods []*k8sAPI.Pod, kubeServices []k8sAPI.Service, hasService bool) ([]byte, error) {
- output := make([]byte, 0)
- marshalledPods := make([]byte, 0)
- marshalledServices := make([]byte, 0)
+// getKubePVCs returns kube persistent volume claim YAML files from podman volumes.
+func getKubePVCs(volumes []*libpod.Volume) ([][]byte, error) {
+ pvs := [][]byte{}
- for i, p := range kubePods {
- if i != 0 {
- marshalledPods = append(marshalledPods, []byte("---\n")...)
- }
-
- b, err := yaml.Marshal(p)
+ for _, v := range volumes {
+ b, err := generateKubeYAML(v.GenerateForKube())
if err != nil {
return nil, err
}
-
- marshalledPods = append(marshalledPods, b...)
+ pvs = append(pvs, b)
}
- if hasService {
- for i, s := range kubeServices {
- if i != 0 {
- marshalledServices = append(marshalledServices, []byte("---\n")...)
- }
-
- b, err := yaml.Marshal(s)
- if err != nil {
- return nil, err
- }
+ return pvs, nil
+}
- marshalledServices = append(marshalledServices, b...)
- }
+// generateKubeYAML marshalls a kube kind into a YAML file.
+func generateKubeYAML(kubeKind interface{}) ([]byte, error) {
+ b, err := yaml.Marshal(kubeKind)
+ if err != nil {
+ return nil, err
}
+ return b, nil
+}
+
+// generateKubeOutput generates kube YAML file containing multiple kube kinds.
+func generateKubeOutput(content [][]byte) ([]byte, error) {
+ output := make([]byte, 0)
+
header := `# Generation of Kubernetes YAML is still under development!
#
# Save the output of this file and use kubectl create -f to import
@@ -169,13 +224,18 @@ func generateKubeOutput(kubePods []*k8sAPI.Pod, kubeServices []k8sAPI.Service, h
return nil, err
}
+ // Add header to kube YAML file.
output = append(output, []byte(fmt.Sprintf(header, podmanVersion.Version))...)
- // kube generate order is based on helm install order (service, pod...)
- if hasService {
- output = append(output, marshalledServices...)
- output = append(output, []byte("---\n")...)
+
+ // kube generate order is based on helm install order (secret, persistentVolume, service, pod...).
+ // Add kube kinds.
+ for i, b := range content {
+ if i != 0 {
+ output = append(output, []byte("---\n")...)
+ }
+
+ output = append(output, b...)
}
- output = append(output, marshalledPods...)
return output, nil
}
diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go
index 3b5c141d7..4a13a8029 100644
--- a/pkg/domain/infra/abi/play.go
+++ b/pkg/domain/infra/abi/play.go
@@ -7,6 +7,7 @@ import (
"io"
"io/ioutil"
"os"
+ "strconv"
"strings"
"github.com/containers/common/pkg/secrets"
@@ -15,6 +16,7 @@ import (
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/libpod/image"
"github.com/containers/podman/v3/pkg/domain/entities"
+ "github.com/containers/podman/v3/pkg/specgen"
"github.com/containers/podman/v3/pkg/specgen/generate"
"github.com/containers/podman/v3/pkg/specgen/generate/kube"
"github.com/containers/podman/v3/pkg/util"
@@ -43,6 +45,14 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en
return nil, err
}
+ // sort kube kinds
+ documentList, err = sortKubeKinds(documentList)
+ if err != nil {
+ return nil, errors.Wrapf(err, "unable to sort kube kinds in %q", path)
+ }
+
+ ipIndex := 0
+
// create pod on each document if it is a pod or deployment
// any other kube kind will be skipped
for _, document := range documentList {
@@ -63,7 +73,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en
podTemplateSpec.ObjectMeta = podYAML.ObjectMeta
podTemplateSpec.Spec = podYAML.Spec
- r, err := ic.playKubePod(ctx, podTemplateSpec.ObjectMeta.Name, &podTemplateSpec, options)
+ r, err := ic.playKubePod(ctx, podTemplateSpec.ObjectMeta.Name, &podTemplateSpec, options, &ipIndex)
if err != nil {
return nil, err
}
@@ -77,13 +87,27 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en
return nil, errors.Wrapf(err, "unable to read YAML %q as Kube Deployment", path)
}
- r, err := ic.playKubeDeployment(ctx, &deploymentYAML, options)
+ r, err := ic.playKubeDeployment(ctx, &deploymentYAML, options, &ipIndex)
if err != nil {
return nil, err
}
report.Pods = append(report.Pods, r.Pods...)
validKinds++
+ case "PersistentVolumeClaim":
+ var pvcYAML v1.PersistentVolumeClaim
+
+ if err := yaml.Unmarshal(document, &pvcYAML); err != nil {
+ return nil, errors.Wrapf(err, "unable to read YAML %q as Kube PersistentVolumeClaim", path)
+ }
+
+ r, err := ic.playKubePVC(ctx, &pvcYAML, options)
+ if err != nil {
+ return nil, err
+ }
+
+ report.Volumes = append(report.Volumes, r.Volumes...)
+ validKinds++
default:
logrus.Infof("kube kind %s not supported", kind)
continue
@@ -97,7 +121,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en
return report, nil
}
-func (ic *ContainerEngine) playKubeDeployment(ctx context.Context, deploymentYAML *v1apps.Deployment, options entities.PlayKubeOptions) (*entities.PlayKubeReport, error) {
+func (ic *ContainerEngine) playKubeDeployment(ctx context.Context, deploymentYAML *v1apps.Deployment, options entities.PlayKubeOptions, ipIndex *int) (*entities.PlayKubeReport, error) {
var (
deploymentName string
podSpec v1.PodTemplateSpec
@@ -119,7 +143,7 @@ func (ic *ContainerEngine) playKubeDeployment(ctx context.Context, deploymentYAM
// create "replicas" number of pods
for i = 0; i < numReplicas; i++ {
podName := fmt.Sprintf("%s-pod-%d", deploymentName, i)
- podReport, err := ic.playKubePod(ctx, podName, &podSpec, options)
+ podReport, err := ic.playKubePod(ctx, podName, &podSpec, options, ipIndex)
if err != nil {
return nil, errors.Wrapf(err, "error encountered while bringing up pod %s", podName)
}
@@ -128,7 +152,7 @@ func (ic *ContainerEngine) playKubeDeployment(ctx context.Context, deploymentYAM
return &report, nil
}
-func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podYAML *v1.PodTemplateSpec, options entities.PlayKubeOptions) (*entities.PlayKubeReport, error) {
+func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podYAML *v1.PodTemplateSpec, options entities.PlayKubeOptions, ipIndex *int) (*entities.PlayKubeReport, error) {
var (
registryCreds *types.DockerAuthConfig
writer io.Writer
@@ -169,9 +193,17 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
// networks.
networks := strings.Split(options.Network, ",")
logrus.Debugf("Pod joining CNI networks: %v", networks)
+ p.NetNS.NSMode = specgen.Bridge
p.CNINetworks = append(p.CNINetworks, networks...)
}
}
+ if len(options.StaticIPs) > *ipIndex {
+ p.StaticIP = &options.StaticIPs[*ipIndex]
+ *ipIndex++
+ } else if len(options.StaticIPs) > 0 {
+ // only warn if the user has set at least one ip ip
+ logrus.Warn("No more static ips left using a random one")
+ }
// Create the Pod
pod, err := generate.MakePod(p, ic.Libpod)
@@ -279,6 +311,7 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
RestartPolicy: ctrRestartPolicy,
NetNSIsHost: p.NetNS.IsHost(),
SecretsManager: secretsManager,
+ LogDriver: options.LogDriver,
}
specGen, err := kube.ToSpecGen(ctx, &specgenOpts)
if err != nil {
@@ -313,6 +346,68 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
return &report, nil
}
+// playKubePVC creates a podman volume from a kube persistent volume claim.
+func (ic *ContainerEngine) playKubePVC(ctx context.Context, pvcYAML *v1.PersistentVolumeClaim, options entities.PlayKubeOptions) (*entities.PlayKubeReport, error) {
+ var report entities.PlayKubeReport
+ opts := make(map[string]string)
+
+ // Get pvc name.
+ // This is the only required pvc attribute to create a podman volume.
+ name := pvcYAML.GetName()
+ if strings.TrimSpace(name) == "" {
+ return nil, fmt.Errorf("persistent volume claim name can not be empty")
+ }
+
+ // Create podman volume options.
+ volOptions := []libpod.VolumeCreateOption{
+ libpod.WithVolumeName(name),
+ libpod.WithVolumeLabels(pvcYAML.GetLabels()),
+ }
+
+ // Get pvc annotations and create remaining podman volume options if available.
+ // These are podman volume options that do not match any of the persistent volume claim
+ // attributes, so they can be configured using annotations since they will not affect k8s.
+ for k, v := range pvcYAML.GetAnnotations() {
+ switch k {
+ case util.VolumeDriverAnnotation:
+ volOptions = append(volOptions, libpod.WithVolumeDriver(v))
+ case util.VolumeDeviceAnnotation:
+ opts["device"] = v
+ case util.VolumeTypeAnnotation:
+ opts["type"] = v
+ case util.VolumeUIDAnnotation:
+ uid, err := strconv.Atoi(v)
+ if err != nil {
+ return nil, errors.Wrapf(err, "cannot convert uid %s to integer", v)
+ }
+ volOptions = append(volOptions, libpod.WithVolumeUID(uid))
+ opts["UID"] = v
+ case util.VolumeGIDAnnotation:
+ gid, err := strconv.Atoi(v)
+ if err != nil {
+ return nil, errors.Wrapf(err, "cannot convert gid %s to integer", v)
+ }
+ volOptions = append(volOptions, libpod.WithVolumeGID(gid))
+ opts["GID"] = v
+ case util.VolumeMountOptsAnnotation:
+ opts["o"] = v
+ }
+ }
+ volOptions = append(volOptions, libpod.WithVolumeOptions(opts))
+
+ // Create volume.
+ vol, err := ic.Libpod.NewVolume(ctx, volOptions...)
+ if err != nil {
+ return nil, err
+ }
+
+ report.Volumes = append(report.Volumes, entities.PlayKubeVolume{
+ Name: vol.Name(),
+ })
+
+ return &report, nil
+}
+
// readConfigMapFromFile returns a kubernetes configMap obtained from --configmap flag
func readConfigMapFromFile(r io.Reader) (v1.ConfigMap, error) {
var cm v1.ConfigMap
@@ -374,3 +469,25 @@ func getKubeKind(obj []byte) (string, error) {
return kubeObject.Kind, nil
}
+
+// sortKubeKinds adds the correct creation order for the kube kinds.
+// Any pod dependecy will be created first like volumes, secrets, etc.
+func sortKubeKinds(documentList [][]byte) ([][]byte, error) {
+ var sortedDocumentList [][]byte
+
+ for _, document := range documentList {
+ kind, err := getKubeKind(document)
+ if err != nil {
+ return nil, err
+ }
+
+ switch kind {
+ case "Pod", "Deployment":
+ sortedDocumentList = append(sortedDocumentList, document)
+ default:
+ sortedDocumentList = append([][]byte{document}, sortedDocumentList...)
+ }
+ }
+
+ return sortedDocumentList, nil
+}
diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go
index a3e753384..f87f9e370 100644
--- a/pkg/domain/infra/abi/system.go
+++ b/pkg/domain/infra/abi/system.go
@@ -390,13 +390,25 @@ func unshareEnv(graphroot, runroot string) []string {
fmt.Sprintf("CONTAINERS_RUNROOT=%s", runroot))
}
-func (ic *ContainerEngine) Unshare(ctx context.Context, args []string) error {
- cmd := exec.Command(args[0], args[1:]...)
- cmd.Env = unshareEnv(ic.Libpod.StorageConfig().GraphRoot, ic.Libpod.StorageConfig().RunRoot)
- cmd.Stdin = os.Stdin
- cmd.Stdout = os.Stdout
- cmd.Stderr = os.Stderr
- return cmd.Run()
+func (ic *ContainerEngine) Unshare(ctx context.Context, args []string, options entities.SystemUnshareOptions) error {
+ unshare := func() error {
+ cmd := exec.Command(args[0], args[1:]...)
+ cmd.Env = unshareEnv(ic.Libpod.StorageConfig().GraphRoot, ic.Libpod.StorageConfig().RunRoot)
+ cmd.Stdin = os.Stdin
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ return cmd.Run()
+ }
+
+ if options.RootlessCNI {
+ rootlesscni, err := ic.Libpod.GetRootlessCNINetNs(true)
+ if err != nil {
+ return err
+ }
+ defer rootlesscni.Cleanup(ic.Libpod)
+ return rootlesscni.Do(unshare)
+ }
+ return unshare()
}
func (ic ContainerEngine) Version(ctx context.Context) (*entities.SystemVersionReport, error) {
diff --git a/pkg/domain/infra/abi/terminal/terminal_linux.go b/pkg/domain/infra/abi/terminal/terminal_linux.go
index 7a0c2907c..ab71f8f6f 100644
--- a/pkg/domain/infra/abi/terminal/terminal_linux.go
+++ b/pkg/domain/infra/abi/terminal/terminal_linux.go
@@ -39,7 +39,7 @@ func ExecAttachCtr(ctx context.Context, ctr *libpod.Container, execConfig *libpo
// StartAttachCtr starts and (if required) attaches to a container
// if you change the signature of this function from os.File to io.Writer, it will trigger a downstream
// error. we may need to just lint disable this one.
-func StartAttachCtr(ctx context.Context, ctr *libpod.Container, stdout, stderr, stdin *os.File, detachKeys string, sigProxy bool, startContainer bool, recursive bool) error { //nolint-interfacer
+func StartAttachCtr(ctx context.Context, ctr *libpod.Container, stdout, stderr, stdin *os.File, detachKeys string, sigProxy bool, startContainer bool) error { //nolint-interfacer
resize := make(chan define.TerminalSize)
haveTerminal := terminal.IsTerminal(int(os.Stdin.Fd()))
@@ -88,7 +88,7 @@ func StartAttachCtr(ctx context.Context, ctr *libpod.Container, stdout, stderr,
return ctr.Attach(streams, detachKeys, resize)
}
- attachChan, err := ctr.StartAndAttach(ctx, streams, detachKeys, resize, recursive)
+ attachChan, err := ctr.StartAndAttach(ctx, streams, detachKeys, resize, true)
if err != nil {
return err
}
diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go
index a0f65f11f..4545d266b 100644
--- a/pkg/domain/infra/tunnel/containers.go
+++ b/pkg/domain/infra/tunnel/containers.go
@@ -629,7 +629,7 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta
if opts.Detach {
// Detach and return early
- err := containers.Start(ic.ClientCtx, con.ID, nil)
+ err := containers.Start(ic.ClientCtx, con.ID, new(containers.StartOptions).WithRecursive(true))
if err != nil {
report.ExitCode = define.ExitCode(err)
}
diff --git a/pkg/domain/infra/tunnel/network.go b/pkg/domain/infra/tunnel/network.go
index adf34460c..7e59e44c2 100644
--- a/pkg/domain/infra/tunnel/network.go
+++ b/pkg/domain/infra/tunnel/network.go
@@ -92,5 +92,6 @@ func (ic *ContainerEngine) NetworkExists(ctx context.Context, networkname string
// Network prune removes unused cni networks
func (ic *ContainerEngine) NetworkPrune(ctx context.Context, options entities.NetworkPruneOptions) ([]*entities.NetworkPruneReport, error) {
- return network.Prune(ic.ClientCtx, nil)
+ opts := new(network.PruneOptions).WithFilters(options.Filters)
+ return network.Prune(ic.ClientCtx, opts)
}
diff --git a/pkg/domain/infra/tunnel/play.go b/pkg/domain/infra/tunnel/play.go
index 9f9076114..e52e1a1f7 100644
--- a/pkg/domain/infra/tunnel/play.go
+++ b/pkg/domain/infra/tunnel/play.go
@@ -11,7 +11,7 @@ import (
func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, opts entities.PlayKubeOptions) (*entities.PlayKubeReport, error) {
options := new(play.KubeOptions).WithAuthfile(opts.Authfile).WithUsername(opts.Username).WithPassword(opts.Password)
options.WithCertDir(opts.CertDir).WithQuiet(opts.Quiet).WithSignaturePolicy(opts.SignaturePolicy).WithConfigMaps(opts.ConfigMaps)
- options.WithLogDriver(opts.LogDriver).WithNetwork(opts.Network).WithSeccompProfileRoot(opts.SeccompProfileRoot)
+ options.WithLogDriver(opts.LogDriver).WithNetwork(opts.Network).WithSeccompProfileRoot(opts.SeccompProfileRoot).WithStaticIPs(opts.StaticIPs)
if s := opts.SkipTLSVerify; s != types.OptionalBoolUndefined {
options.WithSkipTLSVerify(s == types.OptionalBoolTrue)
diff --git a/pkg/domain/infra/tunnel/system.go b/pkg/domain/infra/tunnel/system.go
index d2c5063c9..7400d3771 100644
--- a/pkg/domain/infra/tunnel/system.go
+++ b/pkg/domain/infra/tunnel/system.go
@@ -28,7 +28,7 @@ func (ic *ContainerEngine) SystemDf(ctx context.Context, options entities.System
return system.DiskUsage(ic.ClientCtx, nil)
}
-func (ic *ContainerEngine) Unshare(ctx context.Context, args []string) error {
+func (ic *ContainerEngine) Unshare(ctx context.Context, args []string, options entities.SystemUnshareOptions) error {
return errors.New("unshare is not supported on remote clients")
}