From fd6ee368da6fed8e45565bc24758e3556583862f Mon Sep 17 00:00:00 2001 From: Jakub Stejskal Date: Mon, 29 Jul 2024 12:31:29 +0200 Subject: [PATCH] Add operator-sdk runner Signed-off-by: Jakub Stejskal --- pom.xml | 5 + test-frame-openshift/pom.xml | 14 ++ .../skodjob/testframe/olm/OperatorSdkRun.java | 95 ++++++++++ .../testframe/olm/OperatorSdkRunBuilder.java | 171 ++++++++++++++++++ .../olm/OperatorSdkRunBuilderTest.java | 79 ++++++++ 5 files changed, 364 insertions(+) create mode 100644 test-frame-openshift/src/main/java/io/skodjob/testframe/olm/OperatorSdkRun.java create mode 100644 test-frame-openshift/src/main/java/io/skodjob/testframe/olm/OperatorSdkRunBuilder.java create mode 100644 test-frame-openshift/src/test/java/io/skodjob/testframe/olm/OperatorSdkRunBuilderTest.java diff --git a/pom.xml b/pom.xml index eeaceb0..a40e17a 100644 --- a/pom.xml +++ b/pom.xml @@ -121,6 +121,11 @@ test-frame-kubernetes ${project.version} + + io.skodjob + test-frame-openshift + ${project.version} + io.skodjob test-frame-log-collector diff --git a/test-frame-openshift/pom.xml b/test-frame-openshift/pom.xml index 3dff5c0..b3ea4f1 100644 --- a/test-frame-openshift/pom.xml +++ b/test-frame-openshift/pom.xml @@ -86,6 +86,20 @@ io.fabric8 kubernetes-client-api + + org.slf4j + slf4j-api + + + org.apache.logging.log4j + log4j-slf4j2-impl + test + + + org.junit.jupiter + junit-jupiter-api + test + diff --git a/test-frame-openshift/src/main/java/io/skodjob/testframe/olm/OperatorSdkRun.java b/test-frame-openshift/src/main/java/io/skodjob/testframe/olm/OperatorSdkRun.java new file mode 100644 index 0000000..2896cda --- /dev/null +++ b/test-frame-openshift/src/main/java/io/skodjob/testframe/olm/OperatorSdkRun.java @@ -0,0 +1,95 @@ +/* + * Copyright Skodjob authors. + * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). + */ +package io.skodjob.testframe.olm; + +import io.skodjob.testframe.executor.Exec; +import io.skodjob.testframe.executor.ExecResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.security.InvalidParameterException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Runner for operator-sdk run command + */ +public class OperatorSdkRun { + private static final Logger LOGGER = LoggerFactory.getLogger(OperatorSdkRun.class); + + protected String namespace; + protected String timeout; + protected String installMode; + protected String indexImage; + protected String kubeconfig; + protected String bundleImage; + + private static final String OPTION_INDEX_IMAGE = "--index-image"; + private static final String OPTION_NAMESPACE = "--namespace"; + private static final String OPTION_KUBECONFIG = "--kubeconfig"; + private static final String OPTION_TIMEOUT = "--timeout"; + private static final String OPTION_INSTALL_MODE = "--install-mode"; + private static final String CMD = "operator-sdk"; + private static final String RUN = "run"; + private static final String BUNDLE = "bundle"; + + /** + * Constructor of the runner + * + * @param operatorSdkRunBuilder operator-sdk run command configuration + */ + public OperatorSdkRun(OperatorSdkRunBuilder operatorSdkRunBuilder) { + if (operatorSdkRunBuilder.getNamespace() == null) { + throw new InvalidParameterException("Namespace is a mandatory parameter for OperatorSdkRun!"); + } + + if (operatorSdkRunBuilder.getBundleImage() == null) { + throw new InvalidParameterException("BundleImage is a mandatory parameter for OperatorSdkRun!"); + } + + if (operatorSdkRunBuilder.getInstallMode() == null) { + throw new InvalidParameterException("InstallMode is a mandatory parameter for OperatorSdkRun!"); + } + + this.namespace = operatorSdkRunBuilder.getNamespace(); + this.bundleImage = operatorSdkRunBuilder.getBundleImage(); + this.installMode = operatorSdkRunBuilder.getInstallMode(); + this.timeout = operatorSdkRunBuilder.getTimeout(); + this.indexImage = operatorSdkRunBuilder.getIndexImage(); + this.kubeconfig = operatorSdkRunBuilder.getKubeconfig(); + } + + /** + * Run the built command via Executor and return it result + * + * @return ExecResult with data from the executor + */ + public ExecResult run() { + List command = new ArrayList<>(Arrays.asList(CMD, RUN, BUNDLE, bundleImage)); + + command.add(OPTION_NAMESPACE); + command.add(namespace); + command.add(OPTION_INSTALL_MODE); + command.add(installMode); + + if (indexImage != null) { + command.add(OPTION_INDEX_IMAGE); + command.add(indexImage); + } + + if (timeout != null) { + command.add(OPTION_TIMEOUT); + command.add(String.valueOf(timeout)); + } + + if (kubeconfig != null) { + command.add(OPTION_KUBECONFIG); + command.add(kubeconfig); + } + + return Exec.exec(command); + } +} diff --git a/test-frame-openshift/src/main/java/io/skodjob/testframe/olm/OperatorSdkRunBuilder.java b/test-frame-openshift/src/main/java/io/skodjob/testframe/olm/OperatorSdkRunBuilder.java new file mode 100644 index 0000000..02a333b --- /dev/null +++ b/test-frame-openshift/src/main/java/io/skodjob/testframe/olm/OperatorSdkRunBuilder.java @@ -0,0 +1,171 @@ +/* + * Copyright Skodjob authors. + * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). + */ +package io.skodjob.testframe.olm; + +/** + * Builder class for the {@link OperatorSdkRun} + */ +public class OperatorSdkRunBuilder { + + private String namespace; + private String timeout; + private String installMode; + private String indexImage; + private String kubeconfig; + private String bundleImage; + + + /** + * Constructor for creating {@link OperatorSdkRunBuilder} with parameters from + * current instance of {@link OperatorSdkRun}. + * + * @param operatorSdkRun current instance of {@link OperatorSdkRun} + */ + public OperatorSdkRunBuilder(OperatorSdkRun operatorSdkRun) { + this.namespace = operatorSdkRun.namespace; + this.timeout = operatorSdkRun.timeout; + this.installMode = operatorSdkRun.installMode; + this.indexImage = operatorSdkRun.indexImage; + this.kubeconfig = operatorSdkRun.kubeconfig; + this.bundleImage = operatorSdkRun.bundleImage; + } + + /** + * Empty constructor, we can use the "with" methods to build the LogCollector's configuration + */ + public OperatorSdkRunBuilder() { + // empty constructor + } + + /** + * Method for setting the namespace, where the bundle container will be deployed + * + * @param namespace where the bundle container will be deployed + * @return {@link OperatorSdkRunBuilder} object + */ + public OperatorSdkRunBuilder withNamespace(String namespace) { + this.namespace = namespace; + return this; + } + + /** + * Method for setting the timeout - string dictating the maximum time that run can run. + * The command will return an error if the timeout is exceeded. + * + * @param timeout string dictating the maximum time that run + * @return {@link OperatorSdkRunBuilder} object + */ + public OperatorSdkRunBuilder withTimeout(String timeout) { + this.timeout = timeout; + return this; + } + + /** + * Method for setting the index-image for run command + * + * @param indexImage specifies an index image in which to inject the given bundle + * @return {@link OperatorSdkRunBuilder} object + */ + public OperatorSdkRunBuilder withIndexImage(String indexImage) { + this.indexImage = indexImage; + return this; + } + + /** + * Method for setting the install-mode for run command + * + * @param installMode (AllNamespace|OwnNamespace|SingleNamespace=) + * @return {@link OperatorSdkRunBuilder} object + */ + public OperatorSdkRunBuilder withInstallMode(String installMode) { + this.installMode = installMode; + return this; + } + + /** + * Method for setting the kubeconfig for run command + * + * @param kubeconfig the local path to a kubeconfig + * @return {@link OperatorSdkRunBuilder} object + */ + public OperatorSdkRunBuilder withKubeConfig(String kubeconfig) { + this.kubeconfig = kubeconfig; + return this; + } + + /** + * Method for setting the bundle-image for run command + * + * @param bundleImage specifies the Operator bundle image + * @return {@link OperatorSdkRunBuilder} object + */ + public OperatorSdkRunBuilder withBundleImage(String bundleImage) { + this.bundleImage = bundleImage; + return this; + } + + /** + * Get namespace + * + * @return namespace + */ + public String getNamespace() { + return namespace; + } + + /** + * Get timeout + * + * @return timeout + */ + public String getTimeout() { + return timeout; + } + + /** + * Get installMode + * + * @return installMode + */ + public String getInstallMode() { + return installMode; + } + + /** + * Get indexImage + * + * @return indexImage + */ + public String getIndexImage() { + return indexImage; + } + + /** + * Get kubeconfig + * + * @return kubeconfig + */ + public String getKubeconfig() { + return kubeconfig; + } + + /** + * Get bundleImage + * + * @return bundleImage + */ + public String getBundleImage() { + return bundleImage; + } + + /** + * Method for building the {@link OperatorSdkRun} object + * + * @return {@link OperatorSdkRun} configured by the specified parameters + */ + public OperatorSdkRun build() { + return new OperatorSdkRun(this); + } +} diff --git a/test-frame-openshift/src/test/java/io/skodjob/testframe/olm/OperatorSdkRunBuilderTest.java b/test-frame-openshift/src/test/java/io/skodjob/testframe/olm/OperatorSdkRunBuilderTest.java new file mode 100644 index 0000000..28789e9 --- /dev/null +++ b/test-frame-openshift/src/test/java/io/skodjob/testframe/olm/OperatorSdkRunBuilderTest.java @@ -0,0 +1,79 @@ +/* + * Copyright Skodjob authors. + * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). + */ +package io.skodjob.testframe.olm; + +import org.junit.jupiter.api.Test; + +import java.security.InvalidParameterException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class OperatorSdkRunBuilderTest { + + @Test + void testBuilder() { + OperatorSdkRun operatorSdkRun = new OperatorSdkRunBuilder() + .withTimeout("2m") + .withNamespace("namespace-1") + .withBundleImage("my-bundle-image") + .withIndexImage("my-index-image") + .withKubeConfig("path-to-kubeconfig") + .withInstallMode("automatic") + .build(); + + assertNotNull(operatorSdkRun); + + assertEquals(operatorSdkRun.bundleImage, "my-bundle-image"); + assertEquals(operatorSdkRun.timeout, "2m"); + assertEquals(operatorSdkRun.indexImage, "my-index-image"); + assertEquals(operatorSdkRun.namespace, "namespace-1"); + assertEquals(operatorSdkRun.installMode, "automatic"); + assertEquals(operatorSdkRun.kubeconfig, "path-to-kubeconfig"); + } + + @Test + void testMissingNamespace() { + OperatorSdkRunBuilder operatorSdkRunBuilder = new OperatorSdkRunBuilder() + .withTimeout("2m") + .withBundleImage("my-bundle-image") + .withIndexImage("my-index-image") + .withKubeConfig("path-to-kubeconfig") + .withInstallMode("automatic"); + + InvalidParameterException thrown = assertThrows(InvalidParameterException.class, operatorSdkRunBuilder::build); + + assertEquals("Namespace is a mandatory parameter for OperatorSdkRun!", thrown.getMessage()); + } + + @Test + void testMissingBundleImage() { + OperatorSdkRunBuilder operatorSdkRunBuilder = new OperatorSdkRunBuilder() + .withTimeout("2m") + .withNamespace("namespace-1") + .withIndexImage("my-index-image") + .withKubeConfig("path-to-kubeconfig") + .withInstallMode("automatic"); + + InvalidParameterException thrown = assertThrows(InvalidParameterException.class, operatorSdkRunBuilder::build); + + assertEquals("BundleImage is a mandatory parameter for OperatorSdkRun!", thrown.getMessage()); + } + + @Test + void testWrongInstallMode() { + OperatorSdkRunBuilder operatorSdkRunBuilder = new OperatorSdkRunBuilder() + .withTimeout("2m") + .withNamespace("namespace-1") + .withIndexImage("my-index-image") + .withBundleImage("my-bundle-image") + .withKubeConfig("path-to-kubeconfig"); + + InvalidParameterException thrown = assertThrows(InvalidParameterException.class, operatorSdkRunBuilder::build); + + assertEquals("InstallMode is a mandatory parameter for OperatorSdkRun!", thrown.getMessage()); + } +}