diff options
Diffstat (limited to 'pkg/domain')
-rw-r--r-- | pkg/domain/entities/containers.go | 1 | ||||
-rw-r--r-- | pkg/domain/filters/containers.go | 27 | ||||
-rw-r--r-- | pkg/domain/infra/abi/containers.go | 28 | ||||
-rw-r--r-- | pkg/domain/infra/abi/containers_runlabel.go | 19 | ||||
-rw-r--r-- | pkg/domain/infra/abi/containers_runlabel_test.go | 40 | ||||
-rw-r--r-- | pkg/domain/infra/abi/play.go | 27 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/containers.go | 25 |
7 files changed, 160 insertions, 7 deletions
diff --git a/pkg/domain/entities/containers.go b/pkg/domain/entities/containers.go index 4707ced85..eacc14d50 100644 --- a/pkg/domain/entities/containers.go +++ b/pkg/domain/entities/containers.go @@ -265,6 +265,7 @@ type ContainerExistsOptions struct { // ContainerStartOptions describes the val from the // CLI needed to start a container type ContainerStartOptions struct { + Filters map[string][]string All bool Attach bool DetachKeys string diff --git a/pkg/domain/filters/containers.go b/pkg/domain/filters/containers.go index 9ac72e415..965a12468 100644 --- a/pkg/domain/filters/containers.go +++ b/pkg/domain/filters/containers.go @@ -1,6 +1,7 @@ package filters import ( + "fmt" "strconv" "strings" "time" @@ -226,6 +227,32 @@ func GenerateContainerFilterFuncs(filter string, filterValues []string, r *libpo } return false }, nil + case "restart-policy": + invalidPolicyNames := []string{} + for _, policy := range filterValues { + if _, ok := define.RestartPolicyMap[policy]; !ok { + invalidPolicyNames = append(invalidPolicyNames, policy) + } + } + var filterValueError error = nil + if len(invalidPolicyNames) > 0 { + errPrefix := "invalid restart policy" + if len(invalidPolicyNames) > 1 { + errPrefix = "invalid restart policies" + } + filterValueError = fmt.Errorf("%s %s", strings.Join(invalidPolicyNames, ", "), errPrefix) + } + return func(c *libpod.Container) bool { + for _, policy := range filterValues { + if policy == "none" && c.RestartPolicy() == define.RestartPolicyNone { + return true + } + if c.RestartPolicy() == policy { + return true + } + } + return false + }, filterValueError } return nil, errors.Errorf("%s is an invalid filter", filter) } diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go index ef3ccab0c..d0a2b1bae 100644 --- a/pkg/domain/infra/abi/containers.go +++ b/pkg/domain/infra/abi/containers.go @@ -694,7 +694,33 @@ func (ic *ContainerEngine) ContainerExecDetached(ctx context.Context, nameOrID s func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []string, options entities.ContainerStartOptions) ([]*entities.ContainerStartReport, error) { reports := []*entities.ContainerStartReport{} var exitCode = define.ExecErrorCodeGeneric - ctrs, rawInputs, err := getContainersAndInputByContext(options.All, options.Latest, namesOrIds, ic.Libpod) + containersNamesOrIds := namesOrIds + if len(options.Filters) > 0 { + filterFuncs := make([]libpod.ContainerFilter, 0, len(options.Filters)) + if len(options.Filters) > 0 { + for k, v := range options.Filters { + generatedFunc, err := dfilters.GenerateContainerFilterFuncs(k, v, ic.Libpod) + if err != nil { + return nil, err + } + filterFuncs = append(filterFuncs, generatedFunc) + } + } + candidates, err := ic.Libpod.GetContainers(filterFuncs...) + if err != nil { + return nil, err + } + containersNamesOrIds = []string{} + for _, candidate := range candidates { + for _, nameOrID := range namesOrIds { + if nameOrID == candidate.ID() || nameOrID == candidate.Name() { + containersNamesOrIds = append(containersNamesOrIds, nameOrID) + } + } + } + } + + ctrs, rawInputs, err := getContainersAndInputByContext(options.All, options.Latest, containersNamesOrIds, ic.Libpod) if err != nil { return nil, err } diff --git a/pkg/domain/infra/abi/containers_runlabel.go b/pkg/domain/infra/abi/containers_runlabel.go index 199ae43ad..d448627dc 100644 --- a/pkg/domain/infra/abi/containers_runlabel.go +++ b/pkg/domain/infra/abi/containers_runlabel.go @@ -180,13 +180,28 @@ func generateRunlabelCommand(runlabel string, img *libimage.Image, inputName str } func replaceName(arg, name string) string { + if arg == "NAME" { + return name + } + newarg := strings.ReplaceAll(arg, "$NAME", name) - return strings.ReplaceAll(newarg, "${NAME}", name) + newarg = strings.ReplaceAll(newarg, "${NAME}", name) + if strings.HasSuffix(newarg, "=NAME") { + newarg = strings.ReplaceAll(newarg, "=NAME", fmt.Sprintf("=%s", name)) + } + return newarg } func replaceImage(arg, image string) string { + if arg == "IMAGE" { + return image + } newarg := strings.ReplaceAll(arg, "$IMAGE", image) - return strings.ReplaceAll(newarg, "${IMAGE}", image) + newarg = strings.ReplaceAll(newarg, "${IMAGE}", image) + if strings.HasSuffix(newarg, "=IMAGE") { + newarg = strings.ReplaceAll(newarg, "=IMAGE", fmt.Sprintf("=%s", image)) + } + return newarg } // generateCommand takes a label (string) and converts it to an executable command diff --git a/pkg/domain/infra/abi/containers_runlabel_test.go b/pkg/domain/infra/abi/containers_runlabel_test.go new file mode 100644 index 000000000..10f9ae004 --- /dev/null +++ b/pkg/domain/infra/abi/containers_runlabel_test.go @@ -0,0 +1,40 @@ +package abi + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestReplaceName(t *testing.T) { + tests := [][]string{ + {"NAME=$NAME", "test1", "NAME=test1"}, + {"NAME=${NAME}", "test2", "NAME=test2"}, + {"NAME=NAME", "test3", "NAME=test3"}, + {"NAME=NAMEFOO", "test3", "NAME=NAMEFOO"}, + {"NAME", "test4", "test4"}, + {"FNAME", "test5", "FNAME"}, + {"NAME=foo", "test6", "NAME=foo"}, + {"This is my NAME", "test7", "This is my NAME"}, + } + for _, args := range tests { + val := replaceName(args[0], args[1]) + assert.Equal(t, val, args[2]) + } +} + +func TestReplaceImage(t *testing.T) { + tests := [][]string{ + {"IMAGE=$IMAGE", "test1", "IMAGE=test1"}, + {"IMAGE=${IMAGE}", "test2", "IMAGE=test2"}, + {"IMAGE=IMAGE", "test3", "IMAGE=test3"}, + {"IMAGE=IMAGEFOO", "test3", "IMAGE=IMAGEFOO"}, + {"IMAGE", "test4", "test4"}, + {"FIMAGE", "test5", "FIMAGE"}, + {"IMAGE=foo", "test6", "IMAGE=foo"}, + } + for _, args := range tests { + val := replaceImage(args[0], args[1]) + assert.Equal(t, val, args[2]) + } +} diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go index 64e7f208c..a94c5f5c5 100644 --- a/pkg/domain/infra/abi/play.go +++ b/pkg/domain/infra/abi/play.go @@ -16,6 +16,7 @@ import ( "github.com/containers/image/v5/types" "github.com/containers/podman/v3/libpod" "github.com/containers/podman/v3/libpod/define" + "github.com/containers/podman/v3/pkg/autoupdate" "github.com/containers/podman/v3/pkg/domain/entities" "github.com/containers/podman/v3/pkg/specgen" "github.com/containers/podman/v3/pkg/specgen/generate" @@ -73,7 +74,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, &ipIndex) + r, err := ic.playKubePod(ctx, podTemplateSpec.ObjectMeta.Name, &podTemplateSpec, options, &ipIndex, podYAML.Annotations) if err != nil { return nil, err } @@ -143,7 +144,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, ipIndex) + podReport, err := ic.playKubePod(ctx, podName, &podSpec, options, ipIndex, deploymentYAML.Annotations) if err != nil { return nil, errors.Wrapf(err, "error encountered while bringing up pod %s", podName) } @@ -152,7 +153,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, ipIndex *int) (*entities.PlayKubeReport, error) { +func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podYAML *v1.PodTemplateSpec, options entities.PlayKubeOptions, ipIndex *int, annotations map[string]string) (*entities.PlayKubeReport, error) { var ( writer io.Writer playKubePod entities.PlayKubePod @@ -265,6 +266,9 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY containers := make([]*libpod.Container, 0, len(podYAML.Spec.Containers)) for _, container := range podYAML.Spec.Containers { + // Contains all labels obtained from kube + labels := make(map[string]string) + // 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* @@ -292,6 +296,22 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY return nil, err } + // 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, Image: pulledImages[0], @@ -305,6 +325,7 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY NetNSIsHost: p.NetNS.IsHost(), SecretsManager: secretsManager, LogDriver: options.LogDriver, + Labels: labels, } specGen, err := kube.ToSpecGen(ctx, &specgenOpts) if err != nil { diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go index aa26825e0..3830835cc 100644 --- a/pkg/domain/infra/tunnel/containers.go +++ b/pkg/domain/infra/tunnel/containers.go @@ -506,7 +506,30 @@ func startAndAttach(ic *ContainerEngine, name string, detachKeys *string, input, func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []string, options entities.ContainerStartOptions) ([]*entities.ContainerStartReport, error) { reports := []*entities.ContainerStartReport{} var exitCode = define.ExecErrorCodeGeneric - ctrs, err := getContainersByContext(ic.ClientCtx, options.All, false, namesOrIds) + containersNamesOrIds := namesOrIds + if len(options.Filters) > 0 { + containersNamesOrIds = []string{} + opts := new(containers.ListOptions).WithFilters(options.Filters).WithAll(true) + candidates, listErr := containers.List(ic.ClientCtx, opts) + if listErr != nil { + return nil, listErr + } + for _, candidate := range candidates { + for _, nameOrID := range namesOrIds { + if nameOrID == candidate.ID { + containersNamesOrIds = append(containersNamesOrIds, nameOrID) + continue + } + for _, containerName := range candidate.Names { + if containerName == nameOrID { + containersNamesOrIds = append(containersNamesOrIds, nameOrID) + continue + } + } + } + } + } + ctrs, err := getContainersByContext(ic.ClientCtx, options.All, false, containersNamesOrIds) if err != nil { return nil, err } |