From 471b66203383643e126b092da91689503fb347fd Mon Sep 17 00:00:00 2001 From: Fabio Burzigotti Date: Tue, 19 Dec 2023 16:35:26 +0100 Subject: [PATCH 1/2] [issue 123] - Implement WildFly/EAP 8 Helm Charts provisioning differentiation --- ...tingValuesOpenShiftExampleApplication.java | 42 +- ...elmChartExistingValuesProvisionerTest.java | 6 +- ...yHelmChartOpenShiftExampleApplication.java | 45 +- .../WildflyHelmChartProvisionerTest.java | 2 +- .../provision/openshift/eap8-helm-values.yaml | 22 + tools/intersmash-tools-provisioners/pom.xml | 15 +- .../openshift/helm/HelmChartRelease.java | 62 +- .../helm/HelmChartReleaseAdapter.java | 86 +++ .../tools/provision/helm/Image.java | 34 + .../WildFlyHelmChartReleaseAdapter.java | 703 +++++++++++++++++ .../WildflyHelmChartOpenShiftProvisioner.java | 3 +- ...yHelmChartOpenShiftProvisionerFactory.java | 3 +- .../helm/wildfly/WildflyHelmChartRelease.java | 177 +++++ .../eap8/Eap8HelmChartReleaseAdapter.java | 725 ++++++++++++++++++ ...ersmash.tools.provision.ProvisionerFactory | 3 +- .../values/schema/eap8/helm-eap8-release.json | 633 +++++++++++++++ .../Eap8HelmChartReleaseAdapterTest.java | 205 +++++ 17 files changed, 2659 insertions(+), 107 deletions(-) create mode 100644 testsuite/src/test/resources/org/jboss/intersmash/testsuite/provision/openshift/eap8-helm-values.yaml create mode 100644 tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/HelmChartReleaseAdapter.java create mode 100644 tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/Image.java create mode 100644 tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/wildfly/WildFlyHelmChartReleaseAdapter.java rename tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/{ => wildfly}/WildflyHelmChartOpenShiftProvisioner.java (95%) rename tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/{ => wildfly}/WildflyHelmChartOpenShiftProvisionerFactory.java (91%) create mode 100644 tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/wildfly/WildflyHelmChartRelease.java create mode 100644 tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/wildfly/eap8/Eap8HelmChartReleaseAdapter.java create mode 100644 tools/intersmash-tools-provisioners/src/main/resources/org/jboss/intersmash/tools/provision/helm/values/schema/eap8/helm-eap8-release.json create mode 100644 tools/intersmash-tools-provisioners/src/test/java/org/jboss/intersmash/tools/provision/helm/wildfly/Eap8HelmChartReleaseAdapterTest.java diff --git a/testsuite/src/test/java/org/jboss/intersmash/testsuite/provision/openshift/WildflyHelmChartExistingValuesOpenShiftExampleApplication.java b/testsuite/src/test/java/org/jboss/intersmash/testsuite/provision/openshift/WildflyHelmChartExistingValuesOpenShiftExampleApplication.java index 6fdbf9897..6a3626010 100644 --- a/testsuite/src/test/java/org/jboss/intersmash/testsuite/provision/openshift/WildflyHelmChartExistingValuesOpenShiftExampleApplication.java +++ b/testsuite/src/test/java/org/jboss/intersmash/testsuite/provision/openshift/WildflyHelmChartExistingValuesOpenShiftExampleApplication.java @@ -15,22 +15,21 @@ */ package org.jboss.intersmash.testsuite.provision.openshift; -import java.net.URL; -import java.nio.file.Path; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.jboss.intersmash.deployments.WildflyDeploymentApplicationConfiguration; +import org.jboss.intersmash.model.helm.charts.values.eap8.HelmEap8Release; import org.jboss.intersmash.model.helm.charts.values.wildfly.HelmWildflyRelease; +import org.jboss.intersmash.testsuite.IntersmashTestsuiteProperties; import org.jboss.intersmash.tools.IntersmashConfig; import org.jboss.intersmash.tools.application.openshift.helm.HelmChartRelease; import org.jboss.intersmash.tools.application.openshift.helm.WildflyHelmChartOpenShiftApplication; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; -import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator; +import org.jboss.intersmash.tools.provision.helm.HelmChartReleaseAdapter; +import org.jboss.intersmash.tools.provision.helm.wildfly.WildFlyHelmChartReleaseAdapter; +import org.jboss.intersmash.tools.provision.helm.wildfly.eap8.Eap8HelmChartReleaseAdapter; import io.fabric8.kubernetes.api.model.Secret; @@ -42,7 +41,7 @@ public class WildflyHelmChartExistingValuesOpenShiftExampleApplication private final Map setOverrides = new HashMap<>(); public WildflyHelmChartExistingValuesOpenShiftExampleApplication() { - this.release = new HelmChartRelease(loadRelease()); + this.release = loadRelease(); } WildflyHelmChartExistingValuesOpenShiftExampleApplication addSetOverride(String name, String value) { @@ -55,20 +54,21 @@ public Map getSetOverrides() { return setOverrides; } - private HelmWildflyRelease loadRelease() { - URL url = this.getClass().getResource("wildfly-helm-values.yaml"); - if (url == null) { - throw new IllegalStateException("No wildfly-helm-values.yaml found"); - } - try { - Path valuePath = Path.of(url.toURI()); - ObjectMapper mapper = new ObjectMapper(new YAMLFactory().disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER)); - return mapper.readValue(valuePath.toFile(), HelmWildflyRelease.class); - } catch (Error | RuntimeException e) { - throw e; - } catch (Exception e) { - throw new RuntimeException(e); - } + private HelmChartRelease loadRelease() { + if (IntersmashTestsuiteProperties.isCommunityTestExecutionProfileEnabled()) { + HelmWildflyRelease helmRelease = HelmChartReleaseAdapter. fromValuesFile( + this.getClass().getResource("wildfly-helm-values.yaml"), HelmWildflyRelease.class); + return new WildFlyHelmChartReleaseAdapter(helmRelease) + .withJdk17BuilderImage(IntersmashConfig.wildflyImageURL()) + .withJdk17RuntimeImage(IntersmashConfig.wildflyRuntimeImageURL()); + } else if (IntersmashTestsuiteProperties.isProductizedTestExecutionProfileEnabled()) { + HelmEap8Release helmRelease = HelmChartReleaseAdapter. fromValuesFile( + this.getClass().getResource("eap8-helm-values.yaml"), HelmEap8Release.class); + return new Eap8HelmChartReleaseAdapter(helmRelease) + .withJdk17BuilderImage(IntersmashConfig.wildflyImageURL()) + .withJdk17RuntimeImage(IntersmashConfig.wildflyRuntimeImageURL()); + } else + throw new IllegalStateException("Not a valid testing profile!"); } @Override diff --git a/testsuite/src/test/java/org/jboss/intersmash/testsuite/provision/openshift/WildflyHelmChartExistingValuesProvisionerTest.java b/testsuite/src/test/java/org/jboss/intersmash/testsuite/provision/openshift/WildflyHelmChartExistingValuesProvisionerTest.java index 417238303..b43e2c172 100644 --- a/testsuite/src/test/java/org/jboss/intersmash/testsuite/provision/openshift/WildflyHelmChartExistingValuesProvisionerTest.java +++ b/testsuite/src/test/java/org/jboss/intersmash/testsuite/provision/openshift/WildflyHelmChartExistingValuesProvisionerTest.java @@ -17,7 +17,7 @@ import org.jboss.intersmash.tools.IntersmashConfig; import org.jboss.intersmash.tools.provision.helm.HelmChartOpenShiftProvisioner; -import org.jboss.intersmash.tools.provision.helm.WildflyHelmChartOpenShiftProvisioner; +import org.jboss.intersmash.tools.provision.helm.wildfly.WildflyHelmChartOpenShiftProvisioner; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -37,9 +37,7 @@ public void basicProvisioningTest() { final WildflyHelmChartExistingValuesOpenShiftExampleApplication application = new WildflyHelmChartExistingValuesOpenShiftExampleApplication(); application .addSetOverride("build.uri", IntersmashConfig.deploymentsRepositoryUrl()) - .addSetOverride("build.ref", IntersmashConfig.deploymentsRepositoryRef()) - .addSetOverride("deploy.builderImage", application.getBuilderImage()) - .addSetOverride("deployRuntimeImage", application.getRuntimeImage()); + .addSetOverride("build.ref", IntersmashConfig.deploymentsRepositoryRef()); // and now get an EAP 8/WildFly provisioner for that application final WildflyHelmChartOpenShiftProvisioner provisioner = new WildflyHelmChartOpenShiftProvisioner(application); diff --git a/testsuite/src/test/java/org/jboss/intersmash/testsuite/provision/openshift/WildflyHelmChartOpenShiftExampleApplication.java b/testsuite/src/test/java/org/jboss/intersmash/testsuite/provision/openshift/WildflyHelmChartOpenShiftExampleApplication.java index e31310145..dcd63a4ce 100644 --- a/testsuite/src/test/java/org/jboss/intersmash/testsuite/provision/openshift/WildflyHelmChartOpenShiftExampleApplication.java +++ b/testsuite/src/test/java/org/jboss/intersmash/testsuite/provision/openshift/WildflyHelmChartOpenShiftExampleApplication.java @@ -15,8 +15,6 @@ */ package org.jboss.intersmash.testsuite.provision.openshift; -import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -26,11 +24,15 @@ import org.jboss.intersmash.model.helm.charts.values.wildfly.Build; import org.jboss.intersmash.model.helm.charts.values.wildfly.Deploy; import org.jboss.intersmash.model.helm.charts.values.wildfly.Env; +import org.jboss.intersmash.model.helm.charts.values.eap8.HelmEap8Release; import org.jboss.intersmash.model.helm.charts.values.wildfly.HelmWildflyRelease; -import org.jboss.intersmash.model.helm.charts.values.wildfly.S2i; +import org.jboss.intersmash.testsuite.IntersmashTestsuiteProperties; import org.jboss.intersmash.tools.IntersmashConfig; import org.jboss.intersmash.tools.application.openshift.helm.HelmChartRelease; import org.jboss.intersmash.tools.application.openshift.helm.WildflyHelmChartOpenShiftApplication; +import org.jboss.intersmash.tools.provision.helm.wildfly.WildFlyHelmChartReleaseAdapter; +import org.jboss.intersmash.tools.provision.helm.wildfly.WildflyHelmChartRelease; +import org.jboss.intersmash.tools.provision.helm.wildfly.eap8.Eap8HelmChartReleaseAdapter; import io.fabric8.kubernetes.api.model.Secret; @@ -41,11 +43,15 @@ public class WildflyHelmChartOpenShiftExampleApplication private final HelmChartRelease release; public WildflyHelmChartOpenShiftExampleApplication() { - this.release = new HelmChartRelease(loadRelease()); + if (IntersmashTestsuiteProperties.isCommunityTestExecutionProfileEnabled()) { + release = loadRelease(new WildFlyHelmChartReleaseAdapter(new HelmWildflyRelease())); + } else if (IntersmashTestsuiteProperties.isProductizedTestExecutionProfileEnabled()) { + release = loadRelease(new Eap8HelmChartReleaseAdapter(new HelmEap8Release())); + } else + throw new IllegalStateException("Not a valid testing profile!"); } - private HelmWildflyRelease loadRelease() { - HelmWildflyRelease release = new HelmWildflyRelease(); + private HelmChartRelease loadRelease(final WildflyHelmChartRelease release) { // let's compute some additional maven args for our s2i build to happen on a Pod String mavenAdditionalArgs = "-Denforcer.skip=true"; // let's add configurable deployment additional args: @@ -55,24 +61,17 @@ private HelmWildflyRelease loadRelease() { (Strings.isNullOrEmpty(IntersmashSharedDeploymentsProperties.getWildflyDeploymentsBuildProfile()) ? "" : " -Pwildfly-deployments-build." + IntersmashSharedDeploymentsProperties.getWildflyDeploymentsBuildProfile())); - // ok, let's configure the release via the fluent(-ish) API - List environmentVariables = new ArrayList(); + // ok, let's configure the release via the WildflyHelmChartRelease fluent(-ish) API, + // which offers a common reference for both WildFly and EAP (latest) release - .withBuild( - new Build() - .withUri(IntersmashConfig.deploymentsRepositoryUrl()) - .withRef(IntersmashConfig.deploymentsRepositoryRef()) - .withContextDir("deployments/openshift-jakarta-sample-standalone") - .withEnv( - Arrays.asList( - new Env() - .withName("MAVEN_ARGS_APPEND") - .withValue(mavenAdditionalArgs))) - .withS2i( - new S2i() - .withBuilderImage(IntersmashConfig.wildflyImageURL()) - .withRuntimeImage(IntersmashConfig.wildflyRuntimeImageURL()))) - .withDeploy(new Deploy().withReplicas(1)); + .withSourceRepositoryUrl(IntersmashConfig.deploymentsRepositoryUrl()) + .withSourceRepositoryRef(IntersmashConfig.deploymentsRepositoryRef()) + .withContextDir("deployments/openshift-jakarta-sample-standalone") + // an example, not working with EAP 7.4.x or WildFly and commented in the deployment POM + .withS2iChannel(IntersmashConfig.getWildflyEeChannelLocation()) + .withJdk17BuilderImage(IntersmashConfig.wildflyImageURL()) + .withJdk17RuntimeImage(IntersmashConfig.wildflyRuntimeImageURL()) + .withBuildEnvironmentVariable("MAVEN_ARGS_APPEND", mavenAdditionalArgs); return release; } diff --git a/testsuite/src/test/java/org/jboss/intersmash/testsuite/provision/openshift/WildflyHelmChartProvisionerTest.java b/testsuite/src/test/java/org/jboss/intersmash/testsuite/provision/openshift/WildflyHelmChartProvisionerTest.java index cebf5c93f..9be4ccb5a 100644 --- a/testsuite/src/test/java/org/jboss/intersmash/testsuite/provision/openshift/WildflyHelmChartProvisionerTest.java +++ b/testsuite/src/test/java/org/jboss/intersmash/testsuite/provision/openshift/WildflyHelmChartProvisionerTest.java @@ -17,7 +17,7 @@ import org.jboss.intersmash.tools.application.openshift.helm.WildflyHelmChartOpenShiftApplication; import org.jboss.intersmash.tools.provision.helm.HelmChartOpenShiftProvisioner; -import org.jboss.intersmash.tools.provision.helm.WildflyHelmChartOpenShiftProvisioner; +import org.jboss.intersmash.tools.provision.helm.wildfly.WildflyHelmChartOpenShiftProvisioner; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/testsuite/src/test/resources/org/jboss/intersmash/testsuite/provision/openshift/eap8-helm-values.yaml b/testsuite/src/test/resources/org/jboss/intersmash/testsuite/provision/openshift/eap8-helm-values.yaml new file mode 100644 index 000000000..ccac1acc7 --- /dev/null +++ b/testsuite/src/test/resources/org/jboss/intersmash/testsuite/provision/openshift/eap8-helm-values.yaml @@ -0,0 +1,22 @@ +build: + enabled: true + mode: "s2i" + # uri and ref will be specified via Helm --set arguments + contextDir: "deployments/openshift-jakarta-sample-standalone" + env: + - name: "MAVEN_ARGS_APPEND" + value: "-Denforcer.skip=true -Pwildfly-deployments-build.eap" + s2i: + kind: "DockerImage" + buildApplicationImage: true + # builderImage and runtimeImage will be specified via Helm --set arguments +deploy: + enabled: true + replicas: 1 + env: [] + envFrom: [] + volumeMounts: [] + volumes: [] + initContainers: [] + extraContainers: [] + 'imagePullSecrets:': [] diff --git a/tools/intersmash-tools-provisioners/pom.xml b/tools/intersmash-tools-provisioners/pom.xml index ec718f85f..ee0bb2f66 100644 --- a/tools/intersmash-tools-provisioners/pom.xml +++ b/tools/intersmash-tools-provisioners/pom.xml @@ -204,7 +204,7 @@ src/main/resources/crds false @@ -228,11 +228,24 @@ generate + ${basedir}/src/main/resources/org/jboss/intersmash/tools/provision/helm/values/schema/wildfly ${project.build.directory}/generated-sources/ org.jboss.intersmash.model.helm.charts.values.wildfly + + charts.values.generate-schema-model.eap8 + + generate + + + + ${basedir}/src/main/resources/org/jboss/intersmash/tools/provision/helm/values/schema/eap8 + ${project.build.directory}/generated-sources/ + org.jboss.intersmash.model.helm.charts.values.eap8 + + diff --git a/tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/application/openshift/helm/HelmChartRelease.java b/tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/application/openshift/helm/HelmChartRelease.java index 5652c78fd..86469526e 100644 --- a/tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/application/openshift/helm/HelmChartRelease.java +++ b/tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/application/openshift/helm/HelmChartRelease.java @@ -15,40 +15,20 @@ */ package org.jboss.intersmash.tools.application.openshift.helm; -import java.io.IOException; -import java.nio.file.Files; import java.nio.file.Path; -import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; -import org.jboss.intersmash.model.helm.charts.values.wildfly.HelmWildflyRelease; import org.jboss.intersmash.tools.provision.helm.HelmChartOpenShiftProvisioner; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; -import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator; - /** * Defines the contract for implementing classes to represent a Helm Charts release, as seen by the provisioning * tooling. */ -public class HelmChartRelease implements SerializableHelmChartRelease { - - private final HelmWildflyRelease wildflyRelease; - private final List additionalValuesFiles = new ArrayList<>(); - - public HelmChartRelease(HelmWildflyRelease wildflyRelease) { - this(wildflyRelease, null); - } - - public HelmChartRelease(HelmWildflyRelease wildflyRelease, List additionalValuesFiles) { - this.wildflyRelease = wildflyRelease; - if (additionalValuesFiles != null) { - this.additionalValuesFiles.addAll(additionalValuesFiles.stream().collect(Collectors.toList())); - } - } +/** + * Defines the contract for implementing classes to represent a Helm Charts release, as seen by the provisioning + * tooling. + */ +public interface HelmChartRelease extends SerializableHelmChartRelease { /** * Read the number of replicas that the release should generate @@ -57,9 +37,7 @@ public HelmChartRelease(HelmWildflyRelease wildflyRelease, List additional * * @return {@link Integer} representing the number of replicas that the release should generate */ - public Integer getReplicas() { - return wildflyRelease.getDeploy().getReplicas(); - } + Integer getReplicas(); /** * Set the number of replicas that should be generated by the release @@ -68,9 +46,7 @@ public Integer getReplicas() { * * @param replicas Number of replicas that should be generated by the release */ - public void setReplicas(Integer replicas) { - this.wildflyRelease.getDeploy().setReplicas(replicas); - } + void setReplicas(Integer replicas); /** * Access the additional values files collection @@ -79,27 +55,5 @@ public void setReplicas(Integer replicas) { * @return List of {@link Path} instances representing the location of additional values files that make the * release */ - public List getAdditionalValuesFiles() { - return this.additionalValuesFiles; - } - - @Override - public Path toValuesFile() { - // Handle the values file creation - Path temp; - try { - temp = Files.createTempFile("values", ".yaml"); - } catch (IOException e) { - throw new IllegalStateException("Temporary Helm Chart values file creation failed.", e); - } - ObjectMapper mapper = new ObjectMapper(new YAMLFactory().disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER)); - mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); - try { - mapper.writeValue(temp.toFile(), wildflyRelease); - } catch (IOException e) { - throw new IllegalStateException("Helm Chart values serialization failed.", e); - } - return temp; - } - + List getAdditionalValuesFiles(); } diff --git a/tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/HelmChartReleaseAdapter.java b/tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/HelmChartReleaseAdapter.java new file mode 100644 index 000000000..483113cc2 --- /dev/null +++ b/tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/HelmChartReleaseAdapter.java @@ -0,0 +1,86 @@ +package org.jboss.intersmash.tools.provision.helm; + +import java.io.IOException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +import org.jboss.intersmash.tools.application.openshift.helm.SerializableHelmChartRelease; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator; + +import lombok.NonNull; + +/** + * An adapter that implements a valid {@link org.jboss.intersmash.tools.application.openshift.helm.HelmChartRelease} by exposing an internal generic instance of a POJO + * that represents the release data and that can be serialized to a values file, as an output for + * {@link org.jboss.intersmash.tools.application.openshift.helm.HelmChartRelease#toValuesFile()} + */ +public class HelmChartReleaseAdapter implements SerializableHelmChartRelease { + + protected final A adaptee; + protected final List additionalValuesFiles; + + public HelmChartReleaseAdapter(@NonNull A release) { + this(release, new ArrayList<>()); + } + + public HelmChartReleaseAdapter(@NonNull A release, List additionalValuesFiles) { + this.adaptee = release; + this.additionalValuesFiles = additionalValuesFiles; + } + + public A getAdaptee() { + return adaptee; + } + + @Override + public Path toValuesFile() { + // Handle the values file creation + Path temp; + try { + temp = Files.createTempFile("values", ".yaml"); + } catch (IOException e) { + throw new IllegalStateException("Temporary Helm Chart values file creation failed.", e); + } + ObjectMapper mapper = new ObjectMapper(new YAMLFactory().disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER)); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + try { + mapper.writeValue(temp.toFile(), adaptee); + } catch (IOException e) { + throw new IllegalStateException("Helm Chart values serialization failed.", e); + } + return temp; + } + + /** + * Implementors must generate the POJO by deserializing the data at each call and reflect the information held by + * the concrete instance + * @param valuesFileUrl Source values file URL + * @param typeClazz Deserialized POJO type + * @return A concrete instance of {@link A} generated from a source values file + */ + public static A fromValuesFile(final URL valuesFileUrl, Class typeClazz) { + if (valuesFileUrl == null) { + throw new IllegalStateException("No values file provided!"); + } + try { + Path valuePath = Path.of(valuesFileUrl.toURI()); + ObjectMapper mapper = new ObjectMapper(new YAMLFactory().disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER)); + return mapper.readValue(valuePath.toFile(), typeClazz); + } catch (Error | RuntimeException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public List getAdditionalValuesFiles() { + return additionalValuesFiles; + } +} diff --git a/tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/Image.java b/tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/Image.java new file mode 100644 index 000000000..587111438 --- /dev/null +++ b/tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/Image.java @@ -0,0 +1,34 @@ +package org.jboss.intersmash.tools.provision.helm; + +import java.util.List; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +public class Image { + + private final From from; + private final List paths; + + @Getter + @Setter + @AllArgsConstructor + public static class From { + private final String kind; + private final String namespace; + private final String name; + + } + + @Getter + @Setter + @AllArgsConstructor + public static class Path { + private final String sourcePath; + private final String destinationDir; + } +} diff --git a/tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/wildfly/WildFlyHelmChartReleaseAdapter.java b/tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/wildfly/WildFlyHelmChartReleaseAdapter.java new file mode 100644 index 000000000..f8b791ec1 --- /dev/null +++ b/tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/wildfly/WildFlyHelmChartReleaseAdapter.java @@ -0,0 +1,703 @@ +package org.jboss.intersmash.tools.provision.helm.wildfly; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.jboss.intersmash.model.helm.charts.values.wildfly.BootableJar; +import org.jboss.intersmash.model.helm.charts.values.wildfly.Build; +import org.jboss.intersmash.model.helm.charts.values.wildfly.Deploy; +import org.jboss.intersmash.model.helm.charts.values.wildfly.Env; +import org.jboss.intersmash.model.helm.charts.values.wildfly.Env__1; +import org.jboss.intersmash.model.helm.charts.values.wildfly.HelmWildflyRelease; +import org.jboss.intersmash.model.helm.charts.values.wildfly.Route; +import org.jboss.intersmash.model.helm.charts.values.wildfly.S2i; +import org.jboss.intersmash.model.helm.charts.values.wildfly.Tls; +import org.jboss.intersmash.model.helm.charts.values.wildfly.Tls__1; +import org.jboss.intersmash.tools.application.openshift.helm.HelmChartRelease; +import org.jboss.intersmash.tools.provision.helm.HelmChartReleaseAdapter; +import org.jboss.intersmash.tools.provision.helm.Image; + +import com.google.common.base.Strings; + +import io.fabric8.kubernetes.api.model.Volume; +import io.fabric8.kubernetes.api.model.VolumeMount; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; + +/** + * An adapter that implements a valid WildFly {@link HelmChartRelease} by exposing an internal instance of + * {@link HelmWildflyRelease} to store a WildFly Helm Charts release data and to represent a values file which can be serialized + * as an output for {@link HelmChartRelease#toValuesFile()} + * + * This adapter is compliant with the contract which is required by the + * {@link org.jboss.intersmash.tools.provision.helm.HelmChartOpenShiftProvisioner} logic, i.e. to + * implement {@link HelmChartRelease}, and allows for us to leverage a generated + * {@link WildFlyHelmChartReleaseAdapter#adaptee}, i.e. in terms of UX, provide native release YAML definitions. + * + * Of course the generated APIs can also be used programmatically. + */ +@Slf4j +public class WildFlyHelmChartReleaseAdapter extends HelmChartReleaseAdapter + implements HelmChartRelease, WildflyHelmChartRelease { + + public WildFlyHelmChartReleaseAdapter(@NonNull HelmWildflyRelease release) { + super(release, new ArrayList<>()); + initDefaultReplicas(release); + } + + public WildFlyHelmChartReleaseAdapter(@NonNull HelmWildflyRelease release, List additionalValuesFiles) { + super(release, additionalValuesFiles); + initDefaultReplicas(release); + } + + @Override + public Map getDeploymentEnvironmentVariables() { + return adaptee.getDeploy() == null ? Map.of() + : adaptee.getDeploy().getEnv() == null || adaptee.getDeploy().getEnv().isEmpty() ? Map.of() + : adaptee.getDeploy().getEnv().stream() + .collect(Collectors.toMap(e -> e.getName(), e -> e.getValue())); + } + + @Override + public void setDeploymentEnvironmentVariables(Map deploymentEnvironmentVariables) { + if (adaptee.getDeploy() == null) { + adaptee.setDeploy(new Deploy()); + } + if ((adaptee.getDeploy().getEnv() == null) || adaptee.getDeploy().getEnv().isEmpty()) { + adaptee.getDeploy().setEnv(new ArrayList<>()); + } else { + adaptee.getDeploy().getEnv().clear(); + } + // let's check just here, so there's a way to clear, i.e. by passing an empty or null list + if ((deploymentEnvironmentVariables != null) && !deploymentEnvironmentVariables.isEmpty()) { + deploymentEnvironmentVariables.entrySet().stream() + .map(e -> adaptee.getDeploy().getEnv().add(new Env__1().withName(e.getKey()).withValue(e.getValue()))); + } + } + + public WildflyHelmChartRelease withDeploymentEnvironmentVariables( + Map deploymentEnvironmentVariables) { + this.setDeploymentEnvironmentVariables(deploymentEnvironmentVariables); + return this; + } + + @Override + public WildflyHelmChartRelease withDeploymentEnvironmentVariable(String key, String value) { + if (adaptee.getDeploy() == null) { + adaptee.setDeploy(new Deploy()); + } + if ((adaptee.getDeploy().getEnv() == null) || adaptee.getDeploy().getEnv().isEmpty()) { + adaptee.getDeploy().setEnv(new ArrayList<>()); + } + adaptee.getDeploy().getEnv().add(new Env__1().withName(key).withValue(value)); + return this; + } + + @Override + public Map getBuildEnvironmentVariables() { + return adaptee.getBuild() == null ? Map.of() + : adaptee.getBuild().getEnv() == null || adaptee.getBuild().getEnv().isEmpty() ? Map.of() + : adaptee.getBuild().getEnv().stream() + .collect(Collectors.toMap(e -> e.getName(), e -> e.getValue())); + } + + @Override + public void setBuildEnvironmentVariables(Map buildEnvironmentVariables) { + if (adaptee.getBuild() == null) { + adaptee.setBuild(new Build()); + } + if ((adaptee.getBuild().getEnv() == null) || adaptee.getBuild().getEnv().isEmpty()) { + adaptee.getBuild().setEnv(new ArrayList<>()); + } else { + adaptee.getBuild().getEnv().clear(); + } + // let's check just here, so there's a way to clear, i.e. by passing an empty or null list + if ((buildEnvironmentVariables != null) && !buildEnvironmentVariables.isEmpty()) { + buildEnvironmentVariables.entrySet().stream() + .map(e -> adaptee.getBuild().getEnv().add(new Env().withName(e.getKey()).withValue(e.getValue()))); + } + } + + public WildflyHelmChartRelease withBuildEnvironmentVariables(Map buildEnvironmentVariables) { + this.setBuildEnvironmentVariables(buildEnvironmentVariables); + return this; + } + + @Override + public WildflyHelmChartRelease withBuildEnvironmentVariable(String key, String value) { + + if (adaptee.getBuild() == null) { + adaptee.setBuild(new Build()); + } + if ((adaptee.getBuild().getEnv() == null) || adaptee.getBuild().getEnv().isEmpty()) { + adaptee.getBuild().setEnv(new ArrayList<>()); + } + adaptee.getBuild().getEnv().add(new Env().withName(key).withValue(value)); + return this; + } + + @Override + public List getInjectedImages() { + return adaptee.getBuild() == null ? List.of() + : adaptee.getBuild().getImages() == null ? List.of() + : (List) adaptee.getBuild().getImages(); + } + + @Override + public void setInjectedImages(List injectedImages) { + if (adaptee.getBuild() == null) { + adaptee.setBuild(new Build()); + } + if ((adaptee.getBuild().getImages() == null)) { + adaptee.getBuild().setImages(new ArrayList<>()); + } else { + ((List) adaptee.getBuild().getImages()).clear(); + } + // let's check just here, so there's a way to clear, i.e. by passing an empty or null list + if ((injectedImages != null) && !injectedImages.isEmpty()) { + ((List) adaptee.getBuild().getImages()).addAll(injectedImages); + } + } + + @Override + public WildflyHelmChartRelease withInjectedImages(List injectedImages) { + this.setInjectedImages(injectedImages); + return this; + } + + @Override + public WildflyHelmChartRelease withInjectedImage(Image injectedImage) { + if (adaptee.getBuild() == null) { + adaptee.setBuild(new Build()); + } + if (adaptee.getBuild().getImages() == null) { + adaptee.getBuild().setImages(new ArrayList<>()); + } + ((List) adaptee.getBuild().getImages()).add(injectedImage); + return this; + } + + @Override + public List getVolumes() { + return adaptee.getDeploy() == null ? List.of() + : adaptee.getDeploy().getVolumes() == null ? List.of() + : adaptee.getDeploy().getVolumes().stream() + .map(v -> (Volume) v) + .collect(Collectors.toList()); + } + + @Override + public void setVolumes(List volumes) { + if (adaptee.getDeploy() == null) { + adaptee.setDeploy(new Deploy()); + } + if ((adaptee.getDeploy().getVolumes() == null) || adaptee.getDeploy().getVolumes().isEmpty()) { + adaptee.getDeploy().setVolumes(new ArrayList<>()); + } else { + adaptee.getDeploy().getVolumes().clear(); + } + // let's check just here, so there's a way to clear, i.e. by passing an empty or null list + if ((volumes != null) && !volumes.isEmpty()) { + volumes.stream() + .map(v -> adaptee.getDeploy().getVolumes().add(v)) + .collect(Collectors.toList()); + } + } + + public WildflyHelmChartRelease withVolumes(List volumes) { + this.setVolumes(volumes); + return this; + } + + @Override + public WildflyHelmChartRelease withVolume(Volume volume) { + if (adaptee.getDeploy() == null) { + adaptee.setDeploy(new Deploy()); + } + if ((adaptee.getDeploy().getVolumes() == null) || adaptee.getDeploy().getVolumes().isEmpty()) { + adaptee.getDeploy().setVolumes(new ArrayList<>()); + } + adaptee.getDeploy().getVolumes().add(volume); + return this; + } + + @Override + public List getVolumeMounts() { + return adaptee.getDeploy() == null ? List.of() + : adaptee.getDeploy().getVolumeMounts() == null ? List.of() + : adaptee.getDeploy().getVolumeMounts().stream() + .map(v -> new VolumeMount( + v.getMountPath(), + v.getMountPropagation(), + v.getName(), + v.getReadOnly(), + v.getSubPath(), null)) + .collect(Collectors.toList()); + } + + @Override + public void setVolumeMounts(List volumeMounts) { + if (adaptee.getDeploy() == null) { + adaptee.setDeploy(new Deploy()); + } + if ((adaptee.getDeploy().getVolumeMounts() == null) || adaptee.getDeploy().getVolumeMounts().isEmpty()) { + adaptee.getDeploy().setVolumeMounts(new ArrayList<>()); + } else { + adaptee.getDeploy().getVolumeMounts().clear(); + } + // let's check just here, so there's a way to clear, i.e. by passing an empty or null list + if ((volumeMounts != null) && !volumeMounts.isEmpty()) { + volumeMounts.stream() + .map(v -> adaptee.getDeploy().getVolumeMounts().add( + new org.jboss.intersmash.model.helm.charts.values.wildfly.VolumeMount() + .withName(v.getName()) + .withMountPath(v.getMountPath()) + .withMountPropagation(v.getMountPropagation()) + .withReadOnly(v.getReadOnly()) + .withSubPath(v.getSubPath()))) + .collect(Collectors.toList()); + } + } + + public WildflyHelmChartRelease withVolumeMounts(List volumeMounts) { + this.setVolumeMounts(volumeMounts); + return this; + } + + @Override + public WildflyHelmChartRelease withVolumeMount(VolumeMount volumeMount) { + if (adaptee.getDeploy() == null) { + adaptee.setDeploy(new Deploy()); + } + if ((adaptee.getDeploy().getVolumeMounts() == null) || adaptee.getDeploy().getVolumeMounts().isEmpty()) { + adaptee.getDeploy().setVolumeMounts(new ArrayList<>()); + } + adaptee.getDeploy().getVolumeMounts().add( + new org.jboss.intersmash.model.helm.charts.values.wildfly.VolumeMount() + .withName(volumeMount.getName()) + .withMountPath(volumeMount.getMountPath()) + .withMountPropagation(volumeMount.getMountPropagation()) + .withReadOnly(volumeMount.getReadOnly()) + .withSubPath(volumeMount.getSubPath())); + return this; + } + + @Override + public String getRouteHost() { + return adaptee.getDeploy() == null ? "" + : adaptee.getDeploy().getRoute() == null ? "" : adaptee.getDeploy().getRoute().getHost(); + } + + @Override + public void setRouteHost(String routeHost) { + if (adaptee.getDeploy() == null) { + adaptee.setDeploy(new Deploy()); + } + if (adaptee.getDeploy().getRoute() == null) { + adaptee.getDeploy().setRoute(new Route()); + } + adaptee.getDeploy().getRoute().setHost(routeHost); + } + + public WildflyHelmChartRelease withRouteHost(String routeHost) { + this.setRouteHost(routeHost); + return this; + } + + @Override + public boolean isRouteTLSEnabled() { + return adaptee.getDeploy() == null ? Boolean.FALSE + : adaptee.getDeploy().getRoute() == null ? Boolean.FALSE + : adaptee.getDeploy().getRoute().getTls() == null ? Boolean.FALSE + : adaptee.getDeploy().getRoute().getTls().getEnabled(); + } + + @Override + public void setRouteTLSEnabled(boolean routeTLSEnabled) { + if (adaptee.getDeploy() == null) { + adaptee.setDeploy(new Deploy()); + } + if (adaptee.getDeploy().getRoute() == null) { + adaptee.getDeploy().setRoute(new Route()); + } + if (adaptee.getDeploy().getRoute().getTls() == null) { + adaptee.getDeploy().getRoute().setTls(new Tls()); + } + adaptee.getDeploy().getRoute().getTls().setEnabled(routeTLSEnabled); + } + + @Override + public WildflyHelmChartRelease withRouteTLSEnabled(boolean routeTLSEnabled) { + this.setRouteTLSEnabled(routeTLSEnabled); + return this; + } + + @Override + public boolean isTlsEnabled() { + return adaptee.getDeploy() == null ? Boolean.FALSE + : adaptee.getDeploy().getRoute() == null ? Boolean.FALSE + : adaptee.getDeploy().getTls() == null ? Boolean.FALSE : adaptee.getDeploy().getTls().getEnabled(); + } + + @Override + public void setTlsEnabled(boolean tlsEnabled) { + if (adaptee.getDeploy() == null) { + adaptee.setDeploy(new Deploy()); + } + if (adaptee.getDeploy().getTls() == null) { + adaptee.getDeploy().setTls(new Tls__1()); + } + adaptee.getDeploy().getTls().setEnabled(tlsEnabled); + } + + @Override + public WildflyHelmChartRelease withTlsEnabled(boolean tlsEnabled) { + this.setTlsEnabled(tlsEnabled); + return this; + } + + @Override + public LinkedHashSet getS2iFeaturePacks() { + LinkedHashSet result = new LinkedHashSet(); + if (adaptee.getBuild() != null && adaptee.getBuild().getS2i() != null + && !Strings.isNullOrEmpty(adaptee.getBuild().getS2i().getFeaturePacks())) { + Arrays.stream(adaptee.getBuild().getS2i().getFeaturePacks().split(",")) + .forEach(fp -> result.add(fp)); + } + return result; + } + + @Override + public void setS2iFeaturePacks(LinkedHashSet s2iFeaturePacks) { + if (adaptee.getBuild() == null) { + adaptee.setBuild(new Build()); + } + if (adaptee.getBuild().getS2i() == null) { + adaptee.getBuild().setS2i(new S2i()); + } + // let's check just here, so there's a way to clear, i.e. by passing an empty or null list + if ((s2iFeaturePacks != null) && !s2iFeaturePacks.isEmpty()) { + adaptee.getBuild().getS2i().setFeaturePacks(s2iFeaturePacks.stream().collect(Collectors.joining(","))); + } + } + + @Override + public WildflyHelmChartRelease withS2iFeaturePacks(LinkedHashSet s2iFeaturePacks) { + this.setS2iFeaturePacks(s2iFeaturePacks); + return this; + } + + @Override + public WildflyHelmChartRelease withS2iFeaturePacks(String s2iFeaturePacks) { + LinkedHashSet s2iFeaturePacksSet = new LinkedHashSet<>( + Arrays.stream(s2iFeaturePacks.split(",")).collect(Collectors.toList())); + this.setS2iFeaturePacks(s2iFeaturePacksSet); + return this; + } + + @Override + public WildflyHelmChartRelease withS2iFeaturePack(String s2iFeaturePack) { + if (adaptee.getBuild() == null) { + adaptee.setBuild(new Build()); + } + if (adaptee.getBuild().getS2i() == null) { + adaptee.getBuild().setS2i(new S2i()); + } + final List featurePacks = new ArrayList<>(); + if (!Strings.isNullOrEmpty(adaptee.getBuild().getS2i().getFeaturePacks())) { + featurePacks.addAll(Arrays.stream(adaptee.getBuild().getS2i().getFeaturePacks().split(",")) + .collect(Collectors.toList())); + } + featurePacks.add(s2iFeaturePack); + adaptee.getBuild().getS2i().setFeaturePacks(featurePacks.stream().collect(Collectors.joining(","))); + return this; + } + + @Override + public LinkedHashSet getS2iGalleonLayers() { + LinkedHashSet result = new LinkedHashSet(); + if (adaptee.getBuild() != null && adaptee.getBuild().getS2i() != null + && !Strings.isNullOrEmpty(adaptee.getBuild().getS2i().getGalleonLayers())) { + Arrays.stream(adaptee.getBuild().getS2i().getGalleonLayers().split(",")) + .forEach(fp -> result.add(fp)); + } + return result; + } + + @Override + public void setS2iGalleonLayers(LinkedHashSet s2iGalleonLayers) { + if (adaptee.getBuild() == null) { + adaptee.setBuild(new Build()); + } + if (adaptee.getBuild().getS2i() == null) { + adaptee.getBuild().setS2i(new S2i()); + } + // let's check just here, so there's a way to clear, i.e. by passing an empty or null list + if ((s2iGalleonLayers != null) && !s2iGalleonLayers.isEmpty()) { + adaptee.getBuild().getS2i().setGalleonLayers(s2iGalleonLayers.stream().collect(Collectors.joining(","))); + } + } + + @Override + public WildflyHelmChartRelease withS2iGalleonLayers(LinkedHashSet s2iGalleonLayers) { + this.setS2iGalleonLayers(s2iGalleonLayers); + return this; + } + + @Override + public WildflyHelmChartRelease withS2iGalleonLayers(String s2iGalleonLayers) { + LinkedHashSet s2iGalleonLayersSet = new LinkedHashSet<>( + Arrays.stream(s2iGalleonLayers.split(",")).collect(Collectors.toList())); + this.setS2iGalleonLayers(s2iGalleonLayersSet); + return this; + } + + @Override + public WildflyHelmChartRelease withS2iGalleonLayer(String s2iGalleonLayer) { + if (adaptee.getBuild() == null) { + adaptee.setBuild(new Build()); + } + if (adaptee.getBuild().getS2i() == null) { + adaptee.getBuild().setS2i(new S2i()); + } + final List galleonLayers = new ArrayList<>(); + if (!Strings.isNullOrEmpty(adaptee.getBuild().getS2i().getGalleonLayers())) { + galleonLayers.addAll(Arrays.stream(adaptee.getBuild().getS2i().getGalleonLayers().split(",")) + .collect(Collectors.toList())); + } + galleonLayers.add(s2iGalleonLayer); + adaptee.getBuild().getS2i().setGalleonLayers(galleonLayers.stream().collect(Collectors.joining(","))); + return this; + } + + @Override + public LinkedHashSet getS2iChannels() { + // no channels definition for WIldFly Helm Charts + return new LinkedHashSet<>(); + } + + @Override + public void setS2iChannels(LinkedHashSet s2iChannels) { + log.warn( + "Setting s2i build channels on a WildFly release has no effect since WildFly Helm Charts don't support channels"); + } + + @Override + public WildflyHelmChartRelease withS2iChannels(LinkedHashSet s2iChannels) { + this.setS2iChannels(s2iChannels); + return this; + } + + @Override + public WildflyHelmChartRelease withS2iChannel(String s2iChannel) { + log.warn( + "Setting s2i build channels on a WildFly release has no effect since WildFly Helm Charts don't support channels"); + return this; + } + + @Override + public BuildMode getBuildMode() { + return adaptee.getBuild() == null ? null + : adaptee.getBuild().getS2i() != null ? BuildMode.S2I + : adaptee.getBuild().getBootableJar() != null ? BuildMode.BOOTABLE_JAR : null; + } + + @Override + public String getBootableJarBuilderImage() { + return adaptee.getBuild() == null ? "" + : adaptee.getBuild().getBootableJar() == null ? "" : adaptee.getBuild().getBootableJar().getBuilderImage(); + } + + @Override + public void setBootableJarBuilderImage(String bootableJarBuilderImage) { + if (adaptee.getBuild() == null) { + adaptee.setBuild(new Build()); + } + if (adaptee.getBuild().getBootableJar() == null) { + adaptee.getBuild().setBootableJar(new BootableJar()); + } + adaptee.getBuild().getBootableJar().setBuilderImage(bootableJarBuilderImage); + } + + @Override + public WildflyHelmChartRelease withBootableJarBuilderImage(String bootableJarBuilderImage) { + this.setBootableJarBuilderImage(bootableJarBuilderImage); + return this; + } + + @Override + public String getSourceRepositoryUrl() { + return adaptee.getBuild() == null ? "" : adaptee.getBuild().getUri(); + } + + @Override + public void setSourceRepositoryUrl(String sourceRepositoryUrl) { + if (adaptee.getBuild() == null) { + adaptee.setBuild(new Build()); + } + adaptee.getBuild().setUri(sourceRepositoryUrl); + } + + @Override + public WildflyHelmChartRelease withSourceRepositoryUrl(String sourceRepositoryUrl) { + this.setSourceRepositoryUrl(sourceRepositoryUrl); + return this; + } + + @Override + public String getSourceRepositoryRef() { + return adaptee.getBuild() == null ? "" : adaptee.getBuild().getRef(); + } + + @Override + public void setSourceRepositoryRef(String sourceRepositoryRef) { + if (adaptee.getBuild() == null) { + adaptee.setBuild(new Build()); + } + adaptee.getBuild().setRef(sourceRepositoryRef); + } + + @Override + public WildflyHelmChartRelease withSourceRepositoryRef(String sourceRepositoryRef) { + this.setSourceRepositoryRef(sourceRepositoryRef); + return this; + } + + @Override + public String getContextDir() { + return adaptee.getBuild() == null ? "" : adaptee.getBuild().getContextDir(); + } + + @Override + public void setContextDir(String contextDir) { + if (adaptee.getBuild() == null) { + adaptee.setBuild(new Build()); + } + adaptee.getBuild().setContextDir(contextDir); + } + + @Override + public WildflyHelmChartRelease withContextDir(String contextDir) { + this.setContextDir(contextDir); + return this; + } + + @Override + public Integer getReplicas() { + return adaptee.getDeploy() == null ? 0 : adaptee.getDeploy().getReplicas(); + } + + @Override + public void setReplicas(Integer replicas) { + if (adaptee.getDeploy() == null) { + adaptee.setDeploy(new Deploy()); + } + adaptee.getDeploy().setReplicas(replicas); + } + + @Override + public WildflyHelmChartRelease withReplicas(Integer replicas) { + this.setReplicas(replicas); + return this; + } + + @Override + public boolean isBuildEnabled() { + return adaptee.getBuild() == null ? Boolean.FALSE : adaptee.getBuild().getEnabled(); + } + + @Override + public void setBuildEnabled(boolean buildEnabled) { + if (adaptee.getBuild() == null) { + adaptee.setBuild(new Build()); + } + adaptee.getBuild().setEnabled(buildEnabled); + } + + @Override + public WildflyHelmChartRelease withBuildEnabled(boolean buildEnabled) { + this.setBuildEnabled(buildEnabled); + return this; + } + + @Override + public boolean isDeployEnabled() { + return adaptee.getDeploy() == null ? Boolean.FALSE : adaptee.getDeploy().getEnabled(); + } + + @Override + public void setDeployEnabled(boolean deployEnabled) { + if (adaptee.getDeploy() == null) { + adaptee.setDeploy(new Deploy()); + } + adaptee.getDeploy().setEnabled(deployEnabled); + } + + @Override + public WildflyHelmChartRelease withDeployEnabled(boolean deployEnabled) { + this.setDeployEnabled(deployEnabled); + return this; + } + + @Override + public String getJdk17BuilderImage() { + // WilFly Helm Charts do not differentiate between JDKs + return adaptee.getBuild() == null ? "" : adaptee.getBuild().getS2i().getBuilderImage(); + } + + @Override + public void setJdk17BuilderImage(String jdk17BuilderImage) { + if (adaptee.getBuild() == null) { + adaptee.setBuild(new Build()); + } + if (adaptee.getBuild().getS2i() == null) { + adaptee.getBuild().setS2i(new S2i()); + } + // WilFly Helm Charts do not differentiate between JDKs + adaptee.getBuild().getS2i().setBuilderImage(jdk17BuilderImage); + } + + @Override + public WildflyHelmChartRelease withJdk17BuilderImage(String jdk17BuilderImage) { + this.setJdk17BuilderImage(jdk17BuilderImage); + return this; + } + + @Override + public String getJdk17RuntimeImage() { + // WilFly Helm Charts do not differentiate between JDKs + return adaptee.getBuild() == null ? "" : adaptee.getBuild().getS2i().getRuntimeImage(); + } + + @Override + public void setJdk17RuntimeImage(String jdk17RuntimeImage) { + if (adaptee.getBuild() == null) { + adaptee.setBuild(new Build()); + } + if (adaptee.getBuild().getS2i() == null) { + adaptee.getBuild().setS2i(new S2i()); + } + // WilFly Helm Charts do not differentiate between JDKs + adaptee.getBuild().getS2i().setRuntimeImage(jdk17RuntimeImage); + } + + @Override + public WildflyHelmChartRelease withJdk17RuntimeImage(String jdk17RuntimeImage) { + this.setJdk17RuntimeImage(jdk17RuntimeImage); + return this; + } + + private void initDefaultReplicas(HelmWildflyRelease release) { + if (release.getDeploy() == null) { + release = release.withDeploy(new Deploy()); + } + if (release.getDeploy().getReplicas() == null) { + release.getDeploy().setReplicas(1); + } + } +} diff --git a/tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/WildflyHelmChartOpenShiftProvisioner.java b/tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/wildfly/WildflyHelmChartOpenShiftProvisioner.java similarity index 95% rename from tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/WildflyHelmChartOpenShiftProvisioner.java rename to tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/wildfly/WildflyHelmChartOpenShiftProvisioner.java index 725896d4a..4f1b64e8f 100644 --- a/tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/WildflyHelmChartOpenShiftProvisioner.java +++ b/tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/wildfly/WildflyHelmChartOpenShiftProvisioner.java @@ -13,9 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jboss.intersmash.tools.provision.helm; +package org.jboss.intersmash.tools.provision.helm.wildfly; import org.jboss.intersmash.tools.application.openshift.helm.WildflyHelmChartOpenShiftApplication; +import org.jboss.intersmash.tools.provision.helm.HelmChartOpenShiftProvisioner; import org.jboss.intersmash.tools.provision.openshift.WaitersUtil; import org.jboss.intersmash.tools.util.openshift.WildflyOpenShiftUtils; import org.slf4j.event.Level; diff --git a/tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/WildflyHelmChartOpenShiftProvisionerFactory.java b/tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/wildfly/WildflyHelmChartOpenShiftProvisionerFactory.java similarity index 91% rename from tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/WildflyHelmChartOpenShiftProvisionerFactory.java rename to tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/wildfly/WildflyHelmChartOpenShiftProvisionerFactory.java index 70e2d55e6..82ca9a989 100644 --- a/tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/WildflyHelmChartOpenShiftProvisionerFactory.java +++ b/tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/wildfly/WildflyHelmChartOpenShiftProvisionerFactory.java @@ -13,11 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jboss.intersmash.tools.provision.helm; +package org.jboss.intersmash.tools.provision.helm.wildfly; import org.jboss.intersmash.tools.application.Application; import org.jboss.intersmash.tools.application.openshift.helm.WildflyHelmChartOpenShiftApplication; import org.jboss.intersmash.tools.provision.ProvisionerFactory; +import org.jboss.intersmash.tools.provision.helm.HelmChartOpenShiftProvisioner; import lombok.extern.slf4j.Slf4j; diff --git a/tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/wildfly/WildflyHelmChartRelease.java b/tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/wildfly/WildflyHelmChartRelease.java new file mode 100644 index 000000000..33cdefa4f --- /dev/null +++ b/tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/wildfly/WildflyHelmChartRelease.java @@ -0,0 +1,177 @@ +package org.jboss.intersmash.tools.provision.helm.wildfly; + +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; + +import org.jboss.intersmash.tools.application.openshift.helm.HelmChartRelease; +import org.jboss.intersmash.tools.provision.helm.Image; + +import io.fabric8.kubernetes.api.model.Volume; +import io.fabric8.kubernetes.api.model.VolumeMount; + +/** + * A contract that allows to create adapters that work seamlessly for both WildFly and EAP 8 Helm Charts releases. + * + * Can be used on the test side on order to accomplish dynamic configuration more easily. + */ +public interface WildflyHelmChartRelease extends HelmChartRelease { + + Map getDeploymentEnvironmentVariables(); + + void setDeploymentEnvironmentVariables(Map deploymentEnvironmentVariables); + + WildflyHelmChartRelease withDeploymentEnvironmentVariables(Map deploymentEnvironmentVariables); + + WildflyHelmChartRelease withDeploymentEnvironmentVariable(String key, String value); + + Map getBuildEnvironmentVariables(); + + void setBuildEnvironmentVariables(Map buildEnvironmentVariables); + + WildflyHelmChartRelease withBuildEnvironmentVariables(Map buildEnvironmentVariables); + + WildflyHelmChartRelease withBuildEnvironmentVariable(String key, String value); + + List getInjectedImages(); + + void setInjectedImages(List injectedImages); + + WildflyHelmChartRelease withInjectedImages(List injectedImages); + + WildflyHelmChartRelease withInjectedImage(Image injectedImage); + + List getVolumes(); + + void setVolumes(List volumes); + + WildflyHelmChartRelease withVolumes(List volumes); + + WildflyHelmChartRelease withVolume(Volume volume); + + List getVolumeMounts(); + + void setVolumeMounts(List volumeMounts); + + WildflyHelmChartRelease withVolumeMounts(List volumeMounts); + + WildflyHelmChartRelease withVolumeMount(VolumeMount volumeMount); + + String getRouteHost(); + + void setRouteHost(String routeHost); + + WildflyHelmChartRelease withRouteHost(String routeHost); + + boolean isRouteTLSEnabled(); + + void setRouteTLSEnabled(boolean routeTLSEnabled); + + WildflyHelmChartRelease withRouteTLSEnabled(boolean routeTLSEnabled); + + boolean isTlsEnabled(); + + void setTlsEnabled(boolean tlsEnabled); + + WildflyHelmChartRelease withTlsEnabled(boolean tlsEnabled); + + LinkedHashSet getS2iFeaturePacks(); + + void setS2iFeaturePacks(LinkedHashSet s2iFeaturePacks); + + WildflyHelmChartRelease withS2iFeaturePacks(LinkedHashSet s2iFeaturePacks); + + WildflyHelmChartRelease withS2iFeaturePacks(String s2iFeaturePacks); + + WildflyHelmChartRelease withS2iFeaturePack(String s2iFeaturePack); + + LinkedHashSet getS2iGalleonLayers(); + + void setS2iGalleonLayers(LinkedHashSet s2iGalleonLayers); + + WildflyHelmChartRelease withS2iGalleonLayers(LinkedHashSet s2iGalleonLayers); + + WildflyHelmChartRelease withS2iGalleonLayers(String s2iGalleonLayers); + + WildflyHelmChartRelease withS2iGalleonLayer(String s2iGalleonLayer); + + LinkedHashSet getS2iChannels(); + + void setS2iChannels(LinkedHashSet s2iFeaturePacks); + + WildflyHelmChartRelease withS2iChannels(LinkedHashSet s2iChannels); + + WildflyHelmChartRelease withS2iChannel(String s2iChannel); + + BuildMode getBuildMode(); + + String getBootableJarBuilderImage(); + + void setBootableJarBuilderImage(String bootableJarBuilderImage); + + WildflyHelmChartRelease withBootableJarBuilderImage(String bootableJarBuilderImage); + + String getSourceRepositoryUrl(); + + void setSourceRepositoryUrl(String sourceRepositoryUrl); + + WildflyHelmChartRelease withSourceRepositoryUrl(String sourceRepositoryUrl); + + String getSourceRepositoryRef(); + + void setSourceRepositoryRef(String sourceRepositoryRef); + + WildflyHelmChartRelease withSourceRepositoryRef(String sourceRepositoryRef); + + String getContextDir(); + + void setContextDir(String contextDir); + + WildflyHelmChartRelease withContextDir(String contextDir); + + Integer getReplicas(); + + void setReplicas(Integer replicas); + + WildflyHelmChartRelease withReplicas(Integer replicas); + + boolean isBuildEnabled(); + + void setBuildEnabled(boolean buildEnabled); + + WildflyHelmChartRelease withBuildEnabled(boolean buildEnabled); + + boolean isDeployEnabled(); + + void setDeployEnabled(boolean deployEnabled); + + WildflyHelmChartRelease withDeployEnabled(boolean deployEnabled); + + String getJdk17BuilderImage(); + + void setJdk17BuilderImage(String jdk17BuilderImage); + + WildflyHelmChartRelease withJdk17BuilderImage(String jdk17BuilderImage); + + String getJdk17RuntimeImage(); + + void setJdk17RuntimeImage(String jdk17RuntimeImage); + + WildflyHelmChartRelease withJdk17RuntimeImage(String jdk17RuntimeImage); + + enum BuildMode { + + S2I("s2i"), + BOOTABLE_JAR("bootable-jar"); + + private String value; + + BuildMode(String value) { + this.value = value; + } + + String getValue() { + return value; + } + } +} diff --git a/tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/wildfly/eap8/Eap8HelmChartReleaseAdapter.java b/tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/wildfly/eap8/Eap8HelmChartReleaseAdapter.java new file mode 100644 index 000000000..36fc25fe8 --- /dev/null +++ b/tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/wildfly/eap8/Eap8HelmChartReleaseAdapter.java @@ -0,0 +1,725 @@ +package org.jboss.intersmash.tools.provision.helm.wildfly.eap8; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.jboss.intersmash.model.helm.charts.values.eap8.Build; +import org.jboss.intersmash.model.helm.charts.values.eap8.Deploy; +import org.jboss.intersmash.model.helm.charts.values.eap8.Env; +import org.jboss.intersmash.model.helm.charts.values.eap8.Env__1; +import org.jboss.intersmash.model.helm.charts.values.eap8.HelmEap8Release; +import org.jboss.intersmash.model.helm.charts.values.eap8.Jdk17; +import org.jboss.intersmash.model.helm.charts.values.eap8.Route; +import org.jboss.intersmash.model.helm.charts.values.eap8.S2i; +import org.jboss.intersmash.model.helm.charts.values.eap8.Tls; +import org.jboss.intersmash.model.helm.charts.values.eap8.Tls__1; +import org.jboss.intersmash.tools.application.openshift.helm.HelmChartRelease; +import org.jboss.intersmash.tools.provision.helm.HelmChartReleaseAdapter; +import org.jboss.intersmash.tools.provision.helm.Image; +import org.jboss.intersmash.tools.provision.helm.wildfly.WildflyHelmChartRelease; + +import com.google.common.base.Strings; + +import io.fabric8.kubernetes.api.model.Volume; +import io.fabric8.kubernetes.api.model.VolumeMount; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; + +/** + * An adapter that implements a valid EAP 8 {@link HelmChartRelease} by exposing an internal instance of + * {@link HelmEap8Release} to store an EAP 8 Helm Charts release data and to represent a values file which can be serialized + * as an output for {@link HelmChartRelease#toValuesFile()} + * + * This adapter is compliant with the contract which is required by the + * {@link org.jboss.intersmash.tools.provision.helm.HelmChartOpenShiftProvisioner} logic, i.e. to + * implement {@link HelmChartRelease}, and allows for us to leverage a generated + * {@link Eap8HelmChartReleaseAdapter#adaptee}, i.e. in terms of UX, provide native release YAML definitions. + */ +@Slf4j +public class Eap8HelmChartReleaseAdapter extends HelmChartReleaseAdapter + implements HelmChartRelease, WildflyHelmChartRelease { + + public Eap8HelmChartReleaseAdapter(@NonNull HelmEap8Release release) { + super(release, new ArrayList<>()); + initDefaultReplicas(release); + } + + public Eap8HelmChartReleaseAdapter(@NonNull HelmEap8Release release, List additionalValuesFiles) { + super(release, additionalValuesFiles); + initDefaultReplicas(release); + } + + @Override + public Map getDeploymentEnvironmentVariables() { + return adaptee.getDeploy() == null ? Map.of() + : adaptee.getDeploy().getEnv() == null || adaptee.getDeploy().getEnv().isEmpty() ? Map.of() + : adaptee.getDeploy().getEnv().stream() + .collect(Collectors.toMap(e -> e.getName(), e -> e.getValue())); + } + + @Override + public void setDeploymentEnvironmentVariables(Map deploymentEnvironmentVariables) { + if (adaptee.getDeploy() == null) { + adaptee.setDeploy(new Deploy()); + } + if ((adaptee.getDeploy().getEnv() == null) || adaptee.getDeploy().getEnv().isEmpty()) { + adaptee.getDeploy().setEnv(new ArrayList<>()); + } else { + adaptee.getDeploy().getEnv().clear(); + } + // let's check just here, so there's a way to clear, i.e. by passing an empty or null list + if ((deploymentEnvironmentVariables != null) && !deploymentEnvironmentVariables.isEmpty()) { + deploymentEnvironmentVariables.entrySet().stream() + .forEach(e -> adaptee.getDeploy().getEnv().add(new Env__1().withName(e.getKey()).withValue(e.getValue()))); + } + } + + public WildflyHelmChartRelease withDeploymentEnvironmentVariables( + Map deploymentEnvironmentVariables) { + this.setDeploymentEnvironmentVariables(deploymentEnvironmentVariables); + return this; + } + + @Override + public WildflyHelmChartRelease withDeploymentEnvironmentVariable(String key, String value) { + if (adaptee.getDeploy() == null) { + adaptee.setDeploy(new Deploy()); + } + if ((adaptee.getDeploy().getEnv() == null) || adaptee.getDeploy().getEnv().isEmpty()) { + adaptee.getDeploy().setEnv(new ArrayList<>()); + } + adaptee.getDeploy().getEnv().add(new Env__1().withName(key).withValue(value)); + return this; + } + + @Override + public Map getBuildEnvironmentVariables() { + return adaptee.getBuild() == null ? Map.of() + : adaptee.getBuild().getEnv() == null || adaptee.getBuild().getEnv().isEmpty() ? Map.of() + : adaptee.getBuild().getEnv().stream() + .collect(Collectors.toMap(e -> e.getName(), e -> e.getValue())); + } + + @Override + public void setBuildEnvironmentVariables(Map buildEnvironmentVariables) { + if (adaptee.getBuild() == null) { + adaptee.setBuild(new Build()); + } + if ((adaptee.getBuild().getEnv() == null) || adaptee.getBuild().getEnv().isEmpty()) { + adaptee.getBuild().setEnv(new ArrayList<>()); + } else { + adaptee.getBuild().getEnv().clear(); + } + // let's check just here, so there's a way to clear, i.e. by passing an empty or null list + if ((buildEnvironmentVariables != null) && !buildEnvironmentVariables.isEmpty()) { + buildEnvironmentVariables.entrySet().stream() + .forEach(e -> adaptee.getBuild().getEnv().add(new Env().withName(e.getKey()).withValue(e.getValue()))); + } + } + + public WildflyHelmChartRelease withBuildEnvironmentVariables(Map buildEnvironmentVariables) { + this.setBuildEnvironmentVariables(buildEnvironmentVariables); + return this; + } + + @Override + public WildflyHelmChartRelease withBuildEnvironmentVariable(String key, String value) { + if (adaptee.getBuild() == null) { + adaptee.setBuild(new Build()); + } + if ((adaptee.getBuild().getEnv() == null) || adaptee.getBuild().getEnv().isEmpty()) { + adaptee.getBuild().setEnv(new ArrayList<>()); + } + adaptee.getBuild().getEnv().add(new Env().withName(key).withValue(value)); + return this; + } + + @Override + public List getInjectedImages() { + return adaptee.getBuild() == null ? List.of() + : adaptee.getBuild().getImages() == null ? List.of() + : (List) adaptee.getBuild().getImages(); + } + + @Override + public void setInjectedImages(List injectedImages) { + if (adaptee.getBuild() == null) { + adaptee.setBuild(new Build()); + } + if ((adaptee.getBuild().getImages() == null)) { + adaptee.getBuild().setImages(new ArrayList<>()); + } else { + ((List) adaptee.getBuild().getImages()).clear(); + } + // let's check just here, so there's a way to clear, i.e. by passing an empty or null list + if ((injectedImages != null) && !injectedImages.isEmpty()) { + ((List) adaptee.getBuild().getImages()).addAll(injectedImages); + } + } + + @Override + public WildflyHelmChartRelease withInjectedImages(List injectedImages) { + this.setInjectedImages(injectedImages); + return this; + } + + @Override + public WildflyHelmChartRelease withInjectedImage(Image injectedImage) { + if (adaptee.getBuild() == null) { + adaptee.setBuild(new Build()); + } + if (adaptee.getBuild().getImages() == null) { + adaptee.getBuild().setImages(new ArrayList<>()); + } + ((List) adaptee.getBuild().getImages()).add(injectedImage); + return this; + } + + @Override + public List getVolumes() { + return adaptee.getDeploy() == null ? List.of() + : adaptee.getDeploy().getVolumes() == null ? List.of() + : adaptee.getDeploy().getVolumes().stream() + .map(v -> (Volume) v) + .collect(Collectors.toList()); + } + + @Override + public void setVolumes(List volumes) { + if (adaptee.getDeploy() == null) { + adaptee.setDeploy(new Deploy()); + } + if ((adaptee.getDeploy().getVolumes() == null) || adaptee.getDeploy().getVolumes().isEmpty()) { + adaptee.getDeploy().setVolumes(new ArrayList<>()); + } else { + adaptee.getDeploy().getVolumes().clear(); + } + // let's check just here, so there's a way to clear, i.e. by passing an empty or null list + if ((volumes != null) && !volumes.isEmpty()) { + volumes.stream().forEach(v -> adaptee.getDeploy().getVolumes().add(v)); + } + } + + public WildflyHelmChartRelease withVolumes(List volumes) { + this.setVolumes(volumes); + return this; + } + + @Override + public WildflyHelmChartRelease withVolume(Volume volume) { + if (adaptee.getDeploy() == null) { + adaptee.setDeploy(new Deploy()); + } + if ((adaptee.getDeploy().getVolumes() == null) || adaptee.getDeploy().getVolumes().isEmpty()) { + adaptee.getDeploy().setVolumes(new ArrayList<>()); + } + adaptee.getDeploy().getVolumes().add(volume); + return this; + } + + @Override + public List getVolumeMounts() { + return adaptee.getDeploy() == null ? List.of() + : adaptee.getDeploy().getVolumeMounts() == null ? List.of() + : adaptee.getDeploy().getVolumeMounts().stream() + .map(v -> new VolumeMount( + v.getMountPath(), + v.getMountPropagation(), + v.getName(), + v.getReadOnly(), + v.getSubPath(), null)) + .collect(Collectors.toList()); + } + + @Override + public void setVolumeMounts(List volumeMounts) { + if (adaptee.getDeploy() == null) { + adaptee.setDeploy(new Deploy()); + } + if ((adaptee.getDeploy().getVolumeMounts() == null) || adaptee.getDeploy().getVolumeMounts().isEmpty()) { + adaptee.getDeploy().setVolumeMounts(new ArrayList<>()); + } else { + adaptee.getDeploy().getVolumeMounts().clear(); + } + // let's check just here, so there's a way to clear, i.e. by passing an empty or null list + if ((volumeMounts != null) && !volumeMounts.isEmpty()) { + volumeMounts.stream() + .forEach(v -> adaptee.getDeploy().getVolumeMounts().add( + new org.jboss.intersmash.model.helm.charts.values.eap8.VolumeMount() + .withName(v.getName()) + .withMountPath(v.getMountPath()) + .withMountPropagation(v.getMountPropagation()) + .withReadOnly(v.getReadOnly()) + .withSubPath(v.getSubPath()))); + } + } + + @Override + public WildflyHelmChartRelease withVolumeMounts(List volumeMounts) { + this.setVolumeMounts(volumeMounts); + return this; + } + + @Override + public WildflyHelmChartRelease withVolumeMount(VolumeMount volumeMount) { + if (adaptee.getDeploy() == null) { + adaptee.setDeploy(new Deploy()); + } + if ((adaptee.getDeploy().getVolumeMounts() == null) || adaptee.getDeploy().getVolumeMounts().isEmpty()) { + adaptee.getDeploy().setVolumeMounts(new ArrayList<>()); + } + adaptee.getDeploy().getVolumeMounts().add( + new org.jboss.intersmash.model.helm.charts.values.eap8.VolumeMount() + .withName(volumeMount.getName()) + .withMountPath(volumeMount.getMountPath()) + .withMountPropagation(volumeMount.getMountPropagation()) + .withReadOnly(volumeMount.getReadOnly()) + .withSubPath(volumeMount.getSubPath())); + return this; + } + + @Override + public String getRouteHost() { + return adaptee.getDeploy() == null ? "" + : adaptee.getDeploy().getRoute() == null ? "" : adaptee.getDeploy().getRoute().getHost(); + } + + @Override + public void setRouteHost(String routeHost) { + if (adaptee.getDeploy() == null) { + adaptee.setDeploy(new Deploy()); + } + if (adaptee.getDeploy().getRoute() == null) { + adaptee.getDeploy().setRoute(new Route()); + } + adaptee.getDeploy().getRoute().setHost(routeHost); + } + + public WildflyHelmChartRelease withRouteHost(String routeHost) { + this.setRouteHost(routeHost); + return this; + } + + @Override + public boolean isRouteTLSEnabled() { + return adaptee.getDeploy() == null ? Boolean.FALSE + : adaptee.getDeploy().getRoute() == null ? Boolean.FALSE + : adaptee.getDeploy().getRoute().getTls() == null ? Boolean.FALSE + : adaptee.getDeploy().getRoute().getTls().getEnabled(); + } + + @Override + public void setRouteTLSEnabled(boolean routeTLSEnabled) { + if (adaptee.getDeploy() == null) { + adaptee.setDeploy(new Deploy()); + } + if (adaptee.getDeploy().getRoute() == null) { + adaptee.getDeploy().setRoute(new Route()); + } + if (adaptee.getDeploy().getRoute().getTls() == null) { + adaptee.getDeploy().getRoute().setTls(new Tls()); + } + adaptee.getDeploy().getRoute().getTls().setEnabled(routeTLSEnabled); + } + + @Override + public WildflyHelmChartRelease withRouteTLSEnabled(boolean routeTLSEnabled) { + this.setRouteTLSEnabled(routeTLSEnabled); + return this; + } + + @Override + public boolean isTlsEnabled() { + return adaptee.getDeploy() == null ? Boolean.FALSE + : adaptee.getDeploy().getRoute() == null ? Boolean.FALSE + : adaptee.getDeploy().getTls() == null ? Boolean.FALSE : adaptee.getDeploy().getTls().getEnabled(); + } + + @Override + public void setTlsEnabled(boolean tlsEnabled) { + if (adaptee.getDeploy() == null) { + adaptee.setDeploy(new Deploy()); + } + if (adaptee.getDeploy().getTls() == null) { + adaptee.getDeploy().setTls(new Tls__1()); + } + adaptee.getDeploy().getTls().setEnabled(tlsEnabled); + } + + @Override + public WildflyHelmChartRelease withTlsEnabled(boolean tlsEnabled) { + this.setTlsEnabled(tlsEnabled); + return this; + } + + @Override + public LinkedHashSet getS2iFeaturePacks() { + LinkedHashSet result = new LinkedHashSet(); + if (adaptee.getBuild() != null && adaptee.getBuild().getS2i() != null + && !Strings.isNullOrEmpty(adaptee.getBuild().getS2i().getFeaturePacks())) { + Arrays.stream(adaptee.getBuild().getS2i().getFeaturePacks().split(",")) + .forEach(fp -> result.add(fp)); + } + return result; + } + + @Override + public void setS2iFeaturePacks(LinkedHashSet s2iFeaturePacks) { + if (adaptee.getBuild() == null) { + adaptee.setBuild(new Build()); + } + if (adaptee.getBuild().getS2i() == null) { + adaptee.getBuild().setS2i(new S2i()); + } + // let's check just here, so there's a way to clear, i.e. by passing an empty or null list + if ((s2iFeaturePacks != null) && !s2iFeaturePacks.isEmpty()) { + adaptee.getBuild().getS2i().setFeaturePacks(s2iFeaturePacks.stream().collect(Collectors.joining(","))); + } + } + + @Override + public WildflyHelmChartRelease withS2iFeaturePacks(LinkedHashSet s2iFeaturePacks) { + this.setS2iFeaturePacks(s2iFeaturePacks); + return this; + } + + @Override + public WildflyHelmChartRelease withS2iFeaturePacks(String s2iFeaturePacks) { + LinkedHashSet s2iFeaturePacksSet = new LinkedHashSet<>( + Arrays.stream(s2iFeaturePacks.split(",")).collect(Collectors.toList())); + this.setS2iFeaturePacks(s2iFeaturePacksSet); + return this; + } + + @Override + public WildflyHelmChartRelease withS2iFeaturePack(String s2iFeaturePack) { + if (adaptee.getBuild() == null) { + adaptee.setBuild(new Build()); + } + if (adaptee.getBuild().getS2i() == null) { + adaptee.getBuild().setS2i(new S2i()); + } + final List featurePacks = new ArrayList<>(); + if (!Strings.isNullOrEmpty(adaptee.getBuild().getS2i().getFeaturePacks())) { + featurePacks.addAll(Arrays.stream(adaptee.getBuild().getS2i().getFeaturePacks().split(",")) + .collect(Collectors.toList())); + } + featurePacks.add(s2iFeaturePack); + adaptee.getBuild().getS2i().setFeaturePacks(featurePacks.stream().collect(Collectors.joining(","))); + return this; + } + + @Override + public LinkedHashSet getS2iGalleonLayers() { + LinkedHashSet result = new LinkedHashSet(); + if (adaptee.getBuild() != null && adaptee.getBuild().getS2i() != null + && !Strings.isNullOrEmpty(adaptee.getBuild().getS2i().getGalleonLayers())) { + Arrays.stream(adaptee.getBuild().getS2i().getGalleonLayers().split(",")) + .forEach(gl -> result.add(gl)); + } + return result; + } + + @Override + public void setS2iGalleonLayers(LinkedHashSet s2iGalleonLayers) { + if (adaptee.getBuild() == null) { + adaptee.setBuild(new Build()); + } + if (adaptee.getBuild().getS2i() == null) { + adaptee.getBuild().setS2i(new S2i()); + } + // let's check just here, so there's a way to clear, i.e. by passing an empty or null list + if ((s2iGalleonLayers != null) && !s2iGalleonLayers.isEmpty()) { + adaptee.getBuild().getS2i().setGalleonLayers(s2iGalleonLayers.stream().collect(Collectors.joining(","))); + } + } + + @Override + public WildflyHelmChartRelease withS2iGalleonLayers(LinkedHashSet s2iGalleonLayers) { + this.setS2iGalleonLayers(s2iGalleonLayers); + return this; + } + + @Override + public WildflyHelmChartRelease withS2iGalleonLayers(String s2iGalleonLayers) { + LinkedHashSet s2iGalleonLayersSet = new LinkedHashSet<>( + Arrays.stream(s2iGalleonLayers.split(",")).collect(Collectors.toList())); + this.setS2iGalleonLayers(s2iGalleonLayersSet); + return this; + } + + @Override + public WildflyHelmChartRelease withS2iGalleonLayer(String s2iGalleonLayer) { + if (adaptee.getBuild() == null) { + adaptee.setBuild(new Build()); + } + if (adaptee.getBuild().getS2i() == null) { + adaptee.getBuild().setS2i(new S2i()); + } + final List galleonLayers = new ArrayList<>(); + if (!Strings.isNullOrEmpty(adaptee.getBuild().getS2i().getGalleonLayers())) { + galleonLayers.addAll(Arrays.stream(adaptee.getBuild().getS2i().getGalleonLayers().split(",")) + .collect(Collectors.toList())); + } + galleonLayers.add(s2iGalleonLayer); + adaptee.getBuild().getS2i().setGalleonLayers(galleonLayers.stream().collect(Collectors.joining(","))); + return this; + } + + @Override + public LinkedHashSet getS2iChannels() { + LinkedHashSet result = new LinkedHashSet(); + if (adaptee.getBuild() != null && adaptee.getBuild().getS2i() != null + && !Strings.isNullOrEmpty(adaptee.getBuild().getS2i().getChannels())) { + Arrays.stream(adaptee.getBuild().getS2i().getChannels().split(",")) + .forEach(ch -> result.add(ch)); + } + return result; + } + + @Override + public void setS2iChannels(LinkedHashSet s2iChannels) { + if (adaptee.getBuild() == null) { + adaptee.setBuild(new Build()); + } + if (adaptee.getBuild().getS2i() == null) { + adaptee.getBuild().setS2i(new S2i()); + } + // let's check just here, so there's a way to clear, i.e. by passing an empty or null list + if ((s2iChannels != null) && !s2iChannels.isEmpty()) { + adaptee.getBuild().getS2i().setChannels(s2iChannels.stream().collect(Collectors.joining(","))); + } + } + + @Override + public WildflyHelmChartRelease withS2iChannels(LinkedHashSet s2iChannels) { + this.setS2iChannels(s2iChannels); + return this; + } + + @Override + public WildflyHelmChartRelease withS2iChannel(String s2iChannel) { + if (adaptee.getBuild() == null) { + adaptee.setBuild(new Build()); + } + if (adaptee.getBuild().getS2i() == null) { + adaptee.getBuild().setS2i(new S2i()); + } + final List channels = new ArrayList<>(); + if (!Strings.isNullOrEmpty(adaptee.getBuild().getS2i().getChannels())) { + channels.addAll(Arrays.stream(adaptee.getBuild().getS2i().getChannels().split(",")) + .collect(Collectors.toList())); + } + channels.add(s2iChannel); + adaptee.getBuild().getS2i().setChannels(channels.stream().collect(Collectors.joining(","))); + return this; + } + + @Override + public BuildMode getBuildMode() { + // EAP 8 value files has no bootable JAR definition, since Bootable JAR is only supported on EAP XP + return BuildMode.S2I; + } + + @Override + public String getBootableJarBuilderImage() { + // no Bootable JAR image is supported by EAP 8 Helm Charts + return ""; + } + + @Override + public void setBootableJarBuilderImage(String bootableJarBuilderImage) { + log.warn( + "Setting a Bootable JAR image on an EAP 8 release has no effect since EAP 8 does not support the Bootable JAR build type"); + } + + @Override + public WildflyHelmChartRelease withBootableJarBuilderImage(String bootableJarBuilderImage) { + this.setBootableJarBuilderImage(bootableJarBuilderImage); + return this; + } + + @Override + public String getSourceRepositoryUrl() { + return adaptee.getBuild() == null ? "" : adaptee.getBuild().getUri(); + } + + @Override + public void setSourceRepositoryUrl(String sourceRepositoryUrl) { + if (adaptee.getBuild() == null) { + adaptee.setBuild(new Build()); + } + adaptee.getBuild().setUri(sourceRepositoryUrl); + } + + @Override + public WildflyHelmChartRelease withSourceRepositoryUrl(String sourceRepositoryUrl) { + this.setSourceRepositoryUrl(sourceRepositoryUrl); + return this; + } + + @Override + public String getSourceRepositoryRef() { + return adaptee.getBuild() == null ? "" : adaptee.getBuild().getRef(); + } + + @Override + public void setSourceRepositoryRef(String sourceRepositoryRef) { + if (adaptee.getBuild() == null) { + adaptee.setBuild(new Build()); + } + adaptee.getBuild().setRef(sourceRepositoryRef); + } + + @Override + public WildflyHelmChartRelease withSourceRepositoryRef(String sourceRepositoryRef) { + this.setSourceRepositoryRef(sourceRepositoryRef); + return this; + } + + @Override + public String getContextDir() { + return adaptee.getBuild() == null ? "" : adaptee.getBuild().getContextDir(); + } + + @Override + public void setContextDir(String contextDir) { + if (adaptee.getBuild() == null) { + adaptee.setBuild(new Build()); + } + adaptee.getBuild().setContextDir(contextDir); + } + + @Override + public WildflyHelmChartRelease withContextDir(String contextDir) { + this.setContextDir(contextDir); + return this; + } + + @Override + public Integer getReplicas() { + return adaptee.getDeploy() == null ? 0 : adaptee.getDeploy().getReplicas(); + } + + @Override + public void setReplicas(Integer replicas) { + if (adaptee.getDeploy() == null) { + adaptee.setDeploy(new Deploy()); + } + adaptee.getDeploy().setReplicas(replicas); + } + + @Override + public WildflyHelmChartRelease withReplicas(Integer replicas) { + this.setReplicas(replicas); + return this; + } + + @Override + public boolean isBuildEnabled() { + return adaptee.getBuild() == null ? Boolean.FALSE : adaptee.getBuild().getEnabled(); + } + + @Override + public void setBuildEnabled(boolean buildEnabled) { + if (adaptee.getBuild() == null) { + adaptee.setBuild(new Build()); + } + adaptee.getBuild().setEnabled(buildEnabled); + } + + @Override + public WildflyHelmChartRelease withBuildEnabled(boolean buildEnabled) { + this.setBuildEnabled(buildEnabled); + return this; + } + + @Override + public boolean isDeployEnabled() { + return adaptee.getDeploy() == null ? Boolean.FALSE : adaptee.getDeploy().getEnabled(); + } + + @Override + public void setDeployEnabled(boolean deployEnabled) { + if (adaptee.getDeploy() == null) { + adaptee.setDeploy(new Deploy()); + } + adaptee.getDeploy().setEnabled(deployEnabled); + } + + @Override + public WildflyHelmChartRelease withDeployEnabled(boolean deployEnabled) { + this.setDeployEnabled(deployEnabled); + return this; + } + + @Override + public String getJdk17BuilderImage() { + return adaptee.getBuild() == null ? "" + : adaptee.getBuild().getS2i().getJdk17() == null ? "" + : adaptee.getBuild().getS2i().getJdk17().getBuilderImage(); + } + + @Override + public void setJdk17BuilderImage(String jdk17BuilderImage) { + if (adaptee.getBuild() == null) { + adaptee.setBuild(new Build()); + } + if (adaptee.getBuild().getS2i() == null) { + adaptee.getBuild().setS2i(new S2i()); + } + if (adaptee.getBuild().getS2i().getJdk17() == null) { + adaptee.getBuild().getS2i().setJdk17(new Jdk17()); + } + adaptee.getBuild().getS2i().getJdk17().setBuilderImage(jdk17BuilderImage); + adaptee.getBuild().getS2i().setJdk(S2i.Jdk._17); + } + + @Override + public WildflyHelmChartRelease withJdk17BuilderImage(String jdk17BuilderImage) { + this.setJdk17BuilderImage(jdk17BuilderImage); + return this; + } + + @Override + public String getJdk17RuntimeImage() { + return adaptee.getBuild() == null ? "" + : adaptee.getBuild().getS2i().getJdk17() == null ? "" + : adaptee.getBuild().getS2i().getJdk17().getRuntimeImage(); + } + + @Override + public void setJdk17RuntimeImage(String jdk17RuntimeImage) { + if (adaptee.getBuild() == null) { + adaptee.setBuild(new Build()); + } + if (adaptee.getBuild().getS2i() == null) { + adaptee.getBuild().setS2i(new S2i()); + } + if (adaptee.getBuild().getS2i().getJdk17() == null) { + adaptee.getBuild().getS2i().setJdk17(new Jdk17()); + } + adaptee.getBuild().getS2i().getJdk17().setRuntimeImage(jdk17RuntimeImage); + } + + @Override + public WildflyHelmChartRelease withJdk17RuntimeImage(String jdk17RuntimeImage) { + this.setJdk17RuntimeImage(jdk17RuntimeImage); + return this; + } + + private HelmEap8Release initDefaultReplicas(HelmEap8Release release) { + if (release.getDeploy() == null) { + release = release.withDeploy(new Deploy()); + } + if (release.getDeploy().getReplicas() == null) { + release.getDeploy().setReplicas(1); + } + return release; + } +} diff --git a/tools/intersmash-tools-provisioners/src/main/resources/META-INF/services/org.jboss.intersmash.tools.provision.ProvisionerFactory b/tools/intersmash-tools-provisioners/src/main/resources/META-INF/services/org.jboss.intersmash.tools.provision.ProvisionerFactory index ada5200a8..836e8d3b9 100644 --- a/tools/intersmash-tools-provisioners/src/main/resources/META-INF/services/org.jboss.intersmash.tools.provision.ProvisionerFactory +++ b/tools/intersmash-tools-provisioners/src/main/resources/META-INF/services/org.jboss.intersmash.tools.provision.ProvisionerFactory @@ -3,11 +3,12 @@ org.jboss.intersmash.tools.provision.openshift.KafkaOperatorProvisionerFactory org.jboss.intersmash.tools.provision.openshift.WildflyBootableJarImageOpenShiftProvisionerFactory org.jboss.intersmash.tools.provision.openshift.WildflyImageOpenShiftProvisionerFactory org.jboss.intersmash.tools.provision.openshift.WildflyOperatorProvisionerFactory -org.jboss.intersmash.tools.provision.helm.WildflyHelmChartOpenShiftProvisionerFactory org.jboss.intersmash.tools.provision.openshift.MysqlImageOpenShiftProvisionerFactory org.jboss.intersmash.tools.provision.openshift.PostgreSQLImageOpenShiftProvisionerFactory org.jboss.intersmash.tools.provision.openshift.InfinispanOperatorProvisionerFactory org.jboss.intersmash.tools.provision.openshift.RhSsoOperatorProvisionerFactory +org.jboss.intersmash.tools.provision.helm.wildfly.WildflyHelmChartOpenShiftProvisionerFactory +org.jboss.intersmash.tools.provision.openshift.Eap7ImageOpenShiftProvisionerFactory org.jboss.intersmash.tools.provision.openshift.RhSsoTemplateOpenShiftProvisionerFactory org.jboss.intersmash.tools.provision.openshift.PostgreSQLTemplateOpenShiftProvisionerFactory org.jboss.intersmash.tools.provision.openshift.Eap7ImageOpenShiftProvisionerFactory diff --git a/tools/intersmash-tools-provisioners/src/main/resources/org/jboss/intersmash/tools/provision/helm/values/schema/eap8/helm-eap8-release.json b/tools/intersmash-tools-provisioners/src/main/resources/org/jboss/intersmash/tools/provision/helm/values/schema/eap8/helm-eap8-release.json new file mode 100644 index 000000000..36358e61c --- /dev/null +++ b/tools/intersmash-tools-provisioners/src/main/resources/org/jboss/intersmash/tools/provision/helm/values/schema/eap8/helm-eap8-release.json @@ -0,0 +1,633 @@ +{ + "$schema": "http://json-schema.org/schema#", + "type": "object", + "properties": { + "image": { + "type": ["object", "null"], + "properties": { + "name": { + "description": "Name of the application image. If not specified, the name of the Helm release will be used.", + "type": ["string", "null"] + }, + "tag": { + "description": "Tag of the application image", + "type": ["string", "null"], + "default": "latest" + } + } + }, + "build": { + "description": "Configuration to build the application image", + "type": "object", + "properties": { + "enabled": { + "description": "Enable/Disable building the application image", + "type": "boolean", + "default": true + }, + "mode": { + "description": "Which mode to use to build the application", + "type": "string", + "enum": ["s2i"], + "default": "s2i" + }, + "uri": { + "description": "URI of GitHub repository", + "type": "string" + }, + "ref": { + "description": "Git reference", + "type": ["string", "null"] + }, + "contextDir": { + "description": "Context directory within your Git repo to use as the root for the build", + "type": ["string", "null"] + }, + "sourceSecret": { + "description": "Name of the Secret to use when cloning Git source project", + "type": ["string", "null"] + }, + "pullSecret": { + "description": "Name of the Pull Secret", + "type": ["string", "null"] + }, + "output": { + "description": "Configuration for the built application image", + "type": "object", + "properties": { + "kind": { + "description": "Determines where the application images will be pushed", + "type": "string", + "enum": ["ImageStreamTag", "DockerImage"], + "default": "ImageStreamTag" + }, + "pushSecret": { + "description": "Name of the Push Secret", + "type": ["string", "null"] + } + } + }, + "env": { + "description": "List of environment variables to set in the container. Cannot be updated.", + "items": { + "description": "EnvVar represents an environment variable present in a Container.", + "properties": { + "name": { + "description": "Name of the environment variable. Must be a C_IDENTIFIER.", + "type": "string" + }, + "value": { + "description": "Variable references $(VAR_NAME) are expanded using the previous defined environment variables in the container and any service environment variables. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Defaults to \"\".", + "type": [ + "string", + "null" + ] + }, + "valueFrom": { + "description": "EnvVarSource represents a source for the value of an EnvVar.", + "properties": { + "configMapKeyRef": { + "description": "Selects a key from a ConfigMap.", + "properties": { + "key": { + "description": "The key to select.", + "type": "string" + }, + "name": { + "description": "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": [ + "string", + "null" + ] + }, + "optional": { + "description": "Specify whether the ConfigMap or its key must be defined", + "type": "boolean" + } + }, + "required": [ + "key" + ], + "type": "object" + }, + "fieldRef": { + "description": "ObjectFieldSelector selects an APIVersioned field of an object.", + "properties": { + "apiVersion": { + "description": "Version of the schema the FieldPath is written in terms of, defaults to \"v1\".", + "type": [ + "string", + "null" + ] + }, + "fieldPath": { + "description": "Path of the field to select in the specified API version.", + "type": "string" + } + }, + "required": [ + "fieldPath" + ], + "type": "object" + }, + "resourceFieldRef": { + "description": "ResourceFieldSelector represents container resources (cpu, memory) and their output format", + "properties": { + "containerName": { + "description": "Container name: required for volumes, optional for env vars", + "type": [ + "string", + "null" + ] + }, + "divisor": { + "oneOf": [ + { + "type": [ + "string", + "null" + ] + }, + { + "type": "integer" + } + ] + }, + "resource": { + "description": "Required: resource to select", + "type": "string" + } + }, + "required": [ + "resource" + ], + "type": "object" + }, + "secretKeyRef": { + "description": "SecretKeySelector selects a key of a Secret.", + "properties": { + "key": { + "description": "The key of the secret to select from. Must be a valid secret key.", + "type": "string" + }, + "name": { + "description": "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": [ + "string", + "null" + ] + }, + "optional": { + "description": "Specify whether the Secret or its key must be defined", + "type": "boolean" + } + }, + "required": [ + "key" + ], + "type": "object" + } + }, + "type": "object" + } + }, + "required": [ + "name" + ], + "type": "object" + }, + "type": [ + "array", + "null" + ] + }, + "resources": { + "description": "Freeform resources field. More information: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/" + }, + "images": { + "description": "Freeform images injected in the source during build." + }, + "triggers": { + "description": "Webhooks to trigger building the application image", + "type": ["object", "null"], + "properties": { + "githubSecret": { + "description": "Name of the secret containing the WebHookSecretKey for the GitHub Webhook", + "type": "string" + }, + "genericSecret": { + "description": "Name of the secret containing the WebHookSecretKey for the Generic Webhook", + "type": "string" + } + } + }, + "s2i": { + "description": "Configuration specific to S2I Build (applicable only if build mode is set to s2i)", + "type": ["object", "null"], + "properties": { + "kind": { + "description": "Determines the type of images for S2I Builder and Runtime images", + "type": "string", + "enum": ["ImageStreamTag", "DockerImage", "ImageStreamImage"], + "default": "DockerImage" + }, + "jdk": { + "description": "JDK Version of the EAP S2I images", + "type": "string", + "enum": ["17"], + "default": "17" + }, + "jdk17": { + "description": "EAP S2I images for JDK 17", + "type": "object", + "properties": { + "builderImage": { + "description": "EAP S2I Builder image for JDK 17", + "type": "string" + }, + "runtimeImage": { + "description": "EAP S2I Runtime image for JDK 17", + "type": "string" + } + } + }, + "buildApplicationImage": { + "description": "Determine if the application image must be built. If false, the Helm release will build the first artifact image (with the name of the Helm release)", + "type": "boolean", + "default": true + }, + "builderKind": { + "description": "Determines the type of images for S2I Builder image. If omitted, the value of the kind properties is used", + "type": ["string", "null"], + "enum": ["ImageStreamTag", "DockerImage", "ImageStreamImage"] + }, + "runtimeKind": { + "description": "Determines the type of images for S2I Runtime image. If omitted, the value of the kind properties is used", + "type": ["string", "null"], + "enum": ["ImageStreamTag", "DockerImage", "ImageStreamImage"] + }, + "featurePacks": { + "description": "List of Galleon feature-packs identified by Maven coordinates (`::`). Deprecated, the recommended way to provision EAP is to use the eap-maven-plugin in the application pom.xml", + "type": ["string", "array", "null"], + "items": { + "type": "string" + } + }, + "galleonDir": { + "description": "Directory relative to the root directory for the build that contains custom content for Galleon.", + "type": ["string", "null"] + }, + "galleonLayers": { + "description": "List of Galleon Layers to provision. If galleonLayers are configured, the featurePacks that provides the layers must be specified (including EAP feature pack). Deprecated, the recommended way to provision EAP is to use the eap-maven-plugin in the application pom.xml", + "type": ["string", "array", "null"], + "items": { + "type": "string" + } + }, + "channels": { + "description": "List of Channels identified by Maven coordinates (`:`). If featurePacks are configured without any versioning, the channels that provides the latest feature packs can be specified. Deprecated, the recommended way to provision EAP is to use the eap-maven-plugin in the application pom.xml", + "type": ["string", "array", "null"], + "items": { + "type": "string" + } + } + } + } + } + }, + "deploy": { + "description": "Configuration to deploy the application", + "type": "object", + "properties": { + "annotations": { + "type": "object", + "description": "Annotations that are applied to the deployed application and its pods", + "additionalProperties": { + "type": "string" + } + }, + "enabled": { + "description": "Enable/Disable deploying the application image", + "type": "boolean", + "default": true + }, + "replicas": { + "type": "integer", + "description": "Number of pod replicas to deploy" + }, + "labels": { + "type": "object", + "description": "Labels that are applied to the deployed application and its pods", + "additionalProperties": { + "type":"string" + } + }, + "resources": { + "description": "Freeform resources requirements to deploy the application image" + }, + "env": { + "description": "List of environment variables to set in the container. Cannot be updated.", + "items": { + "description": "EnvVar represents an environment variable present in a Container.", + "properties": { + "name": { + "description": "Name of the environment variable. Must be a C_IDENTIFIER.", + "type": "string" + }, + "value": { + "description": "Variable references $(VAR_NAME) are expanded using the previous defined environment variables in the container and any service environment variables. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Defaults to \"\".", + "type": [ + "string", + "null" + ] + }, + "valueFrom": { + "description": "EnvVarSource represents a source for the value of an EnvVar.", + "properties": { + "configMapKeyRef": { + "description": "Selects a key from a ConfigMap.", + "properties": { + "key": { + "description": "The key to select.", + "type": "string" + }, + "name": { + "description": "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": [ + "string", + "null" + ] + }, + "optional": { + "description": "Specify whether the ConfigMap or its key must be defined", + "type": "boolean" + } + }, + "required": [ + "key" + ], + "type": "object" + }, + "fieldRef": { + "description": "ObjectFieldSelector selects an APIVersioned field of an object.", + "properties": { + "apiVersion": { + "description": "Version of the schema the FieldPath is written in terms of, defaults to \"v1\".", + "type": [ + "string", + "null" + ] + }, + "fieldPath": { + "description": "Path of the field to select in the specified API version.", + "type": "string" + } + }, + "required": [ + "fieldPath" + ], + "type": "object" + }, + "resourceFieldRef": { + "description": "ResourceFieldSelector represents container resources (cpu, memory) and their output format", + "properties": { + "containerName": { + "description": "Container name: required for volumes, optional for env vars", + "type": [ + "string", + "null" + ] + }, + "divisor": { + "oneOf": [ + { + "type": [ + "string", + "null" + ] + }, + { + "type": "integer" + } + ] + }, + "resource": { + "description": "Required: resource to select", + "type": "string" + } + }, + "required": [ + "resource" + ], + "type": "object" + }, + "secretKeyRef": { + "description": "SecretKeySelector selects a key of a Secret.", + "properties": { + "key": { + "description": "The key of the secret to select from. Must be a valid secret key.", + "type": "string" + }, + "name": { + "description": "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": [ + "string", + "null" + ] + }, + "optional": { + "description": "Specify whether the Secret or its key must be defined", + "type": "boolean" + } + }, + "required": [ + "key" + ], + "type": "object" + } + }, + "type": "object" + } + }, + "required": [ + "name" + ], + "type": "object" + }, + "type": [ + "array", + "null" + ] + }, + "envFrom": { + "description": "List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. All invalid keys will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.", + "items": { + "description": "EnvFromSource represents the source of a set of ConfigMaps", + "properties": { + "configMapRef": { + "description": "ConfigMapEnvSource selects a ConfigMap to populate the environment variables with.\n\nThe contents of the target ConfigMap's Data field will represent the key-value pairs as environment variables.", + "properties": { + "name": { + "description": "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": [ + "string", + "null" + ] + }, + "optional": { + "description": "Specify whether the ConfigMap must be defined", + "type": "boolean" + } + }, + "type": "object" + }, + "prefix": { + "description": "An optional identifier to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER.", + "type": [ + "string", + "null" + ] + }, + "secretRef": { + "description": "SecretEnvSource selects a Secret to populate the environment variables with.\n\nThe contents of the target Secret's Data field will represent the key-value pairs as environment variables.", + "properties": { + "name": { + "description": "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": [ + "string", + "null" + ] + }, + "optional": { + "description": "Specify whether the Secret must be defined", + "type": "boolean" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "type": [ + "array", + "null" + ] + }, + "route": { + "description": "Route configuration", + "type": "object", + "properties": { + "enabled": { + "description": "Enable/Disable creating a Route for the application", + "default": true, + "type": "boolean" + }, + "host": { + "description": "alias/DNS that points to the service. If not specified a route name will typically be automatically chosen", + "type": "string" + }, + "tls": { + "description": "TLS Configuration for the Route", + "type": "object", + "properties": { + "enabled" : { + "description": "Determines if the Route should be TLS-encrypted. If deploy.tls.enabled is true, the route will use the secure service to acess to the deployment", + "default": true, + "type": "boolean" + }, + "termination": { + "description": "Determines the type of TLS termination to use", + "type": "string", + "enum": ["edge", "reencrypt", "passthrough"], + "default": "edge" + }, + "insecureEdgeTerminationPolicy": { + "description": "Determines if insecure traffic should be redirected", + "type": "string", + "enum": ["Allow", "Disable", "Redirect"], + "default": "Redirect" + } + } + } + } + }, + "tls": { + "description": "TLS Configuration", + "type": "object", + "properties": { + "enabled": { + "description": "Enable the creation of a secure service to access the application.", + "default": false, + "type": "boolean" + } + } + }, + "livenessProbe": { + "description": "Freeform livenessProbe configuration" + }, + "readinessProbe": { + "description": "Freeform readinessProbe configuration" + }, + "startupProbe": { + "description": "Freeform startupProbe configuration" + }, + "volumeMounts": { + "description": "Freeform array of volumeMounts", + "type": ["array", "null"], + "items": { + "description": "VolumeMount describes a mounting of a Volume within a container.", + "required": ["name", "mountPath"], + "properties": { + "mountPath": { + "description": "Path within the container at which the volume should be mounted. Must not contain ':'.", + "type": "string" + }, + "mountPropagation": { + "description": "mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationHostToContainer is used. This field is alpha in 1.8 and can be reworked or removed in a future release.", + "type": ["string", "null"] + }, + "name": { + "description": "This must match the Name of a Volume.", + "type": "string" + }, + "readOnly": { + "description": "Mounted read-only if true, read-write otherwise (false or unspecified). Defaults to false.", + "type": "boolean" + }, + "subPath": { + "description": "Path within the volume from which the container's volume should be mounted. Defaults to \"\" (volume's root).", + "type": ["string","null"] + } + } + } + }, + "volumes": { + "description": "Freeform array of volumes", + "type": [ "array", "null"] + }, + "initContainers": { + "description": "Freeform array of initContainers", + "type": [ "array", "null"] + }, + "extraContainers": { + "description": "Freeform array of extra containers", + "type": [ "array", "null"] + }, + "imagePullSecrets:": { + "description": "ImagePullSecrets is a list of references to secrets in the same namespace to use for pulling the application image", + "type": [ "array", "null"], + "items": { + "description": "Reference to a secret in the same namespace.", + "required": ["name"], + "properties": { + "name": { + "description": "Name of the referenced secret", + "type": "string" + } + } + } + } + } + } + } +} diff --git a/tools/intersmash-tools-provisioners/src/test/java/org/jboss/intersmash/tools/provision/helm/wildfly/Eap8HelmChartReleaseAdapterTest.java b/tools/intersmash-tools-provisioners/src/test/java/org/jboss/intersmash/tools/provision/helm/wildfly/Eap8HelmChartReleaseAdapterTest.java new file mode 100644 index 000000000..7a3f2ff04 --- /dev/null +++ b/tools/intersmash-tools-provisioners/src/test/java/org/jboss/intersmash/tools/provision/helm/wildfly/Eap8HelmChartReleaseAdapterTest.java @@ -0,0 +1,205 @@ +package org.jboss.intersmash.tools.provision.helm.wildfly; + +import java.util.List; +import java.util.stream.Collectors; + +import org.jboss.intersmash.model.helm.charts.values.eap8.HelmEap8Release; +import org.jboss.intersmash.model.helm.charts.values.wildfly.HelmWildflyRelease; +import org.jboss.intersmash.tools.provision.helm.Image; +import org.jboss.intersmash.tools.provision.helm.wildfly.eap8.Eap8HelmChartReleaseAdapter; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import cz.xtf.builder.builders.pod.SecretVolume; +import io.fabric8.kubernetes.api.model.VolumeMountBuilder; + +/** + * Tests that verify that the EAP 8 and WildFly adapters for the related EAP 8 and WildFly values file (abstracted by + * their equivalent POJO) are working as expected, i.e. values are set properly to the adaptee and return expected + * values once read. + */ +class Eap8HelmChartReleaseAdapterTest { + + /** + * Verify that the EAP 8 adapter for the EAP 8 values file POJO is properly storing and exposing the adaptee values + */ + @Test + public void verifyEap8DynamicallyFilledAdapterTest() { + // arrange + HelmEap8Release adaptee = new HelmEap8Release(); + Eap8HelmChartReleaseAdapter concreteAdapter = new Eap8HelmChartReleaseAdapter(adaptee); + Eap8HelmChartReleaseAdapter eap8HelmChartRelease = concreteAdapter; + + SecretVolume secretVolume = new SecretVolume("v1", "s1"); + eap8HelmChartRelease + .withSourceRepositoryUrl("url") + .withSourceRepositoryRef("ref") + .withS2iFeaturePacks("fp1,fp2") + .withS2iGalleonLayers("gl1,gl2") + .withS2iChannel("ch1") + .withContextDir("context-dir") + .withBuildEnabled(Boolean.TRUE) + .withJdk17BuilderImage("jdk17-B") + .withJdk17RuntimeImage("jdk17-R") + .withDeployEnabled(Boolean.FALSE) + .withReplicas(42) + .withRouteHost("route-host") + .withVolume(secretVolume.build()) + .withVolumeMount(new VolumeMountBuilder() + .withName("vm1") + .withMountPath("mp1") + .withReadOnly(Boolean.TRUE).build()) + .withRouteTLSEnabled(Boolean.FALSE) + .withTlsEnabled(Boolean.FALSE) + .withBuildEnvironmentVariable("a", "1") + .withDeploymentEnvironmentVariable("b", "2") + .withInjectedImage( + new Image( + new Image.From("ImageStreamTag", "openshift", "myImage:latest"), + List.of(new Image.Path("mySourcePath", "myDestPath")))) + .withInjectedImage( + new Image( + new Image.From("ImageStreamTag", "openshift", "anotherImage:latest"), + List.of(new Image.Path("anotherSourcePath", "anotherDestPath")))); + + // act + final HelmEap8Release actualAdaptee = concreteAdapter.getAdaptee(); + + // assert + Assertions.assertEquals("url", actualAdaptee.getBuild().getUri()); + Assertions.assertEquals("ref", actualAdaptee.getBuild().getRef()); + Assertions.assertEquals("context-dir", actualAdaptee.getBuild().getContextDir()); + Assertions.assertEquals("fp1,fp2", actualAdaptee.getBuild().getS2i().getFeaturePacks()); + Assertions.assertEquals("gl1,gl2", actualAdaptee.getBuild().getS2i().getGalleonLayers()); + Assertions.assertEquals("ch1", actualAdaptee.getBuild().getS2i().getChannels()); + Assertions.assertEquals(Boolean.TRUE, actualAdaptee.getBuild().getEnabled()); + Assertions.assertEquals("jdk17-B", actualAdaptee.getBuild().getS2i().getJdk17().getBuilderImage()); + Assertions.assertEquals("jdk17-R", actualAdaptee.getBuild().getS2i().getJdk17().getRuntimeImage()); + Assertions.assertEquals(Boolean.FALSE, actualAdaptee.getDeploy().getEnabled()); + Assertions.assertEquals(42, actualAdaptee.getDeploy().getReplicas()); + Assertions.assertEquals("route-host", actualAdaptee.getDeploy().getRoute().getHost()); + Assertions.assertEquals(1, actualAdaptee.getDeploy().getVolumes().size()); + Assertions.assertEquals(1, actualAdaptee.getDeploy().getVolumeMounts().size()); + Assertions.assertEquals(Boolean.FALSE, actualAdaptee.getDeploy().getRoute().getTls().getEnabled()); + Assertions.assertEquals(Boolean.FALSE, actualAdaptee.getDeploy().getTls().getEnabled()); + Assertions.assertEquals(1, actualAdaptee.getBuild().getEnv().size()); + Assertions.assertEquals(1, actualAdaptee.getDeploy().getEnv().size()); + Assertions.assertTrue(List.class.isAssignableFrom(actualAdaptee.getBuild().getImages().getClass())); + List imagesInstancesList = (List) actualAdaptee.getBuild().getImages(); + Assertions.assertEquals(2, imagesInstancesList.size()); + Assertions.assertTrue(Image.class.isAssignableFrom(imagesInstancesList.get(0).getClass())); + // round trip check + Assertions.assertEquals("url", eap8HelmChartRelease.getSourceRepositoryUrl()); + Assertions.assertEquals("ref", eap8HelmChartRelease.getSourceRepositoryRef()); + Assertions.assertEquals("context-dir", eap8HelmChartRelease.getContextDir()); + Assertions.assertEquals("fp1,fp2", eap8HelmChartRelease.getS2iFeaturePacks().stream().collect(Collectors.joining(","))); + Assertions.assertEquals("gl1,gl2", + eap8HelmChartRelease.getS2iGalleonLayers().stream().collect(Collectors.joining(","))); + Assertions.assertEquals("ch1", eap8HelmChartRelease.getS2iChannels().stream().collect(Collectors.joining(","))); + Assertions.assertEquals(Boolean.TRUE, eap8HelmChartRelease.isBuildEnabled()); + Assertions.assertEquals("jdk17-B", eap8HelmChartRelease.getJdk17BuilderImage()); + Assertions.assertEquals("jdk17-R", eap8HelmChartRelease.getJdk17RuntimeImage()); + Assertions.assertEquals(Boolean.FALSE, eap8HelmChartRelease.isDeployEnabled()); + Assertions.assertEquals(42, eap8HelmChartRelease.getReplicas()); + Assertions.assertEquals("route-host", eap8HelmChartRelease.getRouteHost()); + Assertions.assertEquals(1, eap8HelmChartRelease.getVolumes().size()); + Assertions.assertEquals(1, eap8HelmChartRelease.getVolumeMounts().size()); + Assertions.assertEquals(Boolean.FALSE, eap8HelmChartRelease.isRouteTLSEnabled()); + Assertions.assertEquals(Boolean.FALSE, eap8HelmChartRelease.isTlsEnabled()); + Assertions.assertEquals(1, eap8HelmChartRelease.getBuildEnvironmentVariables().size()); + Assertions.assertEquals(1, eap8HelmChartRelease.getDeploymentEnvironmentVariables().size()); + Assertions.assertTrue(List.class.isAssignableFrom(actualAdaptee.getBuild().getImages().getClass())); + Assertions.assertEquals(2, eap8HelmChartRelease.getInjectedImages().size()); + } + + /** + * Verify that the WildFly adapter for the WildFly values file POJO is properly storing and exposing the adaptee values + */ + @Test + public void verifyWildFlyDynamicallyFilledAdapterTest() { + // arrange + HelmWildflyRelease adaptee = new HelmWildflyRelease(); + WildFlyHelmChartReleaseAdapter concreteAdapter = new WildFlyHelmChartReleaseAdapter(adaptee); + WildflyHelmChartRelease eap8HelmChartRelease = concreteAdapter; + + SecretVolume secretVolume = new SecretVolume("v1", "s1"); + eap8HelmChartRelease + .withSourceRepositoryUrl("url") + .withSourceRepositoryRef("ref") + .withS2iFeaturePacks("fp1,fp2") + .withS2iGalleonLayers("gl1,gl2") + .withS2iChannel("ch1") + .withContextDir("context-dir") + .withBuildEnabled(Boolean.TRUE) + .withJdk17BuilderImage("jdk17-B") + .withJdk17RuntimeImage("jdk17-R") + .withBootableJarBuilderImage("BJ-I") + .withDeployEnabled(Boolean.FALSE) + .withReplicas(42) + .withRouteHost("route-host") + .withVolume(secretVolume.build()) + .withVolumeMount(new VolumeMountBuilder() + .withName("vm1") + .withMountPath("mp1") + .withReadOnly(Boolean.TRUE).build()) + .withRouteTLSEnabled(Boolean.FALSE) + .withTlsEnabled(Boolean.FALSE) + .withBuildEnvironmentVariable("a", "1") + .withDeploymentEnvironmentVariable("b", "2") + .withInjectedImage( + new Image( + new Image.From("ImageStreamTag", "openshift", "myImage:latest"), + List.of(new Image.Path("mySourcePath", "myDestPath")))) + .withInjectedImage( + new Image( + new Image.From("ImageStreamTag", "openshift", "anotherImage:latest"), + List.of(new Image.Path("anotherSourcePath", "anotherDestPath")))); + + // act + final HelmWildflyRelease actualAdaptee = concreteAdapter.getAdaptee(); + // assert + Assertions.assertEquals("url", actualAdaptee.getBuild().getUri()); + Assertions.assertEquals("ref", actualAdaptee.getBuild().getRef()); + Assertions.assertEquals("context-dir", actualAdaptee.getBuild().getContextDir()); + Assertions.assertEquals("fp1,fp2", actualAdaptee.getBuild().getS2i().getFeaturePacks()); + Assertions.assertEquals("gl1,gl2", actualAdaptee.getBuild().getS2i().getGalleonLayers()); + Assertions.assertEquals(Boolean.TRUE, actualAdaptee.getBuild().getEnabled()); + Assertions.assertEquals("jdk17-B", actualAdaptee.getBuild().getS2i().getBuilderImage()); + Assertions.assertEquals("jdk17-R", actualAdaptee.getBuild().getS2i().getRuntimeImage()); + Assertions.assertEquals("BJ-I", actualAdaptee.getBuild().getBootableJar().getBuilderImage()); + Assertions.assertEquals(Boolean.FALSE, actualAdaptee.getDeploy().getEnabled()); + Assertions.assertEquals(42, actualAdaptee.getDeploy().getReplicas()); + Assertions.assertEquals("route-host", actualAdaptee.getDeploy().getRoute().getHost()); + Assertions.assertEquals(1, actualAdaptee.getDeploy().getVolumes().size()); + Assertions.assertEquals(1, actualAdaptee.getDeploy().getVolumeMounts().size()); + Assertions.assertEquals(Boolean.FALSE, actualAdaptee.getDeploy().getRoute().getTls().getEnabled()); + Assertions.assertEquals(Boolean.FALSE, actualAdaptee.getDeploy().getTls().getEnabled()); + Assertions.assertEquals(1, actualAdaptee.getBuild().getEnv().size()); + Assertions.assertEquals(1, actualAdaptee.getDeploy().getEnv().size()); + Assertions.assertTrue(List.class.isAssignableFrom(actualAdaptee.getBuild().getImages().getClass())); + List imagesInstancesList = (List) actualAdaptee.getBuild().getImages(); + Assertions.assertEquals(2, imagesInstancesList.size()); + Assertions.assertTrue(Image.class.isAssignableFrom(imagesInstancesList.get(0).getClass())); + // round-trip check + Assertions.assertEquals("url", eap8HelmChartRelease.getSourceRepositoryUrl()); + Assertions.assertEquals("ref", eap8HelmChartRelease.getSourceRepositoryRef()); + Assertions.assertEquals("context-dir", eap8HelmChartRelease.getContextDir()); + Assertions.assertEquals("fp1,fp2", eap8HelmChartRelease.getS2iFeaturePacks().stream().collect(Collectors.joining(","))); + Assertions.assertEquals("gl1,gl2", + eap8HelmChartRelease.getS2iGalleonLayers().stream().collect(Collectors.joining(","))); + Assertions.assertEquals(Boolean.TRUE, eap8HelmChartRelease.isBuildEnabled()); + Assertions.assertEquals("jdk17-B", eap8HelmChartRelease.getJdk17BuilderImage()); + Assertions.assertEquals("jdk17-R", eap8HelmChartRelease.getJdk17RuntimeImage()); + Assertions.assertEquals("BJ-I", eap8HelmChartRelease.getBootableJarBuilderImage()); + Assertions.assertEquals(Boolean.FALSE, eap8HelmChartRelease.isDeployEnabled()); + Assertions.assertEquals(42, eap8HelmChartRelease.getReplicas()); + Assertions.assertEquals("route-host", eap8HelmChartRelease.getRouteHost()); + Assertions.assertEquals(1, eap8HelmChartRelease.getVolumes().size()); + Assertions.assertEquals(1, eap8HelmChartRelease.getVolumeMounts().size()); + Assertions.assertEquals(Boolean.FALSE, eap8HelmChartRelease.isRouteTLSEnabled()); + Assertions.assertEquals(Boolean.FALSE, eap8HelmChartRelease.isTlsEnabled()); + Assertions.assertEquals(1, eap8HelmChartRelease.getBuildEnvironmentVariables().size()); + Assertions.assertEquals(1, eap8HelmChartRelease.getDeploymentEnvironmentVariables().size()); + Assertions.assertEquals(2, eap8HelmChartRelease.getInjectedImages().size()); + } +} From 690c9056acab9d919d6e2f661027e8dfc816d613 Mon Sep 17 00:00:00 2001 From: Fabio Burzigotti Date: Wed, 20 Dec 2023 15:57:55 +0100 Subject: [PATCH 2/2] [issue 123] - Fixing the HelmChartOpenShiftProvisioner::undeploy, it must actually wait for no app pods to survive --- ...WildflyHelmChartOpenShiftExampleApplication.java | 13 ++++++++----- .../helm/HelmChartOpenShiftProvisioner.java | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/testsuite/src/test/java/org/jboss/intersmash/testsuite/provision/openshift/WildflyHelmChartOpenShiftExampleApplication.java b/testsuite/src/test/java/org/jboss/intersmash/testsuite/provision/openshift/WildflyHelmChartOpenShiftExampleApplication.java index dcd63a4ce..4a25b1c3f 100644 --- a/testsuite/src/test/java/org/jboss/intersmash/testsuite/provision/openshift/WildflyHelmChartOpenShiftExampleApplication.java +++ b/testsuite/src/test/java/org/jboss/intersmash/testsuite/provision/openshift/WildflyHelmChartOpenShiftExampleApplication.java @@ -15,15 +15,14 @@ */ package org.jboss.intersmash.testsuite.provision.openshift; +import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; import org.assertj.core.util.Strings; import org.jboss.intersmash.deployments.IntersmashSharedDeploymentsProperties; import org.jboss.intersmash.deployments.WildflyDeploymentApplicationConfiguration; -import org.jboss.intersmash.model.helm.charts.values.wildfly.Build; -import org.jboss.intersmash.model.helm.charts.values.wildfly.Deploy; -import org.jboss.intersmash.model.helm.charts.values.wildfly.Env; import org.jboss.intersmash.model.helm.charts.values.eap8.HelmEap8Release; import org.jboss.intersmash.model.helm.charts.values.wildfly.HelmWildflyRelease; import org.jboss.intersmash.testsuite.IntersmashTestsuiteProperties; @@ -67,11 +66,15 @@ private HelmChartRelease loadRelease(final WildflyHelmChartRelease release) { .withSourceRepositoryUrl(IntersmashConfig.deploymentsRepositoryUrl()) .withSourceRepositoryRef(IntersmashConfig.deploymentsRepositoryRef()) .withContextDir("deployments/openshift-jakarta-sample-standalone") - // an example, not working with EAP 7.4.x or WildFly and commented in the deployment POM - .withS2iChannel(IntersmashConfig.getWildflyEeChannelLocation()) .withJdk17BuilderImage(IntersmashConfig.wildflyImageURL()) .withJdk17RuntimeImage(IntersmashConfig.wildflyRuntimeImageURL()) .withBuildEnvironmentVariable("MAVEN_ARGS_APPEND", mavenAdditionalArgs); + List channelDefinition = Arrays.asList(this.eeChannelGroupId(), this.eeChannelArtifactId(), + this.eeChannelVersion()); + if (!channelDefinition.isEmpty()) { + // an example of EAP channel usage, not working with EAP 7.4.x or WildFly + release.withS2iChannel(channelDefinition.stream().collect(Collectors.joining(":"))); + } return release; } diff --git a/tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/HelmChartOpenShiftProvisioner.java b/tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/HelmChartOpenShiftProvisioner.java index 07bbd46ce..f8edfd36b 100644 --- a/tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/HelmChartOpenShiftProvisioner.java +++ b/tools/intersmash-tools-provisioners/src/main/java/org/jboss/intersmash/tools/provision/helm/HelmChartOpenShiftProvisioner.java @@ -100,7 +100,7 @@ public void deploy() { @Override public void undeploy() { helmBinary.execute(getHelmChartUninstallArguments(this.getApplication().getName())); - OpenShiftWaiters.get(openShift, ffCheck).areExactlyNPodsReady(0, "app.kubernetes.io/instance", application.getName()) + OpenShiftWaiters.get(openShift, ffCheck).areNoPodsPresent("app.kubernetes.io/instance", application.getName()) .level(Level.DEBUG) .waitFor(); }