diff --git a/README.md b/README.md index d43d99d7..8db91d31 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,31 @@ ![build](https://github.com/citrusframework/yaks/workflows/build/badge.svg?branch=master) -# YAKS - ![logo][1] +# YAKS + YAKS Cloud-Native BDD testing or simply: Yet Another Kubernetes Service +* [Getting started](#getting-started) + * [Installation](#installation) + * [Running](#running-the-hello-world) +* [Steps](#steps) + * [Citrus Steps](#citrus-steps) + * Apache Camel Steps + * [Camel K Steps](#camel-k-steps) + * [JDBC Steps](#jdbc-steps) + * Http Steps + * Open API Steps + * Kafka Steps + * Jms Steps + * [Custom Steps](#custom-steps) +* [Runtime configuration](#runtime-configuration) + * [Add custom runtime dependencies](#add-custom-runtime-dependencies) + * [Add custom Maven repositories](#add-custom-maven-repositories) +* [Pre/Post scripts](#prepos-scripts) +* [Reporting options](#reporting-options) +* [For YAKS developers](#for-yaks-developers) + ## Getting Started YAKS allows you to perform Could-Native BDD testing. Cloud-Native here means that your tests execute within a POD in a @@ -212,7 +232,12 @@ hello Passed You can now change the test to use more complex steps and run it again with `./yaks test hello.feature`. -### Using Citrus features +## Steps + +Each line in a BDD feature file is backed by a step implementation that covers the actual runtime logic executed. YAKS +provides a set of out-of-the-box step implementations that you can just use in your feature file. + +### Citrus steps The Citrus framework provides a lot of features and predefined steps that can be used to write feature files. @@ -233,7 +258,7 @@ Feature: Integration Works ``` -### Using Camel K steps +### Camel K steps If the subject under test is a Camel K integration, you can leverage the YAKS Camel K bindings that provide useful steps for checking the status of integrations. @@ -248,7 +273,7 @@ For example: The Camel K extension library is provided by default in YAKS. -### Using JDBC steps +### JDBC steps YAKS provides a library that allows to execute SQL actions on relational DBs (limited to PostgreSQL for this POC). @@ -257,7 +282,7 @@ You can find examples of JDBC steps in the [examples](/examples/jdbc.feature) fi There's also an example that uses [JDBC and REST together](/examples/task-api.feature) and targets the [Syndesis TODO App](https://github.com/syndesisio/todo-example) database. -### Using custom steps +### Custom steps It's often useful to plug some custom steps into the testing environment. Custom steps help keeping the tests short and self-explanatory and at the same time help teams to add generic assertions that are meaningful in their @@ -280,7 +305,41 @@ This happens transparently to the user. The local library can also be uploaded to the Snap Minio server prior to running the test, using the `yaks upload` command. -### Adding custom runtime dependencies +## Runtime configuration + +There are several runtime options that you can set in order to configure which tests to run for instance. Each test directory +can have its own `yaks-config.yaml` configuration file that holds the runtime options for this specific test suite. + +```yaml +config: + runtime: + cucumber: + tags: + - "not @ignored" + glue: + - "org.citrusframework.yaks" + - "com.company.steps.custom" +``` + +The sample above uses different runtime options for Cucumber to specify a tag filter and some custom glue packages that +should be loaded. The given runtime options will be set as environment variables in the YAKS runtime pod. + +You can also specify the Cucumber options that get passed to the Cucumber runtime. + +```yaml +config: + runtime: + cucumber: + options: "--strict --monochrome --glue org.citrusframework.yaks" +``` + +Also we can make use of command line options when using the `yaks` binary. + +```bash +$ yaks test hello-world.feature --tag @regression --glue org.citrusframework.yaks +``` + +### Add custom runtime dependencies The YAKS testing framework provides a base runtime image that holds all required libraries and artifacts to execute tests. You may need to add additional runtime dependencies though in order to extend the framework capabilities. @@ -396,41 +455,96 @@ dependencies: You can add the configuration file when running the test via `yaks` CLI like follows: ```bash -$ yaks test --settings yaks.dependency.yaml camel-route.feature +$ yaks test --settings yaks.settings.yaml camel-route.feature ``` -## Runtime configuration +### Add custom Maven repositories -There are several runtime options that you can set in order to configure which tests to run for instance. Each test directory -can have its own `yaks-config.yaml` configuration file that holds the runtime options for this specific test suite. +When adding custom runtime dependencies those artifacts might not be available on the public central Maven repository. +Instead you may need to add a custom repository that holds your artifacts. -```yaml -config: - runtime: - cucumber: - tags: - - "not @ignored" - glue: - - "org.citrusframework.yaks" - - "com.company.steps.custom" +You can do this with several configuration options: + +#### Add Maven repository via System property or environment setting + +You can add repositories also by specifying the repositories as command line parameter when running the test via `yaks` CLI. + +```bash +$ yaks test --maven-repository jboss-ea=https://repository.jboss.org/nexus/content/groups/ea/ my.feature ``` -The sample above uses different runtime options for Cucumber to specify a tag filter and some custom glue packages that -should be loaded. The given runtime options will be set as environment variables in the YAKS runtime pod. +This will add a environment setting in the YAKS runtime container and the repository will be added to the Maven runtime project model. -You can also specify the Cucumber options that get passed to the Cucumber runtime. +#### Add Maven repository via property file + +YAKS supports adding Maven repository information to a property file called `yaks.properties`. The dependency is added through +Maven repository id and url in the property file using a common property key prefix `yaks.repository.` + +```properties +# Maven repositories +yaks.repository.central=https://repo.maven.apache.org/maven2/ +yaks.repository.jboss-ea=https://repository.jboss.org/nexus/content/groups/ea/ +``` + +You can add the property file when running the test via `yaks` CLI like follows: + +```bash +$ yaks test --settings yaks.properties my.feature +``` + +#### Add Maven repository via configuration file + +More complex repository configuration might require to add a configuration file as `.yaml` or `.json`. + +The configuration file is able to declare multiple repositories: ```yaml -config: - runtime: - cucumber: - options: "--strict --monochrome --glue org.citrusframework.yaks" +repositories: + - repository: + id: "central" + name: "Maven Central" + url: "https://repo.maven.apache.org/maven2/" + releases: + enabled: "true" + updatePolicy: "daily" + snapshots: + enabled: "false" + - repository: + id: "jboss-ea" + name: "JBoss Community Early Access Release Repository" + url: "https://repository.jboss.org/nexus/content/groups/ea/" + layout: "default" ``` -Also we can make use of command line options when using the `yaks` binary. +```json +{ + "repositories": [ + { + "id": "central", + "name": "Maven Central", + "url": "https://repo.maven.apache.org/maven2/", + "releases": { + "enabled": "true", + "updatePolicy": "daily" + }, + "snapshots": { + "enabled": "false" + } + }, + { + "id": "jboss-ea", + "name": "JBoss Community Early Access Release Repository", + "url": "https://repository.jboss.org/nexus/content/groups/ea/", + "layout": "default" + } + ] +} +``` + +You can add the configuration file when running the test via `yaks` CLI like follows: ```bash -$ yaks test hello-world.feature --tag @regression --glue org.citrusframework.yaks +$ yaks test --settings yaks.settings.yaml my.feature ``` ## Pre/Post scripts @@ -441,7 +555,7 @@ You can run scripts before/after a test group. Just add your commands to the `ya config: namespace: temporary: false - autoremove: true + autoRemove: true pre: - script: prepare.sh - run: echo Start! @@ -540,7 +654,7 @@ Test results: Total: 5, Passed: 5, Failed: 0, Skipped: 0 classpath:org/citrusframework/yaks/test3.feature:3: Passed ``` -## For YAKS Developers +## For YAKS developers Requirements: - Go 1.12+ diff --git a/examples/jitpack/jitpack.feature b/examples/jitpack/jitpack.feature new file mode 100644 index 00000000..e9fb6f74 --- /dev/null +++ b/examples/jitpack/jitpack.feature @@ -0,0 +1,5 @@ +Feature: JitPack steps extension + + Scenario: Use custom steps + Given My steps are loaded + Then I can do whatever I want! diff --git a/examples/jitpack/yaks-config.yaml b/examples/jitpack/yaks-config.yaml new file mode 100644 index 00000000..9742444e --- /dev/null +++ b/examples/jitpack/yaks-config.yaml @@ -0,0 +1,6 @@ +config: + runtime: + cucumber: + glue: + - "org.citrusframework.yaks" + - "dev.yaks.testing.standard" \ No newline at end of file diff --git a/examples/jitpack/yaks.settings.yaml b/examples/jitpack/yaks.settings.yaml new file mode 100644 index 00000000..875871da --- /dev/null +++ b/examples/jitpack/yaks.settings.yaml @@ -0,0 +1,19 @@ +repositories: + - repository: + id: "central" + name: "Maven Central" + url: "https://repo.maven.apache.org/maven2/" + releases: + enabled: "true" + updatePolicy: "daily" + snapshots: + enabled: "false" + - repository: + id: "jitpack.io" + name: "JitPack Repository" + url: "https://jitpack.io" +dependencies: + - dependency: + groupId: com.github.citrusframework + artifactId: yaks-step-extension + version: "0.0.1" diff --git a/examples/yaks.properties b/examples/yaks.properties index 194d2f1f..f5bcd84d 100644 --- a/examples/yaks.properties +++ b/examples/yaks.properties @@ -1 +1,6 @@ -yaks.dependency.camel-groovy=org.apache.camel:camel-groovy:@camel.version@ \ No newline at end of file +# Maven repositories +yaks.repository.central=https://repo.maven.apache.org/maven2/ +yaks.repository.jboss-ea=https://repository.jboss.org/nexus/content/groups/ea/ + +# Additional dependencies +yaks.dependency.camel-groovy=org.apache.camel:camel-groovy:@camel.version@ diff --git a/examples/yaks.settings.json b/examples/yaks.settings.json index 39bf0895..727054d2 100644 --- a/examples/yaks.settings.json +++ b/examples/yaks.settings.json @@ -1,4 +1,24 @@ { + "repositories": [ + { + "id": "central", + "name": "Maven Central", + "url": "https://repo.maven.apache.org/maven2/", + "releases": { + "enabled": "true", + "updatePolicy": "daily" + }, + "snapshots": { + "enabled": "false" + } + }, + { + "id": "jboss-ea", + "name": "JBoss Community Early Access Release Repository", + "url": "https://repository.jboss.org/nexus/content/groups/ea/", + "layout": "default" + } + ], "dependencies": [ { "groupId": "org.apache.camel", diff --git a/examples/yaks.settings.yaml b/examples/yaks.settings.yaml index 818bcebc..e1ccda88 100644 --- a/examples/yaks.settings.yaml +++ b/examples/yaks.settings.yaml @@ -1,5 +1,20 @@ +repositories: + - repository: + id: "central" + name: "Maven Central" + url: "https://repo.maven.apache.org/maven2/" + releases: + enabled: "true" + updatePolicy: "daily" + snapshots: + enabled: "false" + - repository: + id: "jboss-ea" + name: "JBoss Community Early Access Release Repository" + url: "https://repository.jboss.org/nexus/content/groups/ea/" + layout: "default" dependencies: - dependency: groupId: org.apache.camel artifactId: camel-groovy - version: "@camel.version@" \ No newline at end of file + version: "@camel.version@" diff --git a/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/ExtensionSettings.java b/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/ExtensionSettings.java index 6b50b0aa..efeba5a1 100644 --- a/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/ExtensionSettings.java +++ b/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/ExtensionSettings.java @@ -34,6 +34,9 @@ public final class ExtensionSettings { public static final String DEPENDENCIES_SETTING_KEY = "yaks.dependencies"; public static final String DEPENDENCIES_SETTING_ENV = "YAKS_DEPENDENCIES"; + public static final String REPOSITORIES_SETTING_KEY = "yaks.repositories"; + public static final String REPOSITORIES_SETTING_ENV = "YAKS_REPOSITORIES"; + /** * Prevent instantiation of utility class. */ diff --git a/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/ResourceInjectionListener.java b/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/ProjectModelEnricher.java similarity index 98% rename from java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/ResourceInjectionListener.java rename to java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/ProjectModelEnricher.java index 2b4b5d2d..0a027d0c 100644 --- a/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/ResourceInjectionListener.java +++ b/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/ProjectModelEnricher.java @@ -19,16 +19,16 @@ import java.util.List; -import org.citrusframework.yaks.maven.extension.configuration.FileBasedDependencyLoader; -import org.citrusframework.yaks.maven.extension.configuration.cucumber.FeatureTagsDependencyLoader; -import org.citrusframework.yaks.maven.extension.configuration.env.EnvironmentSettingDependencyLoader; -import org.citrusframework.yaks.maven.extension.configuration.properties.SystemPropertyDependencyLoader; import org.apache.maven.execution.ProjectExecutionEvent; import org.apache.maven.execution.ProjectExecutionListener; import org.apache.maven.lifecycle.LifecycleExecutionException; import org.apache.maven.model.Dependency; import org.apache.maven.model.Model; import org.apache.maven.model.Resource; +import org.citrusframework.yaks.maven.extension.configuration.FileBasedDependencyLoader; +import org.citrusframework.yaks.maven.extension.configuration.cucumber.FeatureTagsDependencyLoader; +import org.citrusframework.yaks.maven.extension.configuration.env.EnvironmentSettingDependencyLoader; +import org.citrusframework.yaks.maven.extension.configuration.properties.SystemPropertyDependencyLoader; import org.codehaus.plexus.component.annotations.Component; import org.codehaus.plexus.component.annotations.Requirement; import org.codehaus.plexus.logging.Logger; @@ -40,7 +40,7 @@ * @author Christoph Deppisch */ @Component( role = ProjectExecutionListener.class ) -public class ResourceInjectionListener implements ProjectExecutionListener { +public class ProjectModelEnricher implements ProjectExecutionListener { @Requirement private Logger logger; @@ -77,7 +77,6 @@ private void injectTestResources(Model projectModel) { */ private void injectProjectDependencies(Model projectModel) throws LifecycleExecutionException { logger.info("Add dynamic project dependencies ..."); - List dependencyList = projectModel.getDependencies(); dependencyList.addAll(new FileBasedDependencyLoader().load(projectModel.getProperties(), logger)); dependencyList.addAll(new SystemPropertyDependencyLoader().load(projectModel.getProperties(), logger)); diff --git a/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/ProjectModelReader.java b/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/ProjectModelReader.java new file mode 100644 index 00000000..b27bd5c3 --- /dev/null +++ b/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/ProjectModelReader.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.citrusframework.yaks.maven.extension; + +import javax.inject.Singleton; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.apache.maven.lifecycle.LifecycleExecutionException; +import org.apache.maven.model.Model; +import org.apache.maven.model.Repository; +import org.apache.maven.model.io.DefaultModelReader; +import org.apache.maven.model.io.ModelReader; +import org.citrusframework.yaks.maven.extension.configuration.FileBasedRepositoryLoader; +import org.citrusframework.yaks.maven.extension.configuration.env.EnvironmentSettingRepositoryLoader; +import org.citrusframework.yaks.maven.extension.configuration.properties.SystemPropertyRepositoryLoader; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.component.annotations.Requirement; +import org.codehaus.plexus.logging.Logger; + +/** + * Model reader extends default reader and adds dynamic Maven repositories loaded from different configuration sources. + * This way the extension can add configuration as if it was added to the pom.xml. + * + * @author Christoph Deppisch + */ +@Component(role = ModelReader.class) +@Singleton +public class ProjectModelReader extends DefaultModelReader { + + @Requirement + private Logger logger; + + private List repositoryList; + + @Override + public Model read(InputStream input, Map options) throws IOException { + Model projectModel = super.read(input, options); + projectModel.getRepositories().addAll(loadDynamicRepositories()); + return projectModel; + } + + /** + * Dynamically add project repositories based on different configuration sources such as environment variables, + * system properties configuration files. + */ + private List loadDynamicRepositories() { + if (repositoryList == null) { + repositoryList = new ArrayList<>(); + logger.info("Add dynamic project repositories ..."); + + try { + repositoryList.addAll(new FileBasedRepositoryLoader().load(logger)); + repositoryList.addAll(new SystemPropertyRepositoryLoader().load(logger)); + repositoryList.addAll(new EnvironmentSettingRepositoryLoader().load(logger)); + } catch (LifecycleExecutionException e) { + throw new RuntimeException(e); + } + } + + return repositoryList; + } +} diff --git a/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/configuration/AbstractConfigFileRepositoryLoader.java b/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/configuration/AbstractConfigFileRepositoryLoader.java new file mode 100644 index 00000000..de8f4a51 --- /dev/null +++ b/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/configuration/AbstractConfigFileRepositoryLoader.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.citrusframework.yaks.maven.extension.configuration; + +import java.nio.file.Path; +import java.util.Collections; +import java.util.List; + +import org.apache.maven.lifecycle.LifecycleExecutionException; +import org.apache.maven.model.Repository; +import org.codehaus.plexus.logging.Logger; + +/** + * @author Christoph Deppisch + */ +public abstract class AbstractConfigFileRepositoryLoader implements RepositoryLoader { + + @Override + public List load(Logger logger) { + return Collections.emptyList(); + } + + /** + * Load repositories from given file. + * @param filePath + * @param logger + * @return + * @throws LifecycleExecutionException + */ + protected abstract List load(Path filePath, Logger logger) throws LifecycleExecutionException; +} diff --git a/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/configuration/FileBasedRepositoryLoader.java b/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/configuration/FileBasedRepositoryLoader.java new file mode 100644 index 00000000..10682a0a --- /dev/null +++ b/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/configuration/FileBasedRepositoryLoader.java @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.citrusframework.yaks.maven.extension.configuration; + +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import org.apache.maven.lifecycle.LifecycleExecutionException; +import org.apache.maven.model.Repository; +import org.citrusframework.yaks.maven.extension.ExtensionSettings; +import org.citrusframework.yaks.maven.extension.configuration.json.JsonFileRepositoryLoader; +import org.citrusframework.yaks.maven.extension.configuration.properties.PropertyFileRepositoryLoader; +import org.citrusframework.yaks.maven.extension.configuration.yaml.YamlFileRepositoryLoader; +import org.codehaus.plexus.logging.Logger; + +/** + * Add repositories based on configuration living in a external file. Repository loader delegates to multiple file based + * loaders according to the file extension provided as configuration file (e.g. .yaml, .json, .properties). + * + * User can specify the configuration file to read via System property or environment variable. + * @author Christoph Deppisch + */ +public class FileBasedRepositoryLoader implements RepositoryLoader { + + /** Map of file based config loaders where mapping key is the property file extension */ + private final Map fileConfigLoaders; + + public FileBasedRepositoryLoader() { + this.fileConfigLoaders = new HashMap<>(); + + fileConfigLoaders.put("yaml", new YamlFileRepositoryLoader()); + fileConfigLoaders.put("yml", new YamlFileRepositoryLoader()); + fileConfigLoaders.put("json", new JsonFileRepositoryLoader()); + fileConfigLoaders.put("properties", new PropertyFileRepositoryLoader()); + } + + @Override + public List load(Logger logger) throws LifecycleExecutionException { + Path settingsFile = getSettingsFile(); + + if (Files.exists(settingsFile)) { + Optional fileExtension = getFileNameExtension(settingsFile.getFileName().toString()); + return fileExtension.flatMap(this::getFileConfigLoader) + .orElse(new PropertyFileRepositoryLoader()) + .load(settingsFile, logger); + } + + return Collections.emptyList(); + } + + private Optional getFileConfigLoader(String fileExtension) { + return Optional.ofNullable(fileConfigLoaders.get(fileExtension)); + } + + public static Path getSettingsFile() throws LifecycleExecutionException { + String filePath = ExtensionSettings.getSettingsFilePath(); + + if (filePath.startsWith("classpath:")) { + try { + URL resourceUrl = FileBasedRepositoryLoader.class.getClassLoader().getResource(filePath.substring("classpath:".length())); + if (resourceUrl != null) { + return Paths.get(resourceUrl.toURI()); + } + } catch (URISyntaxException e) { + throw new LifecycleExecutionException("Unable to locate properties file in classpath", e); + } + } else if (filePath.startsWith("file:")) { + return Paths.get(filePath.substring("file:".length())); + } + + return Paths.get(filePath); + } + + public static Optional getFileNameExtension(String filename) { + return Optional.ofNullable(filename) + .filter(f -> f.contains(".")) + .map(f -> f.substring(filename.lastIndexOf(".") + 1)); + } +} diff --git a/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/configuration/RepositoryLoader.java b/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/configuration/RepositoryLoader.java new file mode 100644 index 00000000..f22d5563 --- /dev/null +++ b/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/configuration/RepositoryLoader.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.citrusframework.yaks.maven.extension.configuration; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.List; + +import org.apache.maven.lifecycle.LifecycleExecutionException; +import org.apache.maven.model.Repository; +import org.codehaus.plexus.logging.Logger; + +/** + * @author Christoph Deppisch + */ +public interface RepositoryLoader { + + /** + * Load Maven repositories from configuration source. + * @param logger + * @return + */ + List load(Logger logger) throws LifecycleExecutionException; + + /** + * Construct repository instance from given url. Query parameters are translated to fields on the target repository. + * @param id + * @param url + * @param logger + * @return + */ + default Repository build(String id, String url, Logger logger) throws LifecycleExecutionException { + Repository repository = new Repository(); + + repository.setId(id); + + try { + URL configurationUrl = new URL(url); + repository.setUrl(String.format("%s://%s%s", configurationUrl.getProtocol(), configurationUrl.getHost(), configurationUrl.getPath())); + } catch (MalformedURLException e) { + throw new LifecycleExecutionException("Failed to construct Maven repository model from given URL", e); + } + + logger.info(String.format("Add Repository %s=%s", repository.getId(), repository.getUrl())); + return repository; + } +} diff --git a/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/configuration/env/EnvironmentSettingRepositoryLoader.java b/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/configuration/env/EnvironmentSettingRepositoryLoader.java new file mode 100644 index 00000000..04df2ac8 --- /dev/null +++ b/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/configuration/env/EnvironmentSettingRepositoryLoader.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.citrusframework.yaks.maven.extension.configuration.env; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import org.apache.maven.lifecycle.LifecycleExecutionException; +import org.apache.maven.model.Repository; +import org.citrusframework.yaks.maven.extension.ExtensionSettings; +import org.citrusframework.yaks.maven.extension.configuration.RepositoryLoader; +import org.codehaus.plexus.logging.Logger; + +/** + * Loader reads additional Maven repositories from an environment setting. If environment setting is present the loader + * expects the value to be a comma separated list of Maven repository scalars of form 'id=url'. + * + * @author Christoph Deppisch + */ +public class EnvironmentSettingRepositoryLoader implements RepositoryLoader { + + @Override + public List load(Logger logger) throws LifecycleExecutionException { + List repositoryList = new ArrayList<>(); + + String settings = getEnvSetting(ExtensionSettings.REPOSITORIES_SETTING_ENV); + + if (settings.length() > 0) { + for (String scalar : settings.split(",")) { + String[] config = scalar.split("="); + if (config.length == 2) { + repositoryList.add(build(config[0], config[1], logger)); + } + } + + if (!repositoryList.isEmpty()) { + logger.info(String.format("Add %s repositories found in environment variables", repositoryList.size())); + } + } + + return repositoryList; + } + + /** + * Read environment setting. If setting is not present default to empty value. + * @param name + * @return + */ + protected String getEnvSetting(String name) { + return Optional.ofNullable(System.getenv(name)).orElse(""); + } +} diff --git a/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/configuration/json/JsonFileRepositoryLoader.java b/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/configuration/json/JsonFileRepositoryLoader.java new file mode 100644 index 00000000..e6becfc7 --- /dev/null +++ b/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/configuration/json/JsonFileRepositoryLoader.java @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.citrusframework.yaks.maven.extension.configuration.json; + +import java.io.IOException; +import java.io.StringReader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.apache.maven.lifecycle.LifecycleExecutionException; +import org.apache.maven.model.Repository; +import org.citrusframework.yaks.maven.extension.configuration.AbstractConfigFileRepositoryLoader; +import org.codehaus.plexus.logging.Logger; + +/** + * Load repositories from Json configuration file. The configuration should reside as list of Maven artifact repositories. + * + * { + * "repositories": [ + * { + * "id": "central", + * "name": "Maven Central", + * "url": "https://repo.maven.apache.org/maven2/", + * "releases": { + * "enabled": "true", + * "updatePolicy": "daily" + * }, + * "snapshots": { + * "enabled": "false" + * } + * }, + * { + * "id": "jboss-ea", + * "name": "JBoss Community Early Access Release Repository", + * "url": "https://repository.jboss.org/nexus/content/groups/ea/", + * "layout": "default" + * } + * ] + * } + * + * Each repository value should be a proper Maven coordinate with groupId, artifactId and version. + * @author Christoph Deppisch + */ +public class JsonFileRepositoryLoader extends AbstractConfigFileRepositoryLoader { + + @Override + protected List load(Path filePath, Logger logger) throws LifecycleExecutionException { + List repositoryList = new ArrayList<>(); + + ObjectMapper mapper = new ObjectMapper(); + try { + JsonNode root = mapper.readTree(new StringReader(new String(Files.readAllBytes(filePath), StandardCharsets.UTF_8))); + ArrayNode repositories = (ArrayNode) root.get("repositories"); + for (Object o : repositories) { + ObjectNode model = (ObjectNode) o; + Repository repository = new Repository(); + + repository.setId(model.get("id").textValue()); + repository.setName(model.get("name").textValue()); + repository.setUrl(model.get("url").textValue()); + + logger.info(String.format("Add Repository %s=%s", repository.getId(), repository.getUrl())); + repositoryList.add(repository); + } + } catch (IOException e) { + throw new LifecycleExecutionException("Failed to read json repository config file", e); + } + + return repositoryList; + } +} diff --git a/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/configuration/properties/PropertyFileRepositoryLoader.java b/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/configuration/properties/PropertyFileRepositoryLoader.java new file mode 100644 index 00000000..af72a485 --- /dev/null +++ b/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/configuration/properties/PropertyFileRepositoryLoader.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.citrusframework.yaks.maven.extension.configuration.properties; + +import java.io.IOException; +import java.io.StringReader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; +import java.util.Properties; + +import org.apache.maven.lifecycle.LifecycleExecutionException; +import org.apache.maven.model.Repository; +import org.citrusframework.yaks.maven.extension.configuration.AbstractConfigFileRepositoryLoader; +import org.codehaus.plexus.logging.Logger; + +/** + * Property file based configuration loader. Property file is supposed to have one to many entries following the property name prefix: + * + * yaks.repository.central=https://repo.maven.apache.org/maven2/ + * yaks.repository.jboss-ea=https://repository.jboss.org/nexus/content/groups/ea/ + * + * Each property value should be a proper Maven coordinate with groupId, artifactId and version. + * + * @author Christoph Deppisch + */ +public class PropertyFileRepositoryLoader extends AbstractConfigFileRepositoryLoader { + + @Override + protected List load(Path filePath, Logger logger) throws LifecycleExecutionException { + List repositoryList = new ArrayList<>(); + + try { + Properties props = new Properties(); + props.load(new StringReader(new String(Files.readAllBytes(filePath), StandardCharsets.UTF_8))); + + for (Enumeration e = props.propertyNames(); e.hasMoreElements(); ) { + String name = (String) e.nextElement(); + if (name.startsWith("yaks.repository.")) { + repositoryList.add(build(name.substring("yaks.repository.".length()), props.getProperty(name), logger)); + } + } + } catch (IOException e) { + throw new LifecycleExecutionException("Failed to load properties from repository configuration file", e); + } + + return repositoryList; + } +} diff --git a/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/configuration/properties/SystemPropertyRepositoryLoader.java b/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/configuration/properties/SystemPropertyRepositoryLoader.java new file mode 100644 index 00000000..c65c9dc3 --- /dev/null +++ b/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/configuration/properties/SystemPropertyRepositoryLoader.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.citrusframework.yaks.maven.extension.configuration.properties; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.maven.lifecycle.LifecycleExecutionException; +import org.apache.maven.model.Repository; +import org.citrusframework.yaks.maven.extension.ExtensionSettings; +import org.citrusframework.yaks.maven.extension.configuration.RepositoryLoader; +import org.codehaus.plexus.logging.Logger; + +/** + * Loader reads additional repository configuration from system property setting. If system property is present the loader + * expects the value to be a comma separated list of Maven repository scalars of form 'id=url'. + * + * @author Christoph Deppisch + */ +public class SystemPropertyRepositoryLoader implements RepositoryLoader { + + @Override + public List load(Logger logger) throws LifecycleExecutionException { + List repositoryList = new ArrayList<>(); + + String coordinates = System.getProperty(ExtensionSettings.REPOSITORIES_SETTING_KEY, ""); + + if (coordinates.length() > 0) { + for (String scalar : coordinates.split(",")) { + String[] config = scalar.split("="); + if (config.length == 2) { + repositoryList.add(build(config[0], config[1], logger)); + } + } + + if (!repositoryList.isEmpty()) { + logger.info(String.format("Add %s repositories found in system properties", repositoryList.size())); + } + } + + return repositoryList; + } +} diff --git a/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/configuration/yaml/YamlFileRepositoryLoader.java b/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/configuration/yaml/YamlFileRepositoryLoader.java new file mode 100644 index 00000000..9cf792df --- /dev/null +++ b/java/tools/maven/yaks-maven-extension/src/main/java/org/citrusframework/yaks/maven/extension/configuration/yaml/YamlFileRepositoryLoader.java @@ -0,0 +1,91 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.citrusframework.yaks.maven.extension.configuration.yaml; + +import java.io.IOException; +import java.io.StringReader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.apache.maven.lifecycle.LifecycleExecutionException; +import org.apache.maven.model.Repository; +import org.citrusframework.yaks.maven.extension.configuration.AbstractConfigFileRepositoryLoader; +import org.codehaus.plexus.logging.Logger; +import org.yaml.snakeyaml.Yaml; + +/** + * Yaml configuration file loader is supposed to have one to many entries that unmarshal to a Maven repository model: + * + * repositories: + * - repository: + * id: "central" + * name: "Maven Central" + * url: "https://repo.maven.apache.org/maven2/" + * releases: + * enabled: "true" + * updatePolicy: "daily" + * snapshots: + * enabled: "false" + * - repository: + * id: "jboss-ea" + * name: "JBoss Community Early Access Release Repository" + * url: "https://repository.jboss.org/nexus/content/groups/ea/" + * layout: "default" + * + * Each repository value should be a proper Maven coordinate with groupId, artifactId and version. + * @author Christoph Deppisch + */ +public class YamlFileRepositoryLoader extends AbstractConfigFileRepositoryLoader { + + @Override + protected List load(Path filePath, Logger logger) throws LifecycleExecutionException { + try { + List repositoryList = new ArrayList<>(); + Yaml yaml = new Yaml(); + + HashMap>>> root = yaml.load(new StringReader(new String(Files.readAllBytes(filePath), StandardCharsets.UTF_8))); + if (root.containsKey("repositories")) { + List> repositories = root.get("repositories").stream() + .filter(d -> d.containsKey("repository")) + .map(d -> d.get("repository")) + .collect(Collectors.toList()); + + for (Map model : repositories) { + Repository repository = new Repository(); + + repository.setId(model.get("id").toString()); + repository.setName(model.get("name").toString()); + repository.setUrl(model.get("url").toString()); + + logger.info(String.format("Add Repository %s=%s", repository.getId(), repository.getUrl())); + repositoryList.add(repository); + } + } + + return repositoryList; + } catch (IOException e) { + throw new LifecycleExecutionException("Failed to read repository configuration file", e); + } + } +} diff --git a/java/tools/maven/yaks-maven-extension/src/test/java/org/citrusframework/yaks/maven/extension/configuration/FileBasedRepositoryLoaderTest.java b/java/tools/maven/yaks-maven-extension/src/test/java/org/citrusframework/yaks/maven/extension/configuration/FileBasedRepositoryLoaderTest.java new file mode 100644 index 00000000..acca9cc6 --- /dev/null +++ b/java/tools/maven/yaks-maven-extension/src/test/java/org/citrusframework/yaks/maven/extension/configuration/FileBasedRepositoryLoaderTest.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.citrusframework.yaks.maven.extension.configuration; + +import java.util.List; + +import org.apache.maven.lifecycle.LifecycleExecutionException; +import org.apache.maven.model.Repository; +import org.assertj.core.api.Assertions; +import org.citrusframework.yaks.maven.extension.ExtensionSettings; +import org.codehaus.plexus.logging.console.ConsoleLogger; +import org.junit.Test; + +/** + * @author Christoph Deppisch + */ +public class FileBasedRepositoryLoaderTest { + + private FileBasedRepositoryLoader loader = new FileBasedRepositoryLoader(); + + private ConsoleLogger logger = new ConsoleLogger(); + + @Test + public void shouldLoadFromPropertyFile() throws LifecycleExecutionException { + System.setProperty(ExtensionSettings.SETTINGS_FILE_KEY, "classpath:yaks.properties"); + List repositoryList = loader.load(logger); + TestHelper.verifyRepositories(repositoryList); + + System.setProperty(ExtensionSettings.SETTINGS_FILE_KEY, "classpath:yaks.settings.yaml"); + repositoryList = loader.load(logger); + TestHelper.verifyRepositories(repositoryList); + + System.setProperty(ExtensionSettings.SETTINGS_FILE_KEY, "classpath:yaks.settings.json"); + repositoryList = loader.load(logger); + TestHelper.verifyRepositories(repositoryList); + } + + @Test + public void shouldHandleNonExistingFile() throws LifecycleExecutionException { + System.setProperty(ExtensionSettings.SETTINGS_FILE_KEY, "doesNotExist"); + List repositoryList = loader.load(logger); + Assertions.assertThat(repositoryList).isEmpty(); + } + +} diff --git a/java/tools/maven/yaks-maven-extension/src/test/java/org/citrusframework/yaks/maven/extension/configuration/TestHelper.java b/java/tools/maven/yaks-maven-extension/src/test/java/org/citrusframework/yaks/maven/extension/configuration/TestHelper.java index 5e0425c3..871b6041 100644 --- a/java/tools/maven/yaks-maven-extension/src/test/java/org/citrusframework/yaks/maven/extension/configuration/TestHelper.java +++ b/java/tools/maven/yaks-maven-extension/src/test/java/org/citrusframework/yaks/maven/extension/configuration/TestHelper.java @@ -24,6 +24,7 @@ import java.util.Objects; import org.apache.maven.model.Dependency; +import org.apache.maven.model.Repository; import org.assertj.core.api.Assertions; /** @@ -67,4 +68,27 @@ public static void verifyDependencies(List dependencyList) { Assertions.assertThat(dependencyList).anyMatch(dependency -> dependency.toString().equals(foo.toString())); Assertions.assertThat(dependencyList).anyMatch(dependency -> dependency.toString().equals(bar.toString())); } + + /** + * Verify that default mock repositories are present in the given list od repositories. This verification can be shared by multiple + * tests that load the repository list in different ways (e.g. via Json, Yaml, System properties, ...) + * @param repositoryList + */ + public static void verifyRepositories(List repositoryList) { + Repository central = new Repository(); + central.setId("central"); + central.setName("Maven Central"); + central.setUrl("https://repo.maven.apache.org/maven2/"); + + Repository jboss = new Repository(); + jboss.setId("jboss-ea"); + jboss.setName("JBoss Community Early Access Release Repository"); + jboss.setUrl("https://repository.jboss.org/nexus/content/groups/ea/"); + + Assertions.assertThat(repositoryList).hasSize(2); + Assertions.assertThat(repositoryList).anyMatch(repository -> repository.getId().equals(central.getId())); + Assertions.assertThat(repositoryList).anyMatch(repository -> repository.getUrl().equals(central.getUrl())); + Assertions.assertThat(repositoryList).anyMatch(repository -> repository.getId().equals(jboss.getId())); + Assertions.assertThat(repositoryList).anyMatch(repository -> repository.getUrl().equals(jboss.getUrl())); + } } diff --git a/java/tools/maven/yaks-maven-extension/src/test/java/org/citrusframework/yaks/maven/extension/configuration/env/EnvironmentSettingRepositoryLoaderTest.java b/java/tools/maven/yaks-maven-extension/src/test/java/org/citrusframework/yaks/maven/extension/configuration/env/EnvironmentSettingRepositoryLoaderTest.java new file mode 100644 index 00000000..b58e27c6 --- /dev/null +++ b/java/tools/maven/yaks-maven-extension/src/test/java/org/citrusframework/yaks/maven/extension/configuration/env/EnvironmentSettingRepositoryLoaderTest.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.citrusframework.yaks.maven.extension.configuration.env; + +import java.util.List; + +import org.apache.maven.lifecycle.LifecycleExecutionException; +import org.apache.maven.model.Repository; +import org.assertj.core.api.Assertions; +import org.citrusframework.yaks.maven.extension.configuration.TestHelper; +import org.codehaus.plexus.logging.console.ConsoleLogger; +import org.junit.Test; + +/** + * @author Christoph Deppisch + */ +public class EnvironmentSettingRepositoryLoaderTest { + + private ConsoleLogger logger = new ConsoleLogger(); + @Test + public void shouldLoadFromEnv() throws LifecycleExecutionException { + EnvironmentSettingRepositoryLoader loader = new EnvironmentSettingRepositoryLoader() { + @Override + protected String getEnvSetting(String name) { + return "central=https://repo.maven.apache.org/maven2/,jboss-ea=https://repository.jboss.org/nexus/content/groups/ea/"; + } + }; + + List repositoryList = loader.load(logger); + TestHelper.verifyRepositories(repositoryList); + } + + @Test + public void shouldHandleNonExistingSystemProperty() throws LifecycleExecutionException { + EnvironmentSettingRepositoryLoader loader = new EnvironmentSettingRepositoryLoader(); + List repositoryList = loader.load(logger); + Assertions.assertThat(repositoryList).isEmpty(); + } +} diff --git a/java/tools/maven/yaks-maven-extension/src/test/java/org/citrusframework/yaks/maven/extension/configuration/json/JsonFileRepositoryLoaderTest.java b/java/tools/maven/yaks-maven-extension/src/test/java/org/citrusframework/yaks/maven/extension/configuration/json/JsonFileRepositoryLoaderTest.java new file mode 100644 index 00000000..5b0c729f --- /dev/null +++ b/java/tools/maven/yaks-maven-extension/src/test/java/org/citrusframework/yaks/maven/extension/configuration/json/JsonFileRepositoryLoaderTest.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.citrusframework.yaks.maven.extension.configuration.json; + +import java.net.URISyntaxException; +import java.nio.file.Paths; +import java.util.List; + +import org.apache.maven.lifecycle.LifecycleExecutionException; +import org.apache.maven.model.Repository; +import org.assertj.core.api.Assertions; +import org.citrusframework.yaks.maven.extension.configuration.TestHelper; +import org.codehaus.plexus.logging.console.ConsoleLogger; +import org.junit.Test; + +/** + * @author Christoph Deppisch + */ +public class JsonFileRepositoryLoaderTest { + + private JsonFileRepositoryLoader loader = new JsonFileRepositoryLoader(); + + private ConsoleLogger logger = new ConsoleLogger(); + + @Test + public void shouldLoadFromJson() throws LifecycleExecutionException, URISyntaxException { + List repositoryList = loader.load(TestHelper.getClasspathResource("yaks.settings.json"), logger); + TestHelper.verifyRepositories(repositoryList); + } + + @Test + public void shouldHandleNonExistingJson() { + Assertions.assertThatExceptionOfType(LifecycleExecutionException.class) + .isThrownBy(() -> loader.load(Paths.get("doesNotExist"), logger)); + } + +} diff --git a/java/tools/maven/yaks-maven-extension/src/test/java/org/citrusframework/yaks/maven/extension/configuration/properties/PropertyFileRepositoryLoaderTest.java b/java/tools/maven/yaks-maven-extension/src/test/java/org/citrusframework/yaks/maven/extension/configuration/properties/PropertyFileRepositoryLoaderTest.java new file mode 100644 index 00000000..dd4a7669 --- /dev/null +++ b/java/tools/maven/yaks-maven-extension/src/test/java/org/citrusframework/yaks/maven/extension/configuration/properties/PropertyFileRepositoryLoaderTest.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.citrusframework.yaks.maven.extension.configuration.properties; + +import java.net.URISyntaxException; +import java.nio.file.Paths; +import java.util.List; + +import org.apache.maven.lifecycle.LifecycleExecutionException; +import org.apache.maven.model.Repository; +import org.assertj.core.api.Assertions; +import org.citrusframework.yaks.maven.extension.configuration.TestHelper; +import org.codehaus.plexus.logging.console.ConsoleLogger; +import org.junit.Test; + +/** + * @author Christoph Deppisch + */ +public class PropertyFileRepositoryLoaderTest { + + private PropertyFileRepositoryLoader loader = new PropertyFileRepositoryLoader(); + + private ConsoleLogger logger = new ConsoleLogger(); + + @Test + public void shouldLoadFromPropertyFile() throws LifecycleExecutionException, URISyntaxException { + List repositoryList = loader.load(TestHelper.getClasspathResource("yaks.properties"), logger); + TestHelper.verifyRepositories(repositoryList); + } + + @Test + public void shouldHandleNonExistingFile() { + Assertions.assertThatExceptionOfType(LifecycleExecutionException.class) + .isThrownBy(() -> loader.load(Paths.get("doesNotExist"), logger)); + } + +} diff --git a/java/tools/maven/yaks-maven-extension/src/test/java/org/citrusframework/yaks/maven/extension/configuration/properties/SystemPropertyRepositoryLoaderTest.java b/java/tools/maven/yaks-maven-extension/src/test/java/org/citrusframework/yaks/maven/extension/configuration/properties/SystemPropertyRepositoryLoaderTest.java new file mode 100644 index 00000000..00b9b3b9 --- /dev/null +++ b/java/tools/maven/yaks-maven-extension/src/test/java/org/citrusframework/yaks/maven/extension/configuration/properties/SystemPropertyRepositoryLoaderTest.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.citrusframework.yaks.maven.extension.configuration.properties; + +import java.util.List; + +import org.apache.maven.lifecycle.LifecycleExecutionException; +import org.apache.maven.model.Repository; +import org.assertj.core.api.Assertions; +import org.citrusframework.yaks.maven.extension.ExtensionSettings; +import org.citrusframework.yaks.maven.extension.configuration.TestHelper; +import org.codehaus.plexus.logging.console.ConsoleLogger; +import org.junit.Test; + +/** + * @author Christoph Deppisch + */ +public class SystemPropertyRepositoryLoaderTest { + + private SystemPropertyRepositoryLoader loader = new SystemPropertyRepositoryLoader(); + + private ConsoleLogger logger = new ConsoleLogger(); + + @Test + public void shouldLoadFromSystemProperties() throws LifecycleExecutionException { + System.setProperty(ExtensionSettings.REPOSITORIES_SETTING_KEY, + "central=https://repo.maven.apache.org/maven2/,jboss-ea=https://repository.jboss.org/nexus/content/groups/ea/"); + + List repositoryList = loader.load(logger); + TestHelper.verifyRepositories(repositoryList); + } + + @Test + public void shouldHandleNonExistingSystemProperty() throws LifecycleExecutionException { + System.setProperty(ExtensionSettings.REPOSITORIES_SETTING_KEY, ""); + List repositoryList = loader.load(logger); + Assertions.assertThat(repositoryList).isEmpty(); + } + +} diff --git a/java/tools/maven/yaks-maven-extension/src/test/java/org/citrusframework/yaks/maven/extension/configuration/yaml/YamlFileRepositoryLoaderTest.java b/java/tools/maven/yaks-maven-extension/src/test/java/org/citrusframework/yaks/maven/extension/configuration/yaml/YamlFileRepositoryLoaderTest.java new file mode 100644 index 00000000..3b0e5f2d --- /dev/null +++ b/java/tools/maven/yaks-maven-extension/src/test/java/org/citrusframework/yaks/maven/extension/configuration/yaml/YamlFileRepositoryLoaderTest.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.citrusframework.yaks.maven.extension.configuration.yaml; + +import java.net.URISyntaxException; +import java.nio.file.Paths; +import java.util.List; + +import org.apache.maven.lifecycle.LifecycleExecutionException; +import org.apache.maven.model.Repository; +import org.assertj.core.api.Assertions; +import org.citrusframework.yaks.maven.extension.configuration.TestHelper; +import org.codehaus.plexus.logging.console.ConsoleLogger; +import org.junit.Test; + +/** + * @author Christoph Deppisch + */ +public class YamlFileRepositoryLoaderTest { + + private YamlFileRepositoryLoader loader = new YamlFileRepositoryLoader(); + + private ConsoleLogger logger = new ConsoleLogger(); + + @Test + public void shouldLoadFromYaml() throws LifecycleExecutionException, URISyntaxException { + List repositoryList = loader.load(TestHelper.getClasspathResource("yaks.settings.yaml"), logger); + TestHelper.verifyRepositories(repositoryList); + } + + @Test + public void shouldHandleNonExistingYaml() { + Assertions.assertThatExceptionOfType(LifecycleExecutionException.class) + .isThrownBy(() -> loader.load(Paths.get("doesNotExist"), logger)); + } +} diff --git a/java/tools/maven/yaks-maven-extension/src/test/resources/yaks.properties b/java/tools/maven/yaks-maven-extension/src/test/resources/yaks.properties index a63ec999..f1b449f8 100644 --- a/java/tools/maven/yaks-maven-extension/src/test/resources/yaks.properties +++ b/java/tools/maven/yaks-maven-extension/src/test/resources/yaks.properties @@ -15,6 +15,10 @@ # limitations under the License. # -# include these dependencies +# Maven repositories +yaks.repository.central=https://repo.maven.apache.org/maven2/ +yaks.repository.jboss-ea=https://repository.jboss.org/nexus/content/groups/ea/ + +# Include these dependencies additional dependencies yaks.dependency.foo=org.foo:foo-artifact:1.0.0 yaks.dependency.bar=org.bar:bar-artifact:1.5.0 diff --git a/java/tools/maven/yaks-maven-extension/src/test/resources/yaks.settings.json b/java/tools/maven/yaks-maven-extension/src/test/resources/yaks.settings.json index a5961d92..fda1062a 100644 --- a/java/tools/maven/yaks-maven-extension/src/test/resources/yaks.settings.json +++ b/java/tools/maven/yaks-maven-extension/src/test/resources/yaks.settings.json @@ -1,4 +1,24 @@ { + "repositories": [ + { + "id": "central", + "name": "Maven Central", + "url": "https://repo.maven.apache.org/maven2/", + "releases": { + "enabled": "true", + "updatePolicy": "daily" + }, + "snapshots": { + "enabled": "false" + } + }, + { + "id": "jboss-ea", + "name": "JBoss Community Early Access Release Repository", + "url": "https://repository.jboss.org/nexus/content/groups/ea/", + "layout": "default" + } + ], "dependencies": [ { "groupId": "org.foo", diff --git a/java/tools/maven/yaks-maven-extension/src/test/resources/yaks.settings.yaml b/java/tools/maven/yaks-maven-extension/src/test/resources/yaks.settings.yaml index 025807c4..7fc470e0 100644 --- a/java/tools/maven/yaks-maven-extension/src/test/resources/yaks.settings.yaml +++ b/java/tools/maven/yaks-maven-extension/src/test/resources/yaks.settings.yaml @@ -1,3 +1,18 @@ +repositories: + - repository: + id: "central" + name: "Maven Central" + url: "https://repo.maven.apache.org/maven2/" + releases: + enabled: "true" + updatePolicy: "daily" + snapshots: + enabled: "false" + - repository: + id: "jboss-ea" + name: "JBoss Community Early Access Release Repository" + url: "https://repository.jboss.org/nexus/content/groups/ea/" + layout: "default" dependencies: - dependency: groupId: org.foo diff --git a/pkg/cmd/config/config.go b/pkg/cmd/config/config.go index 8235428c..3ff2c736 100644 --- a/pkg/cmd/config/config.go +++ b/pkg/cmd/config/config.go @@ -56,7 +56,7 @@ type CucumberConfig struct { type NamespaceConfig struct { Name string `yaml:"name"` Temporary bool `yaml:"temporary"` - AutoRemove bool `yaml:"autoremove"` + AutoRemove bool `yaml:"autoRemove"` } func NewWithDefaults() *RunConfig { diff --git a/pkg/cmd/test.go b/pkg/cmd/test.go index 3fa11d68..e8b716ea 100644 --- a/pkg/cmd/test.go +++ b/pkg/cmd/test.go @@ -57,7 +57,9 @@ const ( ) const ( - NamespaceEnv = "YAKS_NAMESPACE" + NamespaceEnv = "YAKS_NAMESPACE" + RepositoriesEnv = "YAKS_REPOSITORIES" + DependenciesEnv = "YAKS_DEPENDENCIES" CucumberOptions = "CUCUMBER_OPTIONS" CucumberGlue = "CUCUMBER_GLUE" @@ -82,6 +84,7 @@ func newCmdTest(rootCmdOptions *RootCmdOptions) *cobra.Command { SilenceUsage: true, } + cmd.Flags().StringArrayVar(&options.repositories, "maven-repository", nil, "Adds custom Maven repository URL that is added to the runtime.") cmd.Flags().StringArrayVarP(&options.dependencies, "dependency", "d", nil, "Adds runtime dependencies that get automatically loaded before the test is executed.") cmd.Flags().StringArrayVarP(&options.uploads, "upload", "u", nil, "Upload a given library to the cluster to allow it to be used by tests.") cmd.Flags().StringVarP(&options.settings, "settings", "s", "", "Path to runtime settings file. File content is added to the test runtime and can hold runtime dependency information for instance.") @@ -97,6 +100,7 @@ func newCmdTest(rootCmdOptions *RootCmdOptions) *cobra.Command { type testCmdOptions struct { *RootCmdOptions + repositories []string dependencies []string uploads []string settings string @@ -343,17 +347,10 @@ func (o *testCmdOptions) createAndRunTest(c client.Client, rawName string, runCo }, } - settings, err := o.newSettings() - - if err != nil { + if settings, err := o.newSettings(); err != nil { return nil, err } else if settings != nil { test.Spec.Settings = *settings - } else if len(o.dependencies) > 0 { - test.Spec.Settings = v1alpha1.SettingsSpec{ - Name: "", - Content: strings.Join(o.dependencies, ","), - } } if err := o.setupEnvSettings(&test, runConfig); err != nil { @@ -459,6 +456,14 @@ func (o *testCmdOptions) setupEnvSettings(test *v1alpha1.Test, runConfig *config env = append(env, CucumberOptions+"="+runConfig.Config.Runtime.Cucumber.Options) } + if len(o.repositories) > 0 { + env = append(env, RepositoriesEnv+"="+strings.Join(o.repositories, ",")) + } + + if len(o.dependencies) > 0 { + env = append(env, DependenciesEnv+"="+strings.Join(o.dependencies, ",")) + } + if o.env != nil { copy(env, o.env) } @@ -471,15 +476,6 @@ func (o *testCmdOptions) setupEnvSettings(test *v1alpha1.Test, runConfig *config } func (o *testCmdOptions) newSettings() (*v1alpha1.SettingsSpec, error) { - runtimeDependencies := o.dependencies - - if len(runtimeDependencies) > 0 { - settings := v1alpha1.SettingsSpec{ - Content: strings.Join(runtimeDependencies, ","), - } - return &settings, nil - } - if o.settings == "" { return nil, nil } diff --git a/pkg/controller/test/start.go b/pkg/controller/test/start.go index a5880dad..6d5b0a79 100644 --- a/pkg/controller/test/start.go +++ b/pkg/controller/test/start.go @@ -175,12 +175,6 @@ func (action *startAction) newTestingPod(ctx context.Context, test *v1alpha1.Tes Value: "/etc/yaks/tests/" + test.Spec.Settings.Name, }, ) - } else if test.Spec.Settings.Content != "" { - pod.Spec.Containers[0].Env = append(pod.Spec.Containers[0].Env, v1.EnvVar{ - Name: "YAKS_DEPENDENCIES", - Value: test.Spec.Settings.Content, - }, - ) } if err := action.injectSnap(ctx, &pod); err != nil {