summaryrefslogtreecommitdiff
path: root/pkg/domain
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/domain')
-rw-r--r--pkg/domain/entities/images.go41
-rw-r--r--pkg/domain/entities/system.go2
-rw-r--r--pkg/domain/entities/types.go4
-rw-r--r--pkg/domain/entities/types/auth.go22
-rw-r--r--pkg/domain/entities/types/types.go28
-rw-r--r--pkg/domain/entities/volumes.go96
-rw-r--r--pkg/domain/filters/containers.go59
-rw-r--r--pkg/domain/filters/pods.go21
-rw-r--r--pkg/domain/filters/volumes.go17
-rw-r--r--pkg/domain/infra/abi/containers.go2
-rw-r--r--pkg/domain/infra/abi/generate.go100
-rw-r--r--pkg/domain/infra/abi/play.go152
-rw-r--r--pkg/domain/infra/abi/play_test.go97
-rw-r--r--pkg/domain/infra/abi/system.go2
-rw-r--r--pkg/domain/infra/runtime_libpod.go8
15 files changed, 486 insertions, 165 deletions
diff --git a/pkg/domain/entities/images.go b/pkg/domain/entities/images.go
index 7999d8209..3cc46ed0a 100644
--- a/pkg/domain/entities/images.go
+++ b/pkg/domain/entities/images.go
@@ -8,33 +8,32 @@ import (
"github.com/containers/image/v5/types"
"github.com/containers/podman/v3/pkg/inspect"
"github.com/containers/podman/v3/pkg/trust"
- docker "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/opencontainers/go-digest"
v1 "github.com/opencontainers/image-spec/specs-go/v1"
)
type Image struct {
- ID string `json:"Id"`
- RepoTags []string `json:",omitempty"`
- RepoDigests []string `json:",omitempty"`
- Parent string `json:",omitempty"`
- Comment string `json:",omitempty"`
- Created string `json:",omitempty"`
- Container string `json:",omitempty"`
- ContainerConfig *container.Config `json:",omitempty"`
- DockerVersion string `json:",omitempty"`
- Author string `json:",omitempty"`
- Config *container.Config `json:",omitempty"`
- Architecture string `json:",omitempty"`
- Variant string `json:",omitempty"`
- Os string `json:",omitempty"`
- OsVersion string `json:",omitempty"`
- Size int64 `json:",omitempty"`
- VirtualSize int64 `json:",omitempty"`
- GraphDriver docker.GraphDriverData `json:",omitempty"`
- RootFS docker.RootFS `json:",omitempty"`
- Metadata docker.ImageMetadata `json:",omitempty"`
+ ID string `json:"Id"`
+ RepoTags []string `json:",omitempty"`
+ RepoDigests []string `json:",omitempty"`
+ Parent string `json:",omitempty"`
+ Comment string `json:",omitempty"`
+ Created string `json:",omitempty"`
+ Container string `json:",omitempty"`
+ ContainerConfig *container.Config `json:",omitempty"`
+ DockerVersion string `json:",omitempty"`
+ Author string `json:",omitempty"`
+ Config *container.Config `json:",omitempty"`
+ Architecture string `json:",omitempty"`
+ Variant string `json:",omitempty"`
+ Os string `json:",omitempty"`
+ OsVersion string `json:",omitempty"`
+ Size int64 `json:",omitempty"`
+ VirtualSize int64 `json:",omitempty"`
+ GraphDriver string `json:",omitempty"`
+ RootFS string `json:",omitempty"`
+ Metadata string `json:",omitempty"`
// Podman extensions
Digest digest.Digest `json:",omitempty"`
diff --git a/pkg/domain/entities/system.go b/pkg/domain/entities/system.go
index 4b8383613..1a671d59e 100644
--- a/pkg/domain/entities/system.go
+++ b/pkg/domain/entities/system.go
@@ -5,7 +5,7 @@ import (
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/pkg/domain/entities/reports"
- "github.com/docker/docker/api/types"
+ "github.com/containers/podman/v3/pkg/domain/entities/types"
"github.com/spf13/cobra"
)
diff --git a/pkg/domain/entities/types.go b/pkg/domain/entities/types.go
index 9efc64c93..02e374111 100644
--- a/pkg/domain/entities/types.go
+++ b/pkg/domain/entities/types.go
@@ -3,7 +3,7 @@ package entities
import (
"net"
- "github.com/containers/buildah/imagebuildah"
+ buildahDefine "github.com/containers/buildah/define"
"github.com/containers/podman/v3/libpod/events"
"github.com/containers/podman/v3/pkg/specgen"
"github.com/containers/storage/pkg/archive"
@@ -91,7 +91,7 @@ type ContainerCreateResponse struct {
// BuildOptions describe the options for building container images.
type BuildOptions struct {
- imagebuildah.BuildOptions
+ buildahDefine.BuildOptions
}
// BuildReport is the image-build report.
diff --git a/pkg/domain/entities/types/auth.go b/pkg/domain/entities/types/auth.go
new file mode 100644
index 000000000..ddf15bb18
--- /dev/null
+++ b/pkg/domain/entities/types/auth.go
@@ -0,0 +1,22 @@
+package types // import "github.com/docker/docker/api/types"
+
+// AuthConfig contains authorization information for connecting to a Registry
+type AuthConfig struct {
+ Username string `json:"username,omitempty"`
+ Password string `json:"password,omitempty"`
+ Auth string `json:"auth,omitempty"`
+
+ // Email is an optional value associated with the username.
+ // This field is deprecated and will be removed in a later
+ // version of docker.
+ Email string `json:"email,omitempty"`
+
+ ServerAddress string `json:"serveraddress,omitempty"`
+
+ // IdentityToken is used to authenticate the user and get
+ // an access token for the registry.
+ IdentityToken string `json:"identitytoken,omitempty"`
+
+ // RegistryToken is a bearer token to be sent to a registry
+ RegistryToken string `json:"registrytoken,omitempty"`
+}
diff --git a/pkg/domain/entities/types/types.go b/pkg/domain/entities/types/types.go
new file mode 100644
index 000000000..77834c0cb
--- /dev/null
+++ b/pkg/domain/entities/types/types.go
@@ -0,0 +1,28 @@
+package types // import "github.com/docker/docker/api/types"
+
+// ComponentVersion describes the version information for a specific component.
+type ComponentVersion struct {
+ Name string
+ Version string
+ Details map[string]string `json:",omitempty"`
+}
+
+// Version contains response of Engine API:
+// GET "/version"
+type Version struct {
+ Platform struct{ Name string } `json:",omitempty"`
+ Components []ComponentVersion `json:",omitempty"`
+
+ // The following fields are deprecated, they relate to the Engine component and are kept for backwards compatibility
+
+ Version string
+ APIVersion string `json:"ApiVersion"`
+ MinAPIVersion string `json:"MinAPIVersion,omitempty"`
+ GitCommit string
+ GoVersion string
+ Os string
+ Arch string
+ KernelVersion string `json:",omitempty"`
+ Experimental bool `json:",omitempty"`
+ BuildTime string `json:",omitempty"`
+}
diff --git a/pkg/domain/entities/volumes.go b/pkg/domain/entities/volumes.go
index beb2a75ac..55a6a1b14 100644
--- a/pkg/domain/entities/volumes.go
+++ b/pkg/domain/entities/volumes.go
@@ -4,10 +4,72 @@ import (
"net/url"
"github.com/containers/podman/v3/libpod/define"
- docker_api_types "github.com/docker/docker/api/types"
- docker_api_types_volume "github.com/docker/docker/api/types/volume"
)
+// Volume volume
+// swagger:model Volume
+type volume struct {
+
+ // Date/Time the volume was created.
+ CreatedAt string `json:"CreatedAt,omitempty"`
+
+ // Name of the volume driver used by the volume.
+ // Required: true
+ Driver string `json:"Driver"`
+
+ // User-defined key/value metadata.
+ // Required: true
+ Labels map[string]string `json:"Labels"`
+
+ // Mount path of the volume on the host.
+ // Required: true
+ Mountpoint string `json:"Mountpoint"`
+
+ // Name of the volume.
+ // Required: true
+ Name string `json:"Name"`
+
+ // The driver specific options used when creating the volume.
+ //
+ // Required: true
+ Options map[string]string `json:"Options"`
+
+ // The level at which the volume exists. Either `global` for cluster-wide,
+ // or `local` for machine level.
+ //
+ // Required: true
+ Scope string `json:"Scope"`
+
+ // Low-level details about the volume, provided by the volume driver.
+ // Details are returned as a map with key/value pairs:
+ // `{"key":"value","key2":"value2"}`.
+ //
+ // The `Status` field is optional, and is omitted if the volume driver
+ // does not support this feature.
+ //
+ Status map[string]interface{} `json:"Status,omitempty"`
+
+ // usage data
+ UsageData *VolumeUsageData `json:"UsageData,omitempty"`
+}
+
+type VolumeUsageData struct {
+
+ // The number of containers referencing this volume. This field
+ // is set to `-1` if the reference-count is not available.
+ //
+ // Required: true
+ RefCount int64 `json:"RefCount"`
+
+ // Amount of disk space used by the volume (in bytes). This information
+ // is only available for volumes created with the `"local"` volume
+ // driver. For volumes created with other volume drivers, this field
+ // is set to `-1` ("not available")
+ //
+ // Required: true
+ Size int64 `json:"Size"`
+}
+
// swagger:model VolumeCreate
type VolumeCreateOptions struct {
// New volume's name. Can be left blank
@@ -113,14 +175,14 @@ type SwagVolumeListResponse struct {
*/
// swagger:model DockerVolumeCreate
-type DockerVolumeCreate docker_api_types_volume.VolumeCreateBody
+type DockerVolumeCreate VolumeCreateBody
// This response definition is used for both the create and inspect endpoints
// swagger:response DockerVolumeInfoResponse
type SwagDockerVolumeInfoResponse struct {
// in:body
Body struct {
- docker_api_types.Volume
+ volume
}
}
@@ -129,6 +191,30 @@ type SwagDockerVolumeInfoResponse struct {
type SwagDockerVolumePruneResponse struct {
// in:body
Body struct {
- docker_api_types.VolumesPruneReport
+ // docker_api_types.VolumesPruneReport
}
}
+
+// VolumeCreateBody Volume configuration
+// swagger:model VolumeCreateBody
+type VolumeCreateBody struct {
+
+ // Name of the volume driver to use.
+ // Required: true
+ Driver string `json:"Driver"`
+
+ // A mapping of driver options and values. These options are
+ // passed directly to the driver and are driver specific.
+ //
+ // Required: true
+ DriverOpts map[string]string `json:"DriverOpts"`
+
+ // User-defined key/value metadata.
+ // Required: true
+ Labels map[string]string `json:"Labels"`
+
+ // The new volume's name. If not specified, Docker generates a name.
+ //
+ // Required: true
+ Name string `json:"Name"`
+}
diff --git a/pkg/domain/filters/containers.go b/pkg/domain/filters/containers.go
index 02727e841..19d704da1 100644
--- a/pkg/domain/filters/containers.go
+++ b/pkg/domain/filters/containers.go
@@ -23,27 +23,7 @@ func GenerateContainerFilterFuncs(filter string, filterValues []string, r *libpo
case "label":
// we have to match that all given labels exits on that container
return func(c *libpod.Container) bool {
- labels := c.Labels()
- for _, filterValue := range filterValues {
- matched := false
- filterArray := strings.SplitN(filterValue, "=", 2)
- filterKey := filterArray[0]
- if len(filterArray) > 1 {
- filterValue = filterArray[1]
- } else {
- filterValue = ""
- }
- for labelKey, labelValue := range labels {
- if labelKey == filterKey && (filterValue == "" || labelValue == filterValue) {
- matched = true
- break
- }
- }
- if !matched {
- return false
- }
- }
- return true
+ return util.MatchLabelFilters(filterValues, c.Labels())
}, nil
case "name":
// we only have to match one name
@@ -185,16 +165,7 @@ func GenerateContainerFilterFuncs(filter string, filterValues []string, r *libpo
return false
}, nil
case "until":
- until, err := util.ComputeUntilTimestamp(filter, filterValues)
- if err != nil {
- return nil, err
- }
- return func(c *libpod.Container) bool {
- if !until.IsZero() && c.CreatedTime().After((until)) {
- return true
- }
- return false
- }, nil
+ return prepareUntilFilterFunc(filterValues)
case "pod":
var pods []*libpod.Pod
for _, podNameOrID := range filterValues {
@@ -246,3 +217,29 @@ func GenerateContainerFilterFuncs(filter string, filterValues []string, r *libpo
}
return nil, errors.Errorf("%s is an invalid filter", filter)
}
+
+// GeneratePruneContainerFilterFuncs return ContainerFilter functions based of filter for prune operation
+func GeneratePruneContainerFilterFuncs(filter string, filterValues []string, r *libpod.Runtime) (func(container *libpod.Container) bool, error) {
+ switch filter {
+ case "label":
+ return func(c *libpod.Container) bool {
+ return util.MatchLabelFilters(filterValues, c.Labels())
+ }, nil
+ case "until":
+ return prepareUntilFilterFunc(filterValues)
+ }
+ return nil, errors.Errorf("%s is an invalid filter", filter)
+}
+
+func prepareUntilFilterFunc(filterValues []string) (func(container *libpod.Container) bool, error) {
+ until, err := util.ComputeUntilTimestamp(filterValues)
+ if err != nil {
+ return nil, err
+ }
+ return func(c *libpod.Container) bool {
+ if !until.IsZero() && c.CreatedTime().After((until)) {
+ return true
+ }
+ return false
+ }, nil
+}
diff --git a/pkg/domain/filters/pods.go b/pkg/domain/filters/pods.go
index 0490a4848..9a1c7d19d 100644
--- a/pkg/domain/filters/pods.go
+++ b/pkg/domain/filters/pods.go
@@ -114,26 +114,7 @@ func GeneratePodFilterFunc(filter string, filterValues []string) (
case "label":
return func(p *libpod.Pod) bool {
labels := p.Labels()
- for _, filterValue := range filterValues {
- matched := false
- filterArray := strings.SplitN(filterValue, "=", 2)
- filterKey := filterArray[0]
- if len(filterArray) > 1 {
- filterValue = filterArray[1]
- } else {
- filterValue = ""
- }
- for labelKey, labelValue := range labels {
- if labelKey == filterKey && (filterValue == "" || labelValue == filterValue) {
- matched = true
- break
- }
- }
- if !matched {
- return false
- }
- }
- return true
+ return util.MatchLabelFilters(filterValues, labels)
}, nil
case "network":
return func(p *libpod.Pod) bool {
diff --git a/pkg/domain/filters/volumes.go b/pkg/domain/filters/volumes.go
index bc1756cf5..9b2fc5280 100644
--- a/pkg/domain/filters/volumes.go
+++ b/pkg/domain/filters/volumes.go
@@ -5,6 +5,7 @@ import (
"strings"
"github.com/containers/podman/v3/libpod"
+ "github.com/containers/podman/v3/pkg/util"
"github.com/pkg/errors"
)
@@ -29,21 +30,9 @@ func GenerateVolumeFilters(filters url.Values) ([]libpod.VolumeFilter, error) {
return v.Scope() == scopeVal
})
case "label":
- filterArray := strings.SplitN(val, "=", 2)
- filterKey := filterArray[0]
- var filterVal string
- if len(filterArray) > 1 {
- filterVal = filterArray[1]
- } else {
- filterVal = ""
- }
+ filter := val
vf = append(vf, func(v *libpod.Volume) bool {
- for labelKey, labelValue := range v.Labels() {
- if labelKey == filterKey && (filterVal == "" || labelValue == filterVal) {
- return true
- }
- }
- return false
+ return util.MatchLabelFilters([]string{filter}, v.Labels())
})
case "opt":
filterArray := strings.SplitN(val, "=", 2)
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go
index 637531ee9..24261e5ed 100644
--- a/pkg/domain/infra/abi/containers.go
+++ b/pkg/domain/infra/abi/containers.go
@@ -194,7 +194,7 @@ func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []strin
func (ic *ContainerEngine) ContainerPrune(ctx context.Context, options entities.ContainerPruneOptions) ([]*reports.PruneReport, error) {
filterFuncs := make([]libpod.ContainerFilter, 0, len(options.Filters))
for k, v := range options.Filters {
- generatedFunc, err := dfilters.GenerateContainerFilterFuncs(k, v, ic.Libpod)
+ generatedFunc, err := dfilters.GeneratePruneContainerFilterFuncs(k, v, ic.Libpod)
if err != nil {
return nil, err
}
diff --git a/pkg/domain/infra/abi/generate.go b/pkg/domain/infra/abi/generate.go
index 161becbfa..94f649e15 100644
--- a/pkg/domain/infra/abi/generate.go
+++ b/pkg/domain/infra/abi/generate.go
@@ -44,11 +44,10 @@ 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
- podYAML *k8sAPI.Pod
- err error
ctrs []*libpod.Container
- servicePorts []k8sAPI.ServicePort
- serviceYAML k8sAPI.Service
+ kubePods []*k8sAPI.Pod
+ kubeServices []k8sAPI.Service
+ content []byte
)
for _, nameOrID := range nameOrIDs {
// Get the container in question
@@ -59,9 +58,6 @@ func (ic *ContainerEngine) GenerateKube(ctx context.Context, nameOrIDs []string,
return nil, err
}
pods = append(pods, pod)
- if len(pods) > 1 {
- return nil, errors.New("can only generate single pod at a time")
- }
} else {
if len(ctr.Dependencies()) > 0 {
return nil, errors.Wrapf(define.ErrNotImplemented, "containers with dependencies")
@@ -79,20 +75,29 @@ func (ic *ContainerEngine) GenerateKube(ctx context.Context, nameOrIDs []string,
return nil, errors.New("cannot generate pods and containers at the same time")
}
- if len(pods) == 1 {
- podYAML, servicePorts, err = pods[0].GenerateForKube()
+ if len(pods) >= 1 {
+ pos, svcs, err := getKubePods(pods, options.Service)
+ if err != nil {
+ return nil, err
+ }
+
+ kubePods = append(kubePods, pos...)
+ if options.Service {
+ kubeServices = append(kubeServices, svcs...)
+ }
} else {
- podYAML, err = libpod.GenerateForKube(ctrs)
- }
- if err != nil {
- return nil, err
- }
+ po, err := libpod.GenerateForKube(ctrs)
+ if err != nil {
+ return nil, err
+ }
- if options.Service {
- serviceYAML = libpod.GenerateKubeServiceFromV1Pod(podYAML, servicePorts)
+ kubePods = append(kubePods, po)
+ if options.Service {
+ kubeServices = append(kubeServices, libpod.GenerateKubeServiceFromV1Pod(po, []k8sAPI.ServicePort{}))
+ }
}
- content, err := generateKubeOutput(podYAML, &serviceYAML, options.Service)
+ content, err := generateKubeOutput(kubePods, kubeServices, options.Service)
if err != nil {
return nil, err
}
@@ -100,24 +105,56 @@ func (ic *ContainerEngine) GenerateKube(ctx context.Context, nameOrIDs []string,
return &entities.GenerateKubeReport{Reader: bytes.NewReader(content)}, nil
}
-func generateKubeOutput(podYAML *k8sAPI.Pod, serviceYAML *k8sAPI.Service, hasService bool) ([]byte, error) {
- var (
- output []byte
- marshalledPod []byte
- marshalledService []byte
- err error
- )
+func getKubePods(pods []*libpod.Pod, getService bool) ([]*k8sAPI.Pod, []k8sAPI.Service, error) {
+ kubePods := make([]*k8sAPI.Pod, 0)
+ kubeServices := make([]k8sAPI.Service, 0)
- marshalledPod, err = yaml.Marshal(podYAML)
- if err != nil {
- return nil, err
+ for _, p := range pods {
+ po, svc, err := p.GenerateForKube()
+ if err != nil {
+ return nil, nil, err
+ }
+
+ kubePods = append(kubePods, po)
+ if getService {
+ kubeServices = append(kubeServices, libpod.GenerateKubeServiceFromV1Pod(po, svc))
+ }
}
- if hasService {
- marshalledService, err = yaml.Marshal(serviceYAML)
+ return kubePods, kubeServices, 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)
+
+ for i, p := range kubePods {
+ if i != 0 {
+ marshalledPods = append(marshalledPods, []byte("---\n")...)
+ }
+
+ b, err := yaml.Marshal(p)
if err != nil {
return nil, err
}
+
+ marshalledPods = append(marshalledPods, 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
+ }
+
+ marshalledServices = append(marshalledServices, b...)
+ }
}
header := `# Generation of Kubernetes YAML is still under development!
@@ -133,11 +170,12 @@ func generateKubeOutput(podYAML *k8sAPI.Pod, serviceYAML *k8sAPI.Service, hasSer
}
output = append(output, []byte(fmt.Sprintf(header, podmanVersion.Version))...)
- output = append(output, marshalledPod...)
+ // kube generate order is based on helm install order (service, pod...)
if hasService {
+ output = append(output, marshalledServices...)
output = append(output, []byte("---\n")...)
- output = append(output, marshalledService...)
}
+ output = append(output, marshalledPods...)
return output, nil
}
diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go
index efc7c86e3..3b5c141d7 100644
--- a/pkg/domain/infra/abi/play.go
+++ b/pkg/domain/infra/abi/play.go
@@ -1,6 +1,7 @@
package abi
import (
+ "bytes"
"context"
"fmt"
"io"
@@ -8,6 +9,7 @@ import (
"os"
"strings"
+ "github.com/containers/common/pkg/secrets"
"github.com/containers/image/v5/types"
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/libpod/define"
@@ -20,46 +22,79 @@ import (
"github.com/ghodss/yaml"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
+ yamlv3 "gopkg.in/yaml.v3"
v1apps "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
)
func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options entities.PlayKubeOptions) (*entities.PlayKubeReport, error) {
- var (
- kubeObject v1.ObjectReference
- )
+ report := &entities.PlayKubeReport{}
+ validKinds := 0
+ // read yaml document
content, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
}
- if err := yaml.Unmarshal(content, &kubeObject); err != nil {
- return nil, errors.Wrapf(err, "unable to read %q as YAML", path)
+ // split yaml document
+ documentList, err := splitMultiDocYAML(content)
+ if err != nil {
+ return nil, err
}
- // NOTE: pkg/bindings/play is also parsing the file.
- // A pkg/kube would be nice to refactor and abstract
- // parts of the K8s-related code.
- switch kubeObject.Kind {
- case "Pod":
- var podYAML v1.Pod
- var podTemplateSpec v1.PodTemplateSpec
- if err := yaml.Unmarshal(content, &podYAML); err != nil {
- return nil, errors.Wrapf(err, "unable to read YAML %q as Kube Pod", path)
+ // create pod on each document if it is a pod or deployment
+ // any other kube kind will be skipped
+ for _, document := range documentList {
+ kind, err := getKubeKind(document)
+ if err != nil {
+ return nil, errors.Wrapf(err, "unable to read %q as kube YAML", path)
}
- podTemplateSpec.ObjectMeta = podYAML.ObjectMeta
- podTemplateSpec.Spec = podYAML.Spec
- return ic.playKubePod(ctx, podTemplateSpec.ObjectMeta.Name, &podTemplateSpec, options)
- case "Deployment":
- var deploymentYAML v1apps.Deployment
- if err := yaml.Unmarshal(content, &deploymentYAML); err != nil {
- return nil, errors.Wrapf(err, "unable to read YAML %q as Kube Deployment", path)
+
+ switch kind {
+ case "Pod":
+ var podYAML v1.Pod
+ var podTemplateSpec v1.PodTemplateSpec
+
+ if err := yaml.Unmarshal(document, &podYAML); err != nil {
+ return nil, errors.Wrapf(err, "unable to read YAML %q as Kube Pod", path)
+ }
+
+ podTemplateSpec.ObjectMeta = podYAML.ObjectMeta
+ podTemplateSpec.Spec = podYAML.Spec
+
+ r, err := ic.playKubePod(ctx, podTemplateSpec.ObjectMeta.Name, &podTemplateSpec, options)
+ if err != nil {
+ return nil, err
+ }
+
+ report.Pods = append(report.Pods, r.Pods...)
+ validKinds++
+ case "Deployment":
+ var deploymentYAML v1apps.Deployment
+
+ if err := yaml.Unmarshal(document, &deploymentYAML); err != nil {
+ return nil, errors.Wrapf(err, "unable to read YAML %q as Kube Deployment", path)
+ }
+
+ r, err := ic.playKubeDeployment(ctx, &deploymentYAML, options)
+ if err != nil {
+ return nil, err
+ }
+
+ report.Pods = append(report.Pods, r.Pods...)
+ validKinds++
+ default:
+ logrus.Infof("kube kind %s not supported", kind)
+ continue
}
- return ic.playKubeDeployment(ctx, &deploymentYAML, options)
- default:
- return nil, errors.Errorf("invalid YAML kind: %q. [Pod|Deployment] are the only supported Kubernetes Kinds", kubeObject.Kind)
}
+
+ if validKinds == 0 {
+ return nil, fmt.Errorf("YAML document does not contain any supported kube kind")
+ }
+
+ return report, nil
}
func (ic *ContainerEngine) playKubeDeployment(ctx context.Context, deploymentYAML *v1apps.Deployment, options entities.PlayKubeOptions) (*entities.PlayKubeReport, error) {
@@ -101,6 +136,12 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
report entities.PlayKubeReport
)
+ // Create the secret manager before hand
+ secretsManager, err := secrets.NewManager(ic.Libpod.GetSecretsStorageDir())
+ if err != nil {
+ return nil, err
+ }
+
// check for name collision between pod and container
if podName == "" {
return nil, errors.Errorf("pod does not have a name")
@@ -227,16 +268,17 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
}
specgenOpts := kube.CtrSpecGenOptions{
- Container: container,
- Image: newImage,
- Volumes: volumes,
- PodID: pod.ID(),
- PodName: podName,
- PodInfraID: podInfraID,
- ConfigMaps: configMaps,
- SeccompPaths: seccompPaths,
- RestartPolicy: ctrRestartPolicy,
- NetNSIsHost: p.NetNS.IsHost(),
+ Container: container,
+ Image: newImage,
+ Volumes: volumes,
+ PodID: pod.ID(),
+ PodName: podName,
+ PodInfraID: podInfraID,
+ ConfigMaps: configMaps,
+ SeccompPaths: seccompPaths,
+ RestartPolicy: ctrRestartPolicy,
+ NetNSIsHost: p.NetNS.IsHost(),
+ SecretsManager: secretsManager,
}
specGen, err := kube.ToSpecGen(ctx, &specgenOpts)
if err != nil {
@@ -290,3 +332,45 @@ func readConfigMapFromFile(r io.Reader) (v1.ConfigMap, error) {
return cm, nil
}
+
+// splitMultiDocYAML reads mutiple documents in a YAML file and
+// returns them as a list.
+func splitMultiDocYAML(yamlContent []byte) ([][]byte, error) {
+ var documentList [][]byte
+
+ d := yamlv3.NewDecoder(bytes.NewReader(yamlContent))
+ for {
+ var o interface{}
+ // read individual document
+ err := d.Decode(&o)
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ return nil, errors.Wrapf(err, "multi doc yaml could not be split")
+ }
+
+ if o != nil {
+ // back to bytes
+ document, err := yamlv3.Marshal(o)
+ if err != nil {
+ return nil, errors.Wrapf(err, "individual doc yaml could not be marshalled")
+ }
+
+ documentList = append(documentList, document)
+ }
+ }
+
+ return documentList, nil
+}
+
+// getKubeKind unmarshals a kube YAML document and returns its kind.
+func getKubeKind(obj []byte) (string, error) {
+ var kubeObject v1.ObjectReference
+
+ if err := yaml.Unmarshal(obj, &kubeObject); err != nil {
+ return "", err
+ }
+
+ return kubeObject.Kind, nil
+}
diff --git a/pkg/domain/infra/abi/play_test.go b/pkg/domain/infra/abi/play_test.go
index 4354a3835..bbc7c3493 100644
--- a/pkg/domain/infra/abi/play_test.go
+++ b/pkg/domain/infra/abi/play_test.go
@@ -89,3 +89,100 @@ data:
})
}
}
+
+func TestGetKubeKind(t *testing.T) {
+ tests := []struct {
+ name string
+ kubeYAML string
+ expectError bool
+ expectedErrorMsg string
+ expected string
+ }{
+ {
+ "ValidKubeYAML",
+ `
+apiVersion: v1
+kind: Pod
+`,
+ false,
+ "",
+ "Pod",
+ },
+ {
+ "InvalidKubeYAML",
+ "InvalidKubeYAML",
+ true,
+ "cannot unmarshal",
+ "",
+ },
+ }
+
+ for _, test := range tests {
+ test := test
+ t.Run(test.name, func(t *testing.T) {
+ kind, err := getKubeKind([]byte(test.kubeYAML))
+ if test.expectError {
+ assert.Error(t, err)
+ assert.Contains(t, err.Error(), test.expectedErrorMsg)
+ } else {
+ assert.NoError(t, err)
+ assert.Equal(t, test.expected, kind)
+ }
+ })
+ }
+}
+
+func TestSplitMultiDocYAML(t *testing.T) {
+ tests := []struct {
+ name string
+ kubeYAML string
+ expectError bool
+ expectedErrorMsg string
+ expected int
+ }{
+ {
+ "ValidNumberOfDocs",
+ `
+apiVersion: v1
+kind: Pod
+---
+apiVersion: v1
+kind: Pod
+---
+apiVersion: v1
+kind: Pod
+`,
+ false,
+ "",
+ 3,
+ },
+ {
+ "InvalidMultiDocYAML",
+ `
+apiVersion: v1
+kind: Pod
+---
+apiVersion: v1
+kind: Pod
+-
+`,
+ true,
+ "multi doc yaml could not be split",
+ 0,
+ },
+ }
+
+ for _, test := range tests {
+ test := test
+ t.Run(test.name, func(t *testing.T) {
+ docs, err := splitMultiDocYAML([]byte(test.kubeYAML))
+ if test.expectError {
+ assert.Error(t, err)
+ assert.Contains(t, err.Error(), test.expectedErrorMsg)
+ } else {
+ assert.NoError(t, err)
+ assert.Equal(t, test.expected, len(docs))
+ }
+ })
+ }
+}
diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go
index 9f7c8919b..a3e753384 100644
--- a/pkg/domain/infra/abi/system.go
+++ b/pkg/domain/infra/abi/system.go
@@ -67,7 +67,7 @@ func (ic *ContainerEngine) SetupRootless(_ context.Context, cmd *cobra.Command)
if os.Geteuid() == 0 {
ownsCgroup, err := cgroups.UserOwnsCurrentSystemdCgroup()
if err != nil {
- logrus.Warnf("Failed to detect the owner for the current cgroup: %v", err)
+ logrus.Infof("Failed to detect the owner for the current cgroup: %v", err)
}
if !ownsCgroup {
conf, err := ic.Config(context.Background())
diff --git a/pkg/domain/infra/runtime_libpod.go b/pkg/domain/infra/runtime_libpod.go
index 8b6581c7b..b0d9dc797 100644
--- a/pkg/domain/infra/runtime_libpod.go
+++ b/pkg/domain/infra/runtime_libpod.go
@@ -15,8 +15,8 @@ import (
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/namespaces"
"github.com/containers/podman/v3/pkg/rootless"
- "github.com/containers/storage"
"github.com/containers/storage/pkg/idtools"
+ "github.com/containers/storage/types"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
flag "github.com/spf13/pflag"
@@ -100,7 +100,7 @@ func GetRuntimeNoStore(ctx context.Context, fs *flag.FlagSet, cfg *entities.Podm
func getRuntime(ctx context.Context, fs *flag.FlagSet, opts *engineOpts) (*libpod.Runtime, error) {
options := []libpod.RuntimeOption{}
- storageOpts := storage.StoreOptions{}
+ storageOpts := types.StoreOptions{}
cfg := opts.config
storageSet := false
@@ -237,8 +237,8 @@ func getRuntime(ctx context.Context, fs *flag.FlagSet, opts *engineOpts) (*libpo
}
// ParseIDMapping takes idmappings and subuid and subgid maps and returns a storage mapping
-func ParseIDMapping(mode namespaces.UsernsMode, uidMapSlice, gidMapSlice []string, subUIDMap, subGIDMap string) (*storage.IDMappingOptions, error) {
- options := storage.IDMappingOptions{
+func ParseIDMapping(mode namespaces.UsernsMode, uidMapSlice, gidMapSlice []string, subUIDMap, subGIDMap string) (*types.IDMappingOptions, error) {
+ options := types.IDMappingOptions{
HostUIDMapping: true,
HostGIDMapping: true,
}