Merge branch 'main' into feature-1635-with-labels

This commit is contained in:
jose luis committed 2024-04-10 17:29:38 +02:00
commit a589f1d6e9
13 files changed
+374 -23

No files matched your search

+1
View File
@@ -144,6 +144,7 @@ type ServiceConfig struct {
ExposeService string `compose:"kompose.service.expose"`
ExposeServicePath string `compose:"kompose.service.expose.path"`
BuildLabels map[string]string `compose:"build-labels"`
BuildTarget string `compose:""`
ExposeServiceTLS string `compose:"kompose.service.expose.tls-secret"`
ExposeServiceIngressClassName string `compose:"kompose.service.expose.ingress-class-name"`
ImagePullSecret string `compose:"kompose.image-pull-secret"`
+1
View File
@@ -559,6 +559,7 @@ func dockerComposeToKomposeMapping(composeObject *types.Project) (kobject.Kompos
serviceConfig.Dockerfile = composeServiceConfig.Build.Dockerfile
serviceConfig.BuildArgs = composeServiceConfig.Build.Args
serviceConfig.BuildLabels = composeServiceConfig.Build.Labels
serviceConfig.BuildTarget = composeServiceConfig.Build.Target
}
// env
+6
View File
@@ -88,6 +88,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"
// LabelNameOverride defines the override resource name
LabelNameOverride = "kompose.service.name_override"
)
+46 -1
View 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
}
+207
View File
@@ -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)
}
})
}
}
+1 -1
View File
@@ -396,7 +396,7 @@ func BuildDockerImage(service kobject.ServiceConfig, name string) error {
// Use the build struct function to build the image
// Build the image!
build := docker.Build{Client: *client}
err = build.BuildImage(imagePath, imageName, service.Dockerfile, buildargs)
err = build.BuildImage(imagePath, imageName, service.Dockerfile, buildargs, service.BuildTarget)
if err != nil {
return err
+9 -5
View File
@@ -43,16 +43,16 @@ in order to make building easier.
if the DOCKER_BUILDKIT is '1', then we will use the docker CLI to build the image
*/
func (c *Build) BuildImage(source string, image string, dockerfile string, buildargs []dockerlib.BuildArg) error {
func (c *Build) BuildImage(source string, image string, dockerfile string, buildargs []dockerlib.BuildArg, buildTarget string) error {
log.Infof("Building image '%s' from directory '%s'", image, path.Base(source))
outputBuffer := bytes.NewBuffer(nil)
var err error
if usecli, _ := strconv.ParseBool(os.Getenv("DOCKER_BUILDKIT")); usecli {
err = buildDockerCli(source, image, dockerfile, buildargs, outputBuffer)
err = buildDockerCli(source, image, dockerfile, buildargs, outputBuffer, buildTarget)
} else {
err = c.buildDockerClient(source, image, dockerfile, buildargs, outputBuffer)
err = c.buildDockerClient(source, image, dockerfile, buildargs, outputBuffer, buildTarget)
}
log.Debugf("Image %s build output:\n%s", image, outputBuffer)
@@ -66,7 +66,7 @@ func (c *Build) BuildImage(source string, image string, dockerfile string, build
return nil
}
func (c *Build) buildDockerClient(source string, image string, dockerfile string, buildargs []dockerlib.BuildArg, outputBuffer *bytes.Buffer) error {
func (c *Build) buildDockerClient(source string, image string, dockerfile string, buildargs []dockerlib.BuildArg, outputBuffer *bytes.Buffer, buildTarget string) error {
// Create a temporary file for tarball image packaging
tmpFile, err := os.CreateTemp(os.TempDir(), "kompose-image-build-")
if err != nil {
@@ -93,13 +93,14 @@ func (c *Build) buildDockerClient(source string, image string, dockerfile string
OutputStream: outputBuffer,
Dockerfile: dockerfile,
BuildArgs: buildargs,
Target: buildTarget,
}
// Build it!
return c.Client.BuildImage(opts)
}
func buildDockerCli(source string, image string, dockerfile string, buildargs []dockerlib.BuildArg, outputBuffer *bytes.Buffer) error {
func buildDockerCli(source string, image string, dockerfile string, buildargs []dockerlib.BuildArg, outputBuffer *bytes.Buffer, buildTarget string) error {
args := []string{"build", "-t", image}
if dockerfile != "" {
@@ -111,6 +112,9 @@ func buildDockerCli(source string, image string, dockerfile string, buildargs []
}
args = append(args, source)
if buildTarget != "" {
args = append(args, fmt.Sprintf("--target=%s", buildTarget))
}
cmd := exec.Command("docker", args...)
cmd.Stdout = outputBuffer