forked from LaconicNetwork/kompose
adds a label for initContainers, test and user-guide (#1840)
* adds a label for initContainers, test and user-guide Signed-off-by: jose luis <2064537+sosan@users.noreply.github.com> * solved suggestion version from 2 to 3, coments Signed-off-by: jose luis <2064537+sosan@users.noreply.github.com> * test e2e Signed-off-by: jose luis <2064537+sosan@users.noreply.github.com> * add target to kompose build Signed-off-by: jose luis <2064537+sosan@users.noreply.github.com> * chore(deps)(deps): bump golang.org/x/tools from 0.16.1 to 0.19.0 (#1836) Bumps [golang.org/x/tools](https://github.com/golang/tools) from 0.16.1 to 0.19.0. - [Release notes](https://github.com/golang/tools/releases) - [Commits](https://github.com/golang/tools/compare/v0.16.1...v0.19.0) --- updated-dependencies: - dependency-name: golang.org/x/tools dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * changed var names contaers to containers changed labels to kompose.init.container.name, kompose.init.container.image, kompose.init.container.command fixed documentation, tests and e2e also merged main with new commits to this branch Signed-off-by: jose luis <2064537+sosan@users.noreply.github.com> --------- Signed-off-by: jose luis <2064537+sosan@users.noreply.github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Kubernetes Prow Robot <20407524+k8s-ci-robot@users.noreply.github.com>
This commit is contained in:
co-authored by
dependabot[bot]
Kubernetes Prow Robot
parent
14152d4a81
commit
c9c1080306
@@ -87,6 +87,12 @@ const (
|
||||
LabelCronJobConcurrencyPolicy = "kompose.cronjob.concurrency_policy"
|
||||
// LabelCronJobBackoffLimit defines the job backoff limit
|
||||
LabelCronJobBackoffLimit = "kompose.cronjob.backoff_limit"
|
||||
// LabelInitContainerName defines name resource
|
||||
LabelInitContainerName = "kompose.init.containers.name"
|
||||
// LabelInitContainerImage defines image to pull
|
||||
LabelInitContainerImage = "kompose.init.containers.image"
|
||||
// LabelInitContainerCommand defines commands
|
||||
LabelInitContainerCommand = "kompose.init.containers.command"
|
||||
)
|
||||
|
||||
// load environment variables from compose file
|
||||
|
||||
@@ -654,7 +654,7 @@ func (k *Kubernetes) UpdateKubernetesObjects(name string, service kobject.Servic
|
||||
if serviceAccountName, ok := service.Labels[compose.LabelServiceAccountName]; ok {
|
||||
template.Spec.ServiceAccountName = serviceAccountName
|
||||
}
|
||||
|
||||
fillInitContainers(template, service)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -985,3 +985,48 @@ func reformatSecretConfigUnderscoreWithDash(secretConfig types.ServiceSecretConf
|
||||
|
||||
return newSecretConfig
|
||||
}
|
||||
|
||||
// fillInitContainers looks for an initContainer resources and its passed as labels
|
||||
// if there is no image, it does not fill the initContainer
|
||||
// https://kubernetes.io/docs/concepts/workloads/pods/init-containers/
|
||||
func fillInitContainers(template *api.PodTemplateSpec, service kobject.ServiceConfig) {
|
||||
resourceImage, exist := service.Labels[compose.LabelInitContainerImage]
|
||||
if !exist || resourceImage == "" {
|
||||
return
|
||||
}
|
||||
resourceName, exist := service.Labels[compose.LabelInitContainerName]
|
||||
if !exist || resourceName == "" {
|
||||
resourceName = "init-service"
|
||||
}
|
||||
|
||||
template.Spec.InitContainers = append(template.Spec.InitContainers, api.Container{
|
||||
Name: resourceName,
|
||||
Command: parseContainerCommandsFromStr(service.Labels[compose.LabelInitContainerCommand]),
|
||||
Image: resourceImage,
|
||||
})
|
||||
}
|
||||
|
||||
// parseContainerCommandsFromStr parses a string containing comma-separated commands
|
||||
// returns a slice of strings or a single command
|
||||
// example:
|
||||
// [ "bundle", "exec", "thin", "-p", "3000" ]
|
||||
//
|
||||
// example:
|
||||
// [ "bundle exec thin -p 3000" ]
|
||||
func parseContainerCommandsFromStr(line string) []string {
|
||||
if line == "" {
|
||||
return []string{}
|
||||
}
|
||||
var commands []string
|
||||
if strings.Contains(line, ",") {
|
||||
line = strings.TrimSpace(strings.Trim(line, "[]"))
|
||||
commands = strings.Split(line, ",")
|
||||
// remove space "'
|
||||
for i := range commands {
|
||||
commands[i] = strings.TrimSpace(strings.Trim(commands[i], `"' `))
|
||||
}
|
||||
} else {
|
||||
commands = append(commands, line)
|
||||
}
|
||||
return commands
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import (
|
||||
"github.com/kubernetes/kompose/pkg/testutils"
|
||||
"github.com/pkg/errors"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
api "k8s.io/api/core/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
@@ -738,3 +739,209 @@ func TestRemoveEmptyInterfaces(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_parseContainerCommandsFromStr(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
line string
|
||||
want []string
|
||||
}{
|
||||
{
|
||||
name: "line command without spaces in between",
|
||||
line: `[ "bundle", "exec", "thin", "-p", "3000" ]`,
|
||||
want: []string{
|
||||
"bundle", "exec", "thin", "-p", "3000",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: `line command spaces inside ""`,
|
||||
line: `[ " bundle ", " exec ", " thin ", " -p ", "3000" ]`,
|
||||
want: []string{
|
||||
"bundle", "exec", "thin", "-p", "3000",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: `more use cases for line command spaces inside ""`,
|
||||
line: `[ " bundle ", "exec ", " thin ", " -p ", "3000 " ]`,
|
||||
want: []string{
|
||||
"bundle", "exec", "thin", "-p", "3000",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: `line command without [] and ""`,
|
||||
line: `bundle exec thin -p 3000`,
|
||||
want: []string{
|
||||
"bundle exec thin -p 3000",
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := parseContainerCommandsFromStr(tt.line); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("parseContainerCommandsFromStr() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_fillInitContainers(t *testing.T) {
|
||||
type args struct {
|
||||
template *api.PodTemplateSpec
|
||||
service kobject.ServiceConfig
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []corev1.Container
|
||||
}{
|
||||
{
|
||||
name: "Testing init container are generated from labels with ,",
|
||||
args: args{
|
||||
template: &api.PodTemplateSpec{},
|
||||
service: kobject.ServiceConfig{
|
||||
Labels: map[string]string{
|
||||
compose.LabelInitContainerName: "name",
|
||||
compose.LabelInitContainerImage: "image",
|
||||
compose.LabelInitContainerCommand: `[ "bundle", "exec", "thin", "-p", "3000" ]`,
|
||||
},
|
||||
},
|
||||
},
|
||||
want: []corev1.Container{
|
||||
{
|
||||
Name: "name",
|
||||
Image: "image",
|
||||
Command: []string{
|
||||
"bundle", "exec", "thin", "-p", "3000",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Testing init container are generated from labels without ,",
|
||||
args: args{
|
||||
template: &api.PodTemplateSpec{},
|
||||
service: kobject.ServiceConfig{
|
||||
Labels: map[string]string{
|
||||
compose.LabelInitContainerName: "name",
|
||||
compose.LabelInitContainerImage: "image",
|
||||
compose.LabelInitContainerCommand: `bundle exec thin -p 3000`,
|
||||
},
|
||||
},
|
||||
},
|
||||
want: []corev1.Container{
|
||||
{
|
||||
Name: "name",
|
||||
Image: "image",
|
||||
Command: []string{
|
||||
`bundle exec thin -p 3000`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: `Testing init container with long command with vars inside and ''`,
|
||||
args: args{
|
||||
template: &api.PodTemplateSpec{},
|
||||
service: kobject.ServiceConfig{
|
||||
Labels: map[string]string{
|
||||
compose.LabelInitContainerName: "init-myservice",
|
||||
compose.LabelInitContainerImage: "busybox:1.28",
|
||||
compose.LabelInitContainerCommand: `['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]`,
|
||||
},
|
||||
},
|
||||
},
|
||||
want: []corev1.Container{
|
||||
{
|
||||
Name: "init-myservice",
|
||||
Image: "busybox:1.28",
|
||||
Command: []string{
|
||||
"sh", "-c", `until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: `without image`,
|
||||
args: args{
|
||||
template: &api.PodTemplateSpec{},
|
||||
service: kobject.ServiceConfig{
|
||||
Labels: map[string]string{
|
||||
compose.LabelInitContainerName: "init-myservice",
|
||||
compose.LabelInitContainerImage: "",
|
||||
compose.LabelInitContainerCommand: `['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]`,
|
||||
},
|
||||
},
|
||||
},
|
||||
want: nil,
|
||||
},
|
||||
{
|
||||
name: `Testing init container without name`,
|
||||
args: args{
|
||||
template: &api.PodTemplateSpec{},
|
||||
service: kobject.ServiceConfig{
|
||||
Labels: map[string]string{
|
||||
compose.LabelInitContainerName: "",
|
||||
compose.LabelInitContainerImage: "busybox:1.28",
|
||||
compose.LabelInitContainerCommand: `['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]`,
|
||||
},
|
||||
},
|
||||
},
|
||||
want: []corev1.Container{
|
||||
{
|
||||
Name: "init-service",
|
||||
Image: "busybox:1.28",
|
||||
Command: []string{
|
||||
"sh", "-c", `until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: `Testing init container without command`,
|
||||
args: args{
|
||||
template: &api.PodTemplateSpec{},
|
||||
service: kobject.ServiceConfig{
|
||||
Labels: map[string]string{
|
||||
compose.LabelInitContainerName: "init-service",
|
||||
compose.LabelInitContainerImage: "busybox:1.28",
|
||||
compose.LabelInitContainerCommand: ``,
|
||||
},
|
||||
},
|
||||
},
|
||||
want: []corev1.Container{
|
||||
{
|
||||
Name: "init-service",
|
||||
Image: "busybox:1.28",
|
||||
Command: []string{},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: `Testing init container without command`,
|
||||
args: args{
|
||||
template: &api.PodTemplateSpec{},
|
||||
service: kobject.ServiceConfig{
|
||||
Labels: map[string]string{
|
||||
compose.LabelInitContainerName: "init-service",
|
||||
compose.LabelInitContainerImage: "busybox:1.28",
|
||||
},
|
||||
},
|
||||
},
|
||||
want: []corev1.Container{
|
||||
{
|
||||
Name: "init-service",
|
||||
Image: "busybox:1.28",
|
||||
Command: []string{},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
fillInitContainers(tt.args.template, tt.args.service)
|
||||
if !reflect.DeepEqual(tt.args.template.Spec.InitContainers, tt.want) {
|
||||
t.Errorf("Test_fillInitContainers Fail got %v, want %v", tt.args.template.Spec.InitContainers, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user