diff options
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/api/handlers/compat/containers_stats.go | 2 | ||||
-rw-r--r-- | pkg/api/handlers/swagger/swagger.go | 9 | ||||
-rw-r--r-- | pkg/api/server/register_containers.go | 4 | ||||
-rw-r--r-- | pkg/domain/entities/play.go | 2 | ||||
-rw-r--r-- | pkg/domain/infra/abi/play.go | 190 | ||||
-rw-r--r-- | pkg/machine/ignition.go | 46 | ||||
-rw-r--r-- | pkg/specgen/generate/kube/kube.go | 5 |
7 files changed, 187 insertions, 71 deletions
diff --git a/pkg/api/handlers/compat/containers_stats.go b/pkg/api/handlers/compat/containers_stats.go index 851955207..b95fbfdd8 100644 --- a/pkg/api/handlers/compat/containers_stats.go +++ b/pkg/api/handlers/compat/containers_stats.go @@ -97,7 +97,7 @@ streamLabel: // A label to flatten the scope default: // Container stats - stats, err := ctnr.GetContainerStats(stats) + stats, err = ctnr.GetContainerStats(stats) if err != nil { logrus.Errorf("Unable to get container stats: %v", err) return diff --git a/pkg/api/handlers/swagger/swagger.go b/pkg/api/handlers/swagger/swagger.go index 2296eea3a..9844839b7 100644 --- a/pkg/api/handlers/swagger/swagger.go +++ b/pkg/api/handlers/swagger/swagger.go @@ -176,3 +176,12 @@ type swagInspectPodResponse struct { define.InspectPodData } } + +// Get stats for one or more containers +// swagger:response ContainerStats +type swagContainerStatsResponse struct { + // in:body + Body struct { + define.ContainerStats + } +} diff --git a/pkg/api/server/register_containers.go b/pkg/api/server/register_containers.go index 2a32966cc..8dcea1301 100644 --- a/pkg/api/server/register_containers.go +++ b/pkg/api/server/register_containers.go @@ -1124,11 +1124,9 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error { // - application/json // responses: // 200: - // description: no error + // $ref: "#/responses/ContainerStats" // 404: // $ref: "#/responses/NoSuchContainer" - // 409: - // $ref: "#/responses/ConflictError" // 500: // $ref: "#/responses/InternalError" r.HandleFunc(VersionedPath("/libpod/containers/stats"), s.APIHandler(libpod.StatsContainer)).Methods(http.MethodGet) diff --git a/pkg/domain/entities/play.go b/pkg/domain/entities/play.go index 77329e328..f630b3f24 100644 --- a/pkg/domain/entities/play.go +++ b/pkg/domain/entities/play.go @@ -51,6 +51,8 @@ type PlayKubePod struct { ID string // Containers - the IDs of the containers running in the created pod. Containers []string + // InitContainers - the IDs of the init containers to be run in the created pod. + InitContainers []string // Logs - non-fatal errors and log messages while processing. Logs []string // ContainerErrors - any errors that occurred while starting containers diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go index c6d5dcc3d..87506f70c 100644 --- a/pkg/domain/infra/abi/play.go +++ b/pkg/domain/infra/abi/play.go @@ -304,76 +304,59 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY } containers := make([]*libpod.Container, 0, len(podYAML.Spec.Containers)) + initContainers := make([]*libpod.Container, 0, len(podYAML.Spec.InitContainers)) cwd, err := os.Getwd() if err != nil { return nil, err } + + for _, initCtr := range podYAML.Spec.InitContainers { + // Init containers cannot have either of lifecycle, livenessProbe, readinessProbe, or startupProbe set + if initCtr.Lifecycle != nil || initCtr.LivenessProbe != nil || initCtr.ReadinessProbe != nil || initCtr.StartupProbe != nil { + return nil, errors.Errorf("cannot create an init container that has either of lifecycle, livenessProbe, readinessProbe, or startupProbe set") + } + pulledImage, labels, err := ic.getImageAndLabelInfo(ctx, cwd, annotations, writer, initCtr, options) + if err != nil { + return nil, err + } + + specgenOpts := kube.CtrSpecGenOptions{ + Container: initCtr, + Image: pulledImage, + Volumes: volumes, + PodID: pod.ID(), + PodName: podName, + PodInfraID: podInfraID, + ConfigMaps: configMaps, + SeccompPaths: seccompPaths, + RestartPolicy: ctrRestartPolicy, + NetNSIsHost: p.NetNS.IsHost(), + SecretsManager: secretsManager, + LogDriver: options.LogDriver, + Labels: labels, + InitContainerType: define.AlwaysInitContainer, + } + specGen, err := kube.ToSpecGen(ctx, &specgenOpts) + if err != nil { + return nil, err + } + rtSpec, spec, opts, err := generate.MakeContainer(ctx, ic.Libpod, specGen) + if err != nil { + return nil, err + } + ctr, err := generate.ExecuteCreate(ctx, ic.Libpod, rtSpec, spec, false, opts...) + if err != nil { + return nil, err + } + + initContainers = append(initContainers, ctr) + } for _, container := range podYAML.Spec.Containers { if !strings.Contains("infra", container.Name) { - // Contains all labels obtained from kube - labels := make(map[string]string) - var pulledImage *libimage.Image - buildFile, err := getBuildFile(container.Image, cwd) + pulledImage, labels, err := ic.getImageAndLabelInfo(ctx, cwd, annotations, writer, container, options) if err != nil { return nil, err } - existsLocally, err := ic.Libpod.LibimageRuntime().Exists(container.Image) - if err != nil { - return nil, err - } - if (len(buildFile) > 0 && !existsLocally) || (len(buildFile) > 0 && options.Build) { - buildOpts := new(buildahDefine.BuildOptions) - commonOpts := new(buildahDefine.CommonBuildOptions) - buildOpts.ConfigureNetwork = buildahDefine.NetworkDefault - buildOpts.Isolation = buildahDefine.IsolationChroot - buildOpts.CommonBuildOpts = commonOpts - buildOpts.Output = container.Image - if _, _, err := ic.Libpod.Build(ctx, *buildOpts, []string{buildFile}...); err != nil { - return nil, err - } - i, _, err := ic.Libpod.LibimageRuntime().LookupImage(container.Image, new(libimage.LookupImageOptions)) - if err != nil { - return nil, err - } - pulledImage = i - } else { - // NOTE: set the pull policy to "newer". This will cover cases - // where the "latest" tag requires a pull and will also - // transparently handle "localhost/" prefixed files which *may* - // refer to a locally built image OR an image running a - // registry on localhost. - pullPolicy := config.PullPolicyNewer - if len(container.ImagePullPolicy) > 0 { - // Make sure to lower the strings since K8s pull policy - // may be capitalized (see bugzilla.redhat.com/show_bug.cgi?id=1985905). - rawPolicy := string(container.ImagePullPolicy) - pullPolicy, err = config.ParsePullPolicy(strings.ToLower(rawPolicy)) - if err != nil { - return nil, err - } - } - pulledImages, err := pullImage(ic, writer, container.Image, options, pullPolicy) - if err != nil { - return nil, err - } - pulledImage = pulledImages[0] - } - - // Handle kube annotations - for k, v := range annotations { - switch k { - // Auto update annotation without container name will apply to - // all containers within the pod - case autoupdate.Label, autoupdate.AuthfileLabel: - labels[k] = v - // Auto update annotation with container name will apply only - // to the specified container - case fmt.Sprintf("%s/%s", autoupdate.Label, container.Name), - fmt.Sprintf("%s/%s", autoupdate.AuthfileLabel, container.Name): - prefixAndCtr := strings.Split(k, "/") - labels[prefixAndCtr[0]] = v - } - } specgenOpts := kube.CtrSpecGenOptions{ Container: container, @@ -394,7 +377,6 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY if err != nil { return nil, err } - rtSpec, spec, opts, err := generate.MakeContainer(ctx, ic.Libpod, specGen) if err != nil { return nil, err @@ -423,12 +405,96 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY for _, ctr := range containers { playKubePod.Containers = append(playKubePod.Containers, ctr.ID()) } + for _, initCtr := range initContainers { + playKubePod.InitContainers = append(playKubePod.InitContainers, initCtr.ID()) + } report.Pods = append(report.Pods, playKubePod) return &report, nil } +// getImageAndLabelInfo returns the image information and how the image should be pulled plus as well as labels to be used for the container in the pod. +// Moved this to a separate function so that it can be used for both init and regular containers when playing a kube yaml. +func (ic *ContainerEngine) getImageAndLabelInfo(ctx context.Context, cwd string, annotations map[string]string, writer io.Writer, container v1.Container, options entities.PlayKubeOptions) (*libimage.Image, map[string]string, error) { + // Contains all labels obtained from kube + labels := make(map[string]string) + var pulledImage *libimage.Image + buildFile, err := getBuildFile(container.Image, cwd) + if err != nil { + return nil, nil, err + } + existsLocally, err := ic.Libpod.LibimageRuntime().Exists(container.Image) + if err != nil { + return nil, nil, err + } + if (len(buildFile) > 0 && !existsLocally) || (len(buildFile) > 0 && options.Build) { + buildOpts := new(buildahDefine.BuildOptions) + commonOpts := new(buildahDefine.CommonBuildOptions) + buildOpts.ConfigureNetwork = buildahDefine.NetworkDefault + buildOpts.Isolation = buildahDefine.IsolationChroot + buildOpts.CommonBuildOpts = commonOpts + buildOpts.Output = container.Image + if _, _, err := ic.Libpod.Build(ctx, *buildOpts, []string{buildFile}...); err != nil { + return nil, nil, err + } + i, _, err := ic.Libpod.LibimageRuntime().LookupImage(container.Image, new(libimage.LookupImageOptions)) + if err != nil { + return nil, nil, err + } + pulledImage = i + } else { + // NOTE: set the pull policy to "newer". This will cover cases + // where the "latest" tag requires a pull and will also + // transparently handle "localhost/" prefixed files which *may* + // refer to a locally built image OR an image running a + // registry on localhost. + pullPolicy := config.PullPolicyNewer + if len(container.ImagePullPolicy) > 0 { + // Make sure to lower the strings since K8s pull policy + // may be capitalized (see bugzilla.redhat.com/show_bug.cgi?id=1985905). + rawPolicy := string(container.ImagePullPolicy) + pullPolicy, err = config.ParsePullPolicy(strings.ToLower(rawPolicy)) + if err != nil { + return nil, nil, err + } + } + // This ensures the image is the image store + pullOptions := &libimage.PullOptions{} + pullOptions.AuthFilePath = options.Authfile + pullOptions.CertDirPath = options.CertDir + pullOptions.SignaturePolicyPath = options.SignaturePolicy + pullOptions.Writer = writer + pullOptions.Username = options.Username + pullOptions.Password = options.Password + pullOptions.InsecureSkipTLSVerify = options.SkipTLSVerify + + pulledImages, err := ic.Libpod.LibimageRuntime().Pull(ctx, container.Image, pullPolicy, pullOptions) + if err != nil { + return nil, nil, err + } + pulledImage = pulledImages[0] + } + + // Handle kube annotations + for k, v := range annotations { + switch k { + // Auto update annotation without container name will apply to + // all containers within the pod + case autoupdate.Label, autoupdate.AuthfileLabel: + labels[k] = v + // Auto update annotation with container name will apply only + // to the specified container + case fmt.Sprintf("%s/%s", autoupdate.Label, container.Name), + fmt.Sprintf("%s/%s", autoupdate.AuthfileLabel, container.Name): + prefixAndCtr := strings.Split(k, "/") + labels[prefixAndCtr[0]] = v + } + } + + return pulledImage, labels, 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 diff --git a/pkg/machine/ignition.go b/pkg/machine/ignition.go index a9289d6b3..89b556b14 100644 --- a/pkg/machine/ignition.go +++ b/pkg/machine/ignition.go @@ -135,10 +135,25 @@ func getDirs(usrName string) []Directory { Path: d, User: getNodeUsr(usrName), }, - DirectoryEmbedded1: DirectoryEmbedded1{Mode: intToPtr(493)}, + DirectoryEmbedded1: DirectoryEmbedded1{Mode: intToPtr(0755)}, } dirs[i] = newDir } + + // Issue #11489: make sure that we can inject a custom registries.conf + // file on the system level to force a single search registry. + // The remote client does not yet support prompting for short-name + // resolution, so we enforce a single search registry (i.e., docker.io) + // as a workaround. + dirs = append(dirs, Directory{ + Node: Node{ + Group: getNodeGrp("root"), + Path: "/etc/containers/registries.conf.d", + User: getNodeUsr("root"), + }, + DirectoryEmbedded1: DirectoryEmbedded1{Mode: intToPtr(0755)}, + }) + return dirs } @@ -158,7 +173,7 @@ func getFiles(usrName string) []File { Contents: Resource{ Source: strToPtr("data:,%5BUnit%5D%0ADescription%3DA%20systemd%20user%20unit%20demo%0AAfter%3Dnetwork-online.target%0AWants%3Dnetwork-online.target%20podman.socket%0A%5BService%5D%0AExecStart%3D%2Fusr%2Fbin%2Fsleep%20infinity%0A"), }, - Mode: intToPtr(484), + Mode: intToPtr(0744), }, }) @@ -175,7 +190,7 @@ func getFiles(usrName string) []File { Contents: Resource{ Source: strToPtr("data:,%5Bcontainers%5D%0D%0Anetns%3D%22bridge%22%0D%0Arootless_networking%3D%22cni%22"), }, - Mode: intToPtr(484), + Mode: intToPtr(0744), }, }) // Add a file into linger @@ -185,7 +200,7 @@ func getFiles(usrName string) []File { Path: "/var/lib/systemd/linger/core", User: getNodeUsr(usrName), }, - FileEmbedded1: FileEmbedded1{Mode: intToPtr(420)}, + FileEmbedded1: FileEmbedded1{Mode: intToPtr(0644)}, }) // Set machine_enabled to true to indicate we're in a VM @@ -200,9 +215,30 @@ func getFiles(usrName string) []File { Contents: Resource{ Source: strToPtr("data:,%5Bengine%5D%0Amachine_enabled%3Dtrue%0A"), }, - Mode: intToPtr(420), + Mode: intToPtr(0644), + }, + }) + + // Issue #11489: make sure that we can inject a custom registries.conf + // file on the system level to force a single search registry. + // The remote client does not yet support prompting for short-name + // resolution, so we enforce a single search registry (i.e., docker.io) + // as a workaround. + files = append(files, File{ + Node: Node{ + Group: getNodeGrp("root"), + Path: "/etc/containers/registries.conf.d/999-podman-machine.conf", + User: getNodeUsr("root"), + }, + FileEmbedded1: FileEmbedded1{ + Append: nil, + Contents: Resource{ + Source: strToPtr("data:,unqualified-search-registries%3D%5B%22docker.io%22%5D"), + }, + Mode: intToPtr(0644), }, }) + return files } diff --git a/pkg/specgen/generate/kube/kube.go b/pkg/specgen/generate/kube/kube.go index 5188abc3a..c01d7a1f0 100644 --- a/pkg/specgen/generate/kube/kube.go +++ b/pkg/specgen/generate/kube/kube.go @@ -114,6 +114,9 @@ type CtrSpecGenOptions struct { Labels map[string]string // IsInfra bool + // InitContainerType sets what type the init container is + // Note: When playing a kube yaml, the inti container type will be set to "always" only + InitContainerType string } func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGenerator, error) { @@ -135,6 +138,8 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener Driver: opts.LogDriver, } + s.InitContainerType = opts.InitContainerType + setupSecurityContext(s, opts.Container) err := setupLivenessProbe(s, opts.Container, opts.RestartPolicy) if err != nil { |