From b0d46a4ce39434f4fbc9e861ef7d0de6f2b6a829 Mon Sep 17 00:00:00 2001 From: AhmedGrati <48932084+AhmedGrati@users.noreply.github.com> Date: Wed, 5 Jul 2023 11:37:28 +0100 Subject: [PATCH] Feat add custom build push (#1630) * feat: support custom build and push commands Signed-off-by: AhmedGrati * test: add functional tests of the support of custom build and push Signed-off-by: AhmedGrati * docs: add docs of the support of custom build and push Signed-off-by: AhmedGrati --------- Signed-off-by: AhmedGrati --- cmd/convert.go | 6 +++ docs/user-guide.md | 7 +++ pkg/kobject/kobject.go | 3 ++ pkg/transformer/kubernetes/kubernetes.go | 23 ++++++++++ script/test/cmd/tests_new.sh | 5 +++ .../fixtures/custom-build-push/Dockerfile | 3 ++ .../custom-build-push/docker-compose.yaml | 10 +++++ .../custom-build-push/output-k8s.yaml | 44 +++++++++++++++++++ 8 files changed, 101 insertions(+) create mode 100644 script/test/fixtures/custom-build-push/Dockerfile create mode 100644 script/test/fixtures/custom-build-push/docker-compose.yaml create mode 100644 script/test/fixtures/custom-build-push/output-k8s.yaml diff --git a/cmd/convert.go b/cmd/convert.go index dc327ee1..e022646a 100644 --- a/cmd/convert.go +++ b/cmd/convert.go @@ -54,6 +54,8 @@ var ( UpBuild string + BuildCommand string + PushCommand string // WithKomposeAnnotation decides if we will add metadata about this convert to resource's annotation. // default is true. WithKomposeAnnotation bool @@ -118,6 +120,8 @@ var convertCmd = &cobra.Command{ ServiceGroupName: ServiceGroupName, SecretsAsFiles: SecretsAsFiles, GenerateNetworkPolicies: GenerateNetworkPolicies, + BuildCommand: BuildCommand, + PushCommand: PushCommand, } if ServiceGroupMode == "" && MultipleContainerMode { @@ -170,6 +174,8 @@ func init() { // Standard between the two convertCmd.Flags().StringVar(&ConvertBuild, "build", "none", `Set the type of build ("local"|"build-config"(OpenShift only)|"none")`) convertCmd.Flags().BoolVar(&ConvertPushImage, "push-image", false, "If we should push the docker image we built") + convertCmd.Flags().StringVar(&BuildCommand, "build-command", "", `Set the command used to build the container image. override the docker build command.Should be used in conjuction with --push-command flag.`) + convertCmd.Flags().StringVar(&PushCommand, "push-command", "", `Set the command used to push the container image. override the docker push command. Should be used in conjuction with --build-command flag.`) convertCmd.Flags().StringVar(&ConvertPushImageRegistry, "push-image-registry", "", "Specify registry for pushing image, which will override registry from image name.") convertCmd.Flags().BoolVarP(&ConvertYaml, "yaml", "y", false, "Generate resource files into YAML format") convertCmd.Flags().MarkDeprecated("yaml", "YAML is the default format now.") diff --git a/docs/user-guide.md b/docs/user-guide.md index d0073371..c4fa2475 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -523,6 +523,13 @@ Now `config.json` should contain base64 encoded passwords, then push image shoul For Windows, there is also `credsStore` which is `wincred`. Technically it will fail on authentication as macOS does, but you can try the approach above like macOS too. +### Custom Build and Push +If you want to customize the build and push processes and use another containers solution than Docker, +Kompose offers you the possibility to do that. You can use `--build-command` and `--push-command` flags +to achieve that. + +e.g: `kompose -f convert --build-command 'whatever command --you-use' --push-command 'whatever command --you-use'` + ## Docker Compose Versions Kompose supports Docker Compose versions: 1, 2 and 3. We have limited support on versions 2.1 and 3.2 due to their experimental nature. diff --git a/pkg/kobject/kobject.go b/pkg/kobject/kobject.go index 8b6567c1..a5b4ba9e 100644 --- a/pkg/kobject/kobject.go +++ b/pkg/kobject/kobject.go @@ -73,6 +73,9 @@ type ConvertOptions struct { IsDeploymentConfigFlag bool IsNamespaceFlag bool + BuildCommand string + PushCommand string + Server string YAMLIndent int diff --git a/pkg/transformer/kubernetes/kubernetes.go b/pkg/transformer/kubernetes/kubernetes.go index 2226f3de..b46d6f35 100644 --- a/pkg/transformer/kubernetes/kubernetes.go +++ b/pkg/transformer/kubernetes/kubernetes.go @@ -20,6 +20,7 @@ import ( "encoding/base64" "fmt" "os" + "os/exec" "path" "path/filepath" "reflect" @@ -33,6 +34,7 @@ import ( "github.com/kubernetes/kompose/pkg/kobject" "github.com/kubernetes/kompose/pkg/loader/compose" "github.com/kubernetes/kompose/pkg/transformer" + "github.com/mattn/go-shellwords" deployapi "github.com/openshift/api/apps/v1" buildapi "github.com/openshift/api/build/v1" "github.com/pkg/errors" @@ -1333,6 +1335,27 @@ func buildServiceImage(opt kobject.ConvertOptions, service kobject.ServiceConfig // Check to see if there is an InputFile (required!) before we build the container // Check that there's actually a Build key // Lastly, we must have an Image name to continue + + // If the user provided a custom build it will override the docker one. + if opt.BuildCommand != "" && opt.PushCommand != "" { + p := shellwords.NewParser() + p.ParseEnv = true + + buildArgs, _ := p.Parse(opt.BuildCommand) + buildCommand := exec.Command(buildArgs[0], buildArgs[1:]...) + err := buildCommand.Run() + if err != nil { + return errors.Wrap(err, "error while trying to build a custom container image") + } + + pushArgs, _ := p.Parse(opt.PushCommand) + pushCommand := exec.Command(pushArgs[0], pushArgs[1:]...) + err = pushCommand.Run() + if err != nil { + return errors.Wrap(err, "error while trying to push a custom container image") + } + return nil + } if opt.Build == "local" && opt.InputFiles != nil && service.Build != "" { // If there's no "image" key, use the name of the container that's built if service.Image == "" { diff --git a/script/test/cmd/tests_new.sh b/script/test/cmd/tests_new.sh index e93ac645..5ce8f055 100755 --- a/script/test/cmd/tests_new.sh +++ b/script/test/cmd/tests_new.sh @@ -272,3 +272,8 @@ convert::expect_success "$os_cmd" "$os_output" k8s_cmd="kompose -f $KOMPOSE_ROOT/script/test/fixtures/network-policies/docker-compose.yaml convert --generate-network-policies --stdout --with-kompose-annotation=false" k8s_output="$KOMPOSE_ROOT/script/test/fixtures/network-policies/output-k8s.yaml" convert::expect_success "$os_cmd" "$os_output" + +# Test support for custom build and push images +k8s_cmd="kompose -f $KOMPOSE_ROOT/script/test/fixtures/custom-build-push/docker-compose.yaml convert --build-command 'docker build -t ahmedgrati/kompose-test ./script/test/fixtures/custom-build-push' --push-command 'docker push ahmedgrati/kompose-test' --stdout --with-kompose-annotation=false" +k8s_output="$KOMPOSE_ROOT/script/test/fixtures/custom-build-push/output-k8s.yaml" +convert::expect_success "$os_cmd" "$os_output" diff --git a/script/test/fixtures/custom-build-push/Dockerfile b/script/test/fixtures/custom-build-push/Dockerfile new file mode 100644 index 00000000..4be68ad1 --- /dev/null +++ b/script/test/fixtures/custom-build-push/Dockerfile @@ -0,0 +1,3 @@ +FROM busybox + +CMD ["sleep", "4800"] diff --git a/script/test/fixtures/custom-build-push/docker-compose.yaml b/script/test/fixtures/custom-build-push/docker-compose.yaml new file mode 100644 index 00000000..8b24f656 --- /dev/null +++ b/script/test/fixtures/custom-build-push/docker-compose.yaml @@ -0,0 +1,10 @@ +version: '3.8' + +networks: + web: + +services: + nginx: + image: nginx + networks: + - web diff --git a/script/test/fixtures/custom-build-push/output-k8s.yaml b/script/test/fixtures/custom-build-push/output-k8s.yaml new file mode 100644 index 00000000..32d118b6 --- /dev/null +++ b/script/test/fixtures/custom-build-push/output-k8s.yaml @@ -0,0 +1,44 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + creationTimestamp: null + labels: + io.kompose.service: nginx + name: nginx +spec: + replicas: 1 + selector: + matchLabels: + io.kompose.service: nginx + strategy: {} + template: + metadata: + creationTimestamp: null + labels: + io.kompose.network/custom-build-push-web: "true" + io.kompose.service: nginx + spec: + containers: + - image: nginx + name: nginx + resources: {} + restartPolicy: Always +status: {} + +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + creationTimestamp: null + name: custom-build-push-web +spec: + ingress: + - from: + - podSelector: + matchLabels: + io.kompose.network/custom-build-push-web: "true" + podSelector: + matchLabels: + io.kompose.network/custom-build-push-web: "true" +