diff --git a/packages/kn-plugin-workflow/pkg/command/quarkus/quarkus_project.go b/packages/kn-plugin-workflow/pkg/command/quarkus/quarkus_project.go index 6d3bf133e51..7440edfb962 100644 --- a/packages/kn-plugin-workflow/pkg/command/quarkus/quarkus_project.go +++ b/packages/kn-plugin-workflow/pkg/command/quarkus/quarkus_project.go @@ -20,8 +20,11 @@ package quarkus import ( + "bufio" "fmt" "os" + "path" + "strings" "github.com/apache/incubator-kie-tools/packages/kn-plugin-workflow/pkg/common" "github.com/apache/incubator-kie-tools/packages/kn-plugin-workflow/pkg/metadata" @@ -69,16 +72,31 @@ func CreateQuarkusProject(cfg CreateQuarkusProjectConfig) error { } //Until we are part of Quarkus 3.x bom we need to manipulate the pom.xml to use the right kogito dependencies - pomPath := cfg.ProjectName + "/pom.xml" + pomPath := path.Join(cfg.ProjectName, "pom.xml") if err := manipulatePomToKogito(pomPath, cfg); err != nil { return err } + + dockerIgnorePath := path.Join(cfg.ProjectName, ".dockerignore") + if err := manipulateDockerIgnore(dockerIgnorePath); err != nil { + return err + } + + extensions := []string{"jvm", "legacy-jar", "native", "native-micro"} + + for _, extension := range extensions { + dockerfilePath := path.Join(cfg.ProjectName, "src/main/docker", "Dockerfile."+extension) + if err := manipulateDockerfile(dockerfilePath); err != nil { + return err + } + } + return nil } func PostMavenCleanup(cfg CreateQuarkusProjectConfig) error { for _, file := range filesToRemove { - var fqdn = cfg.ProjectName + "/" + file + var fqdn = path.Join(cfg.ProjectName, file) if err := os.RemoveAll(fqdn); err != nil { return fmt.Errorf("error removing %s: %w", fqdn, err) } @@ -180,3 +198,67 @@ func manipulatePomToKogito(filename string, cfg CreateQuarkusProjectConfig) erro return nil } + +func manipulateDockerIgnore(filename string) error { + line := "\n!target/classes/workflow.sw.json" + f, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY, 0644) + defer f.Close() + + if _, err := f.WriteString(line); err != nil { + return fmt.Errorf("error writing to %s: %w", filename, err) + } + + if err != nil { + return fmt.Errorf("error opening %s: %w", filename, err) + } + return nil +} + +func manipulateDockerfile(filename string) error { + text := "COPY target/classes/workflow.sw.json /deployments/app/workflow.sw.json" + + file, err := os.Open(filename) + defer file.Close() + if err != nil { + return fmt.Errorf("error opening %s: %w", filename, err) + } + + appended := false + scanner := bufio.NewScanner(file) + + var lines []string + + for scanner.Scan() { + line := scanner.Text() + if strings.HasPrefix(line, "COPY") && !appended { + lines = append(lines, text) + appended = true + } + lines = append(lines, line) + } + + if err := scanner.Err(); err != nil { + return fmt.Errorf("error reading from %s: %w", filename, err) + } + + file, err = os.OpenFile(filename, os.O_WRONLY|os.O_TRUNC, 0644) + if err != nil { + return fmt.Errorf("error opening %s for writing: %w", filename, err) + } + defer file.Close() + + writer := bufio.NewWriter(file) + for _, line := range lines { + _, err := writer.WriteString(line + "\n") + if err != nil { + return fmt.Errorf("error writing to %s: %w", filename, err) + } + } + + err = writer.Flush() + if err != nil { + return fmt.Errorf("error flushing to %s: %w", filename, err) + } + + return nil +} diff --git a/packages/kn-plugin-workflow/pkg/command/quarkus/quarkus_project_test.go b/packages/kn-plugin-workflow/pkg/command/quarkus/quarkus_project_test.go index 98ccab8c5e9..d753476e268 100644 --- a/packages/kn-plugin-workflow/pkg/command/quarkus/quarkus_project_test.go +++ b/packages/kn-plugin-workflow/pkg/command/quarkus/quarkus_project_test.go @@ -20,7 +20,9 @@ package quarkus import ( + "bufio" "os" + "path" "testing" "github.com/apache/incubator-kie-tools/packages/kn-plugin-workflow/pkg/metadata" @@ -71,3 +73,88 @@ func TestManipulatePom(t *testing.T) { t.Errorf("Manipulated XML does not match expected XML") } } + +func TestManipulateDockerFiles(t *testing.T) { + text := "COPY target/classes/workflow.sw.json /deployments/app/workflow.sw.json" + tempDir, err := os.MkdirTemp("", "project") + if err != nil { + t.Fatalf("❌ ERROR: failed to create temporary directory: %v", err) + } + defer os.RemoveAll(tempDir) + + dockerDir := path.Join(tempDir, "/src/main/docker") + err = os.MkdirAll(dockerDir, 0755) + if err != nil { + t.Fatalf("Error creating docker directory: %v", err) + } + err = copyDir("testdata/docker", dockerDir) + if err != nil { + t.Fatalf("Error copying Dockerfiles: %v", err) + } + + extensions := []string{"jvm", "legacy-jar", "native", "native-micro"} + + for _, extension := range extensions { + dockerFilePath := path.Join(dockerDir, "Dockerfile."+extension) + _, err := os.Stat(dockerFilePath) + if err != nil { + t.Fatalf("Error reading Dockerfile: %v", err) + } + + if err := manipulateDockerfile(dockerFilePath); err != nil { + t.Fatalf("Error manipulating Dockerfile: %v", err) + } + + contains, err := checkFileContainsText(dockerFilePath, text) + if err != nil { + t.Fatalf("Failed to stat Dockerfile for extension %s: %v", extension, err) + } + if !contains { + t.Errorf("Dockerfile does not contain expected text") + } + } +} +func TestManipulateDockerIgnoreFile(t *testing.T) { + text := "!target/classes/workflow.sw.json" + tempDir, err := os.MkdirTemp("", "project") + if err != nil { + t.Fatalf("❌ ERROR: failed to create temporary directory: %v", err) + } + defer os.RemoveAll(tempDir) + + dockerIgnorePath := path.Join(tempDir, ".dockerignore") + err = copyFile("testdata/dockerignore", dockerIgnorePath) + if err != nil { + t.Fatalf("Error copying .dockerignore: %v", err) + } + if err := manipulateDockerIgnore(dockerIgnorePath); err != nil { + t.Fatalf("Error manipulating .dockerignore: %v", err) + } + contains, err := checkFileContainsText(dockerIgnorePath, text) + if err != nil { + t.Fatalf("Error reading .dockerignore: %v", err) + } + if !contains { + t.Errorf(".dockerignore does not contain expected text") + } + +} + +func checkFileContainsText(filePath, text string) (bool, error) { + file, err := os.Open(filePath) + if err != nil { + return false, err + } + defer file.Close() + + var contains = false + scanner := bufio.NewScanner(file) + for scanner.Scan() { + line := scanner.Text() + if line == text { + contains = true + break + } + } + return contains, nil +} diff --git a/packages/kn-plugin-workflow/pkg/command/quarkus/testdata/docker/Dockerfile.jvm b/packages/kn-plugin-workflow/pkg/command/quarkus/testdata/docker/Dockerfile.jvm new file mode 100644 index 00000000000..0d0f446b4b9 --- /dev/null +++ b/packages/kn-plugin-workflow/pkg/command/quarkus/testdata/docker/Dockerfile.jvm @@ -0,0 +1,16 @@ +FROM registry.access.redhat.com/ubi8/openjdk-17:1.18 + +ENV LANGUAGE='en_US:en' + + +COPY --chown=185 target/quarkus-app/lib/ /deployments/lib/ +COPY --chown=185 target/quarkus-app/*.jar /deployments/ +COPY --chown=185 target/quarkus-app/app/ /deployments/app/ +COPY --chown=185 target/quarkus-app/quarkus/ /deployments/quarkus/ + +EXPOSE 8080 +USER 185 +ENV JAVA_OPTS_APPEND="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" +ENV JAVA_APP_JAR="/deployments/quarkus-run.jar" + +ENTRYPOINT [ "/opt/jboss/container/java/run/run-java.sh" ] diff --git a/packages/kn-plugin-workflow/pkg/command/quarkus/testdata/docker/Dockerfile.legacy-jar b/packages/kn-plugin-workflow/pkg/command/quarkus/testdata/docker/Dockerfile.legacy-jar new file mode 100644 index 00000000000..9797ef13588 --- /dev/null +++ b/packages/kn-plugin-workflow/pkg/command/quarkus/testdata/docker/Dockerfile.legacy-jar @@ -0,0 +1,14 @@ +FROM registry.access.redhat.com/ubi8/openjdk-17:1.18 + +ENV LANGUAGE='en_US:en' + + +COPY target/lib/* /deployments/lib/ +COPY target/*-runner.jar /deployments/quarkus-run.jar + +EXPOSE 8080 +USER 185 +ENV JAVA_OPTS_APPEND="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" +ENV JAVA_APP_JAR="/deployments/quarkus-run.jar" + +ENTRYPOINT [ "/opt/jboss/container/java/run/run-java.sh" ] diff --git a/packages/kn-plugin-workflow/pkg/command/quarkus/testdata/docker/Dockerfile.native b/packages/kn-plugin-workflow/pkg/command/quarkus/testdata/docker/Dockerfile.native new file mode 100644 index 00000000000..b640808e62c --- /dev/null +++ b/packages/kn-plugin-workflow/pkg/command/quarkus/testdata/docker/Dockerfile.native @@ -0,0 +1,11 @@ +FROM registry.access.redhat.com/ubi8/ubi-minimal:8.9 +WORKDIR /work/ +RUN chown 1001 /work \ + && chmod "g+rwX" /work \ + && chown 1001:root /work +COPY --chown=1001:root target/*-runner /work/application + +EXPOSE 8080 +USER 1001 + +ENTRYPOINT ["./application", "-Dquarkus.http.host=0.0.0.0"] diff --git a/packages/kn-plugin-workflow/pkg/command/quarkus/testdata/docker/Dockerfile.native-micro b/packages/kn-plugin-workflow/pkg/command/quarkus/testdata/docker/Dockerfile.native-micro new file mode 100644 index 00000000000..fb244ab56f9 --- /dev/null +++ b/packages/kn-plugin-workflow/pkg/command/quarkus/testdata/docker/Dockerfile.native-micro @@ -0,0 +1,11 @@ +FROM quay.io/quarkus/quarkus-micro-image:2.0 +WORKDIR /work/ +RUN chown 1001 /work \ + && chmod "g+rwX" /work \ + && chown 1001:root /work +COPY --chown=1001:root target/*-runner /work/application + +EXPOSE 8080 +USER 1001 + +ENTRYPOINT ["./application", "-Dquarkus.http.host=0.0.0.0"] diff --git a/packages/kn-plugin-workflow/pkg/command/quarkus/testdata/dockerignore b/packages/kn-plugin-workflow/pkg/command/quarkus/testdata/dockerignore new file mode 100644 index 00000000000..94810d006e7 --- /dev/null +++ b/packages/kn-plugin-workflow/pkg/command/quarkus/testdata/dockerignore @@ -0,0 +1,5 @@ +* +!target/*-runner +!target/*-runner.jar +!target/lib/* +!target/quarkus-app/* \ No newline at end of file