diff options
Diffstat (limited to 'pkg/domain')
-rw-r--r-- | pkg/domain/entities/images.go | 41 | ||||
-rw-r--r-- | pkg/domain/entities/system.go | 2 | ||||
-rw-r--r-- | pkg/domain/entities/types.go | 4 | ||||
-rw-r--r-- | pkg/domain/entities/types/auth.go | 22 | ||||
-rw-r--r-- | pkg/domain/entities/types/types.go | 28 | ||||
-rw-r--r-- | pkg/domain/entities/volumes.go | 96 | ||||
-rw-r--r-- | pkg/domain/filters/containers.go | 59 | ||||
-rw-r--r-- | pkg/domain/filters/pods.go | 21 | ||||
-rw-r--r-- | pkg/domain/filters/volumes.go | 17 | ||||
-rw-r--r-- | pkg/domain/infra/abi/containers.go | 2 | ||||
-rw-r--r-- | pkg/domain/infra/abi/generate.go | 100 | ||||
-rw-r--r-- | pkg/domain/infra/abi/play.go | 152 | ||||
-rw-r--r-- | pkg/domain/infra/abi/play_test.go | 97 | ||||
-rw-r--r-- | pkg/domain/infra/abi/system.go | 2 | ||||
-rw-r--r-- | pkg/domain/infra/runtime_libpod.go | 8 |
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, } |