Messaging polyglot support (#1472)
added support for AMQP, KAFKA and standalone options
This commit is contained in:
committed by
GitHub
parent
c5d3456d3a
commit
a915cf102b
12
docker/spring-cloud-contract-docker/build_adocs.sh
Executable file
12
docker/spring-cloud-contract-docker/build_adocs.sh
Executable file
@@ -0,0 +1,12 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
CURRENT_DIR="$( pwd )"
|
||||
ADOC_OUTPUT_DIR="${CURRENT_DIR}/target/adoc/"
|
||||
pushd project
|
||||
mkdir -p "${ADOC_OUTPUT_DIR}"
|
||||
./gradlew dumpAllProps
|
||||
cp "$( pwd )/build/props.adoc" "${ADOC_OUTPUT_DIR}/"
|
||||
cp "$( pwd )/build/appProps.adoc" "${ADOC_OUTPUT_DIR}/"
|
||||
popd
|
||||
@@ -8,15 +8,20 @@ GRADLE_WRAPPER_DIR="${HOME}/.gradle/wrapper/dists/${GRADLE_BIN_DIR}"
|
||||
CURRENT_DIR="$( pwd )"
|
||||
GRADLE_OUTPUT_DIR="${CURRENT_DIR}/target/gradle_dependencies/"
|
||||
pushd project
|
||||
rm -rf .gradle
|
||||
./gradlew wrapper --gradle-version "${WRAPPER_VERSION}"
|
||||
./gradlew clean resolveDependencies build -g "${GRADLE_OUTPUT_DIR}" -x copyOutput || echo "Expected to fail the build"
|
||||
if [ -d "${GRADLE_WRAPPER_DIR}" ]; then
|
||||
echo "Copying Gradle Wrapper version [${WRAPPER_VERSION}]"
|
||||
mkdir -p "${GRADLE_OUTPUT_DIR}/wrapper/dists/"
|
||||
cp -r "${GRADLE_WRAPPER_DIR}" "${GRADLE_OUTPUT_DIR}/wrapper/dists/"
|
||||
else
|
||||
echo "Gradle Wrapper [${GRADLE_WRAPPER_DIR}] not found. Will not copy it"
|
||||
fi
|
||||
rm -rf build
|
||||
rm -rf .gradle
|
||||
./gradlew wrapper --gradle-version "${WRAPPER_VERSION}"
|
||||
./gradlew clean resolveDependencies build -g "${GRADLE_OUTPUT_DIR}" -x copyOutput || echo "Expected to fail the build"
|
||||
if [ -d "${GRADLE_WRAPPER_DIR}" ]; then
|
||||
echo "Copying Gradle Wrapper version [${WRAPPER_VERSION}]"
|
||||
mkdir -p "${GRADLE_OUTPUT_DIR}/wrapper/dists/"
|
||||
cp -r "${GRADLE_WRAPPER_DIR}" "${GRADLE_OUTPUT_DIR}/wrapper/dists/"
|
||||
else
|
||||
echo "Gradle Wrapper [${GRADLE_WRAPPER_DIR}] not found. Will not copy it"
|
||||
fi
|
||||
popd
|
||||
|
||||
./build_adocs.sh
|
||||
|
||||
pushd project
|
||||
rm -rf build
|
||||
popd
|
||||
17
docker/spring-cloud-contract-docker/project/README.adoc
Normal file
17
docker/spring-cloud-contract-docker/project/README.adoc
Normal file
@@ -0,0 +1,17 @@
|
||||
# Spring Cloud Contract Verifier Docker Project
|
||||
|
||||
## Developer tips
|
||||
|
||||
In order to use a new environment variable inside the Gradle script, you need to add it to the `envVars` map together with a description and a default value. Otherwise, any attempt to resolve such an environment variable will lead to an exception being thrown.
|
||||
|
||||
If you're referencing any environment variables from inside the Java code please follow the following convention.
|
||||
|
||||
```java
|
||||
/**
|
||||
* Some description.
|
||||
**/
|
||||
@Value("${ENV_VAR_NAME:defaultValue}")
|
||||
String envVar;
|
||||
```
|
||||
|
||||
If you provide Javadocs, we will automatically parse any `@Value` annotated fields and build a table of environment variables with description and default values.
|
||||
@@ -1,3 +1,5 @@
|
||||
import contracts.DocsFromSources
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenLocal()
|
||||
@@ -10,13 +12,39 @@ buildscript {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath "io.spring.gradle:dependency-management-plugin:1.0.8.RELEASE"
|
||||
classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}"
|
||||
classpath "org.springframework.cloud:spring-cloud-contract-gradle-plugin:${verifierVersion}"
|
||||
}
|
||||
}
|
||||
|
||||
group = getProp("PROJECT_GROUP") ?: 'com.example'
|
||||
version = getProp("PROJECT_VERSION") ?: '0.0.1-SNAPSHOT'
|
||||
Map<String, EnvVar> envVars = [
|
||||
PROJECT_GROUP: new EnvVar("Your project's group ID", "com.example"),
|
||||
PROJECT_VERSION: new EnvVar("Your project's version", "0.0.1-SNAPSHOT"),
|
||||
PROJECT_NAME: new EnvVar("Your project's artifact id", "example"),
|
||||
STANDALONE_PROTOCOL: new EnvVar("For standalone version, which additional protocol should be added", ""),
|
||||
PRODUCER_STUBS_CLASSIFIER: new EnvVar("Archive classifier used for generated producer stubs", "stubs"),
|
||||
FAIL_ON_NO_CONTRACTS: new EnvVar("Should the build fail if there are no contracts present?", false),
|
||||
REPO_WITH_BINARIES_URL: new EnvVar("URL of your Artifact Manager (defaults to the default URL of https://jfrog.com/artifactory/[Artifactory] when running locally)", "http://localhost:8081/artifactory/libs-release-local"),
|
||||
REPO_WITH_BINARIES_USERNAME: new EnvVar("(optional) Username when the Artifact Manager is secured", "admin"),
|
||||
REPO_WITH_BINARIES_PASSWORD: new EnvVar("(optional) Password when the Artifact Manager is secured", "password"),
|
||||
PUBLISH_ARTIFACTS: new EnvVar("If set to `true`, publishes the artifact to binary storage", "true"),
|
||||
PUBLISH_ARTIFACTS_OFFLINE: new EnvVar("If set to `true`, publishes the artifacts to local m2", "false"),
|
||||
EXTERNAL_CONTRACTS_GROUP_ID: new EnvVar("Group ID of the project with contracts", "com.example"),
|
||||
EXTERNAL_CONTRACTS_ARTIFACT_ID: new EnvVar("Artifact ID of the project with contracts", ""),
|
||||
EXTERNAL_CONTRACTS_CLASSIFIER: new EnvVar("Classifier of the project with contracts", ""),
|
||||
EXTERNAL_CONTRACTS_VERSION: new EnvVar("Version of the project with contracts. Defautls to an equivalent of picking the latest", "+"),
|
||||
EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_URL: new EnvVar("URL of your Artifact Manager. It defaults to the value of `REPO_WITH_BINARIES_URL` environment variable and if that is not set, it defaults to `http://localhost:8081/artifactory/libs-release-local`", ""),
|
||||
EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_USERNAME: new EnvVar("(optional) Username if the `EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_URL` requires authentication. It defaults to `REPO_WITH_BINARIES_USERNAME`. If that is not set, it defaults to `admin", ""),
|
||||
EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_PASSWORD: new EnvVar("(optional) Password if the `EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_URL` requires authentication. It defaults to `REPO_WITH_BINARIES_PASSWORD, If that is not set, it defaults to `password", ""),
|
||||
EXTERNAL_CONTRACTS_PATH: new EnvVar("Path to contracts for the given project, inside the project with contracts. Defaults to slash-separated `EXTERNAL_CONTRACTS_GROUP_ID` concatenated with `/` and `EXTERNAL_CONTRACTS_ARTIFACT_ID. For example,\n" +
|
||||
"for group id `cat-server-side.dog` and artifact ID `fish`, would result in `cat/dog/fish` for the contracts path.", ""),
|
||||
EXTERNAL_CONTRACTS_WORK_OFFLINE: new EnvVar("If set to `true`, retrieves the artifact with contracts from the container's `.m2`. Mount your local `.m2` as a volume available at the container's `/root/.m2` path", "false"),
|
||||
PUBLISH_STUBS_TO_SCM: new EnvVar("If set to `true` will run the task to publish stubs to scm", false),
|
||||
MESSAGING_TYPE: new EnvVar("Type of messaging. Can be either [rabbit] or [kafka].", ""),
|
||||
]
|
||||
|
||||
group = getProp(envVars, "PROJECT_GROUP") ?: 'com.example'
|
||||
version = getProp(envVars, "PROJECT_VERSION") ?: '0.0.1-SNAPSHOT'
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
@@ -29,21 +57,69 @@ repositories {
|
||||
}
|
||||
|
||||
apply plugin: 'groovy'
|
||||
apply plugin: 'io.spring.dependency-management'
|
||||
apply plugin: "io.spring.dependency-management"
|
||||
apply plugin: "org.springframework.boot"
|
||||
apply plugin: 'spring-cloud-contract'
|
||||
apply plugin: 'maven-publish'
|
||||
|
||||
dependencyManagement {
|
||||
imports {
|
||||
mavenBom "org.springframework.cloud:spring-cloud-contract-dependencies:${verifierVersion}"
|
||||
bootJar.enabled = false
|
||||
|
||||
class EnvVar {
|
||||
final Object defaultValue
|
||||
final String description
|
||||
|
||||
EnvVar(String description, Object defaultValue) {
|
||||
this.defaultValue = defaultValue
|
||||
this.description = description
|
||||
}
|
||||
|
||||
boolean equals(o) {
|
||||
if (this.is(o)) {
|
||||
return true
|
||||
}
|
||||
if (getClass() != o.class) {
|
||||
return false
|
||||
}
|
||||
EnvVar envVar = (EnvVar) o
|
||||
if (defaultValue != envVar.defaultValue) {
|
||||
return false
|
||||
}
|
||||
if (description != envVar.description) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
int hashCode() {
|
||||
int result
|
||||
result = (defaultValue != null ? defaultValue.hashCode() : 0)
|
||||
result = 31 * result + (description != null ? description.hashCode() : 0)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation(platform("org.springframework.cloud:spring-cloud-contract-dependencies:${verifierVersion}"))
|
||||
testImplementation(platform("org.apache.camel.springboot:camel-spring-boot-dependencies:${camelVersion}"))
|
||||
|
||||
testImplementation("org.springframework.boot:spring-boot-starter-web")
|
||||
testImplementation("org.springframework.cloud:spring-cloud-starter-contract-verifier")
|
||||
testImplementation("org.springframework.amqp:spring-rabbit")
|
||||
testImplementation("org.apache.camel.springboot:camel-spring-boot-starter")
|
||||
testImplementation("org.apache.camel.springboot:camel-kafka-starter")
|
||||
testImplementation("org.apache.camel.springboot:camel-rabbitmq-starter")
|
||||
if (getProp(envVars, "STANDALONE_PROTOCOL")) {
|
||||
testImplementation("org.apache.camel.springboot:camel-${getProp(envVars, "STANDALONE_PROTOCOL")}-starter")
|
||||
}
|
||||
}
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
if (getProp(envVars, "MESSAGING_TYPE") != "") {
|
||||
systemProperty("spring.profiles.active", "messagingtype")
|
||||
} else if (getProp(envVars, "STANDALONE_PROTOCOL") != "") {
|
||||
systemProperty("spring.profiles.active", "standalone")
|
||||
}
|
||||
testLogging {
|
||||
exceptionFormat = 'full'
|
||||
afterSuite { desc, result ->
|
||||
@@ -58,32 +134,33 @@ test {
|
||||
}
|
||||
|
||||
contracts {
|
||||
baseClassForTests = "contracts.RestBase"
|
||||
baseClassForTests = "contracts.ContractTestsBase"
|
||||
testMode = "EXPLICIT"
|
||||
stubsSuffix = getProp("PRODUCER_STUBS_CLASSIFIER") ?: "stubs"
|
||||
if (getProp("EXTERNAL_CONTRACTS_ARTIFACT_ID")) {
|
||||
stubsSuffix = getProp(envVars, "PRODUCER_STUBS_CLASSIFIER") ?: "stubs"
|
||||
failOnNoContracts = getProp(envVars, "FAIL_ON_NO_CONTRACTS") ?: false
|
||||
if (getProp(envVars, "EXTERNAL_CONTRACTS_ARTIFACT_ID")) {
|
||||
logger.
|
||||
lifecycle("Will use an artifact with contracts [${getProp("EXTERNAL_CONTRACTS_GROUP_ID")}:${getProp("EXTERNAL_CONTRACTS_ARTIFACT_ID")}]")
|
||||
lifecycle("Will use an artifact with contracts [${getProp(envVars, "EXTERNAL_CONTRACTS_GROUP_ID")}:${getProp(envVars, "EXTERNAL_CONTRACTS_ARTIFACT_ID")}]")
|
||||
// tests - contracts from an artifact
|
||||
contractsPath = getProp("EXTERNAL_CONTRACTS_PATH") ?: ""
|
||||
if (Boolean.parseBoolean(getProp("EXTERNAL_CONTRACTS_WORK_OFFLINE")) == false) {
|
||||
contractsPath = getProp(envVars, "EXTERNAL_CONTRACTS_PATH") ?: ""
|
||||
if (!Boolean.parseBoolean(getProp(envVars, "EXTERNAL_CONTRACTS_WORK_OFFLINE").toString())) {
|
||||
contractRepository {
|
||||
repositoryUrl = getProp('EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_URL') ?:
|
||||
getProp('REPO_WITH_BINARIES_URL') ?: 'http://localhost:8081/artifactory/libs-release-local'
|
||||
username = getProp('EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_USERNAME') ?:
|
||||
getProp('REPO_WITH_BINARIES_USERNAME') ?: 'admin'
|
||||
password = getProp('EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_PASSWORD') ?:
|
||||
getProp('REPO_WITH_BINARIES_PASSWORD') ?: 'password'
|
||||
repositoryUrl = getProp(envVars, 'EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_URL') ?:
|
||||
getProp(envVars, 'REPO_WITH_BINARIES_URL') ?: 'http://localhost:8081/artifactory/libs-release-local'
|
||||
username = getProp(envVars, 'EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_USERNAME') ?:
|
||||
getProp(envVars, 'REPO_WITH_BINARIES_USERNAME') ?: 'admin'
|
||||
password = getProp(envVars, 'EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_PASSWORD') ?:
|
||||
getProp(envVars, 'REPO_WITH_BINARIES_PASSWORD') ?: 'password'
|
||||
}
|
||||
}
|
||||
contractDependency {
|
||||
groupId = getProp("EXTERNAL_CONTRACTS_GROUP_ID") ?: "com.example"
|
||||
artifactId = getProp("EXTERNAL_CONTRACTS_ARTIFACT_ID")
|
||||
delegate.classifier = getProp("EXTERNAL_CONTRACTS_CLASSIFIER") ?: ""
|
||||
delegate.version = getProp("EXTERNAL_CONTRACTS_VERSION") ?: "+"
|
||||
groupId = getProp(envVars, "EXTERNAL_CONTRACTS_GROUP_ID") ?: "com.example"
|
||||
artifactId = getProp(envVars, "EXTERNAL_CONTRACTS_ARTIFACT_ID")
|
||||
delegate.classifier = getProp(envVars, "EXTERNAL_CONTRACTS_CLASSIFIER") ?: ""
|
||||
delegate.version = getProp(envVars, "EXTERNAL_CONTRACTS_VERSION") ?: "+"
|
||||
}
|
||||
contractsMode = Boolean.
|
||||
parseBoolean(getProp("EXTERNAL_CONTRACTS_WORK_OFFLINE")) ? "LOCAL" : "REMOTE"
|
||||
parseBoolean(getProp(envVars, "EXTERNAL_CONTRACTS_WORK_OFFLINE").toString()) ? "LOCAL" : "REMOTE"
|
||||
}
|
||||
else {
|
||||
logger.lifecycle("Will use contracts from the mounted [/contracts] folder")
|
||||
@@ -107,16 +184,15 @@ task copyOutput(type: Copy) {
|
||||
|
||||
test {
|
||||
finalizedBy("copyOutput")
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
publishing {
|
||||
repositories {
|
||||
maven {
|
||||
url getProp('REPO_WITH_BINARIES_URL') ?: 'http://localhost:8081/artifactory/libs-release-local'
|
||||
url getProp(envVars, 'REPO_WITH_BINARIES_URL') ?: 'http://localhost:8081/artifactory/libs-release-local'
|
||||
credentials {
|
||||
username getProp('REPO_WITH_BINARIES_USERNAME') ?: 'admin'
|
||||
password getProp('REPO_WITH_BINARIES_PASSWORD') ?: 'password'
|
||||
username getProp(envVars, 'REPO_WITH_BINARIES_USERNAME').toString() ?: 'admin'
|
||||
password getProp(envVars, 'REPO_WITH_BINARIES_PASSWORD').toString() ?: 'password'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -125,8 +201,8 @@ publishing {
|
||||
}
|
||||
|
||||
// explicitly disable artifacts publication
|
||||
boolean publishEnabled = Boolean.parseBoolean(getProp("PUBLISH_ARTIFACTS") ?: "true")
|
||||
boolean publishOffline = Boolean.parseBoolean(getProp("PUBLISH_ARTIFACTS_OFFLINE") ?: "false")
|
||||
boolean publishEnabled = Boolean.parseBoolean(getProp(envVars, "PUBLISH_ARTIFACTS").toString() ?: "true")
|
||||
boolean publishOffline = Boolean.parseBoolean(getProp(envVars, "PUBLISH_ARTIFACTS_OFFLINE").toString() ?: "false")
|
||||
publish.setEnabled(publishEnabled)
|
||||
publishToMavenLocal.setEnabled(publishOffline)
|
||||
|
||||
@@ -138,14 +214,17 @@ gradle.taskGraph.whenReady { graph ->
|
||||
findAll { it.name.startsWith("publish") && it.name.endsWith("ToMavenLocal") }*.setEnabled(publishOffline)
|
||||
}
|
||||
|
||||
if (Boolean.parseBoolean(getProp("PUBLISH_STUBS_TO_SCM"))) {
|
||||
if (Boolean.parseBoolean(getProp(envVars, "PUBLISH_STUBS_TO_SCM").toString())) {
|
||||
publish.dependsOn("publishStubsToScm")
|
||||
}
|
||||
|
||||
String getProp(String propName) {
|
||||
Object getProp(Map<String, EnvVar> envVars, String propName) {
|
||||
if (!envVars.containsKey(propName)) {
|
||||
throw new IllegalStateException("You've referenced a property with name [${propName}] but it's not in the list of accepatble props ${envVars.keySet()}")
|
||||
}
|
||||
return hasProperty(propName) ?
|
||||
(getProperty(propName) ?: System.properties[propName]) : System.properties[propName] ?:
|
||||
System.getenv(propName)
|
||||
System.getenv(propName) ?: envVars.get(propName)?.defaultValue
|
||||
}
|
||||
|
||||
task resolveDependencies {
|
||||
@@ -157,8 +236,27 @@ task resolveDependencies {
|
||||
config.files
|
||||
}
|
||||
catch (e) {
|
||||
project.logger.info e.message // some cannot be resolved, silentlyish skip them
|
||||
project.logger.info e.message // some cannot be resolved, silently skip them
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task dumpAllProps() {
|
||||
doLast {
|
||||
// TODO: Parse the java code for env vars
|
||||
File output = new File("build", "props.adoc")
|
||||
if (!output.exists()) {
|
||||
output.parentFile.mkdirs()
|
||||
output.createNewFile()
|
||||
}
|
||||
String table = """\
|
||||
.Docker environment variables
|
||||
|===
|
||||
|Name | Description | Default
|
||||
"""
|
||||
output.text = table + envVars.sort().collect { '|' + it.key + '|' + it.value.description + '|' + it.value.defaultValue }.join("\n") + "\n|==="
|
||||
|
||||
new DocsFromSources(project).buildApplicationEnvVars()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
repositories {
|
||||
mavenLocal()
|
||||
mavenCentral()
|
||||
maven { url "https://repo.spring.io/snapshot" }
|
||||
maven { url "https://repo.spring.io/milestone" }
|
||||
maven { url "https://repo.spring.io/release" }
|
||||
}
|
||||
|
||||
ext {
|
||||
roasterVersion = "2.21.2.Final"
|
||||
junit5Version = "5.6.2"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation "org.jboss.forge.roaster:roaster-api:${roasterVersion}"
|
||||
implementation "org.jboss.forge.roaster:roaster-jdt:${roasterVersion}"
|
||||
}
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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 contracts;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileVisitResult;
|
||||
import java.nio.file.FileVisitor;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.SimpleFileVisitor;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
import org.jboss.forge.roaster.Roaster;
|
||||
import org.jboss.forge.roaster.model.JavaUnit;
|
||||
import org.jboss.forge.roaster.model.source.AnnotationSource;
|
||||
import org.jboss.forge.roaster.model.source.FieldSource;
|
||||
import org.jboss.forge.roaster.model.source.JavaClassSource;
|
||||
import org.jboss.forge.roaster.model.source.JavaDocSource;
|
||||
|
||||
public class DocsFromSources {
|
||||
|
||||
private static final String ADOC_HEADER =
|
||||
".Docker environment variables - read at runtime\n"
|
||||
+ "|===\n"
|
||||
+ "|Name | Description | Default\n";
|
||||
|
||||
private final Project project;
|
||||
|
||||
public DocsFromSources(Project project) {
|
||||
this.project = project;
|
||||
}
|
||||
|
||||
public void buildApplicationEnvVars() {
|
||||
Path path = new File(rootDir(), sourcePath()).toPath();
|
||||
List<EnvVar> envVars = new ArrayList<>();
|
||||
FileVisitor<Path> fv = new SimpleFileVisitor<Path>() {
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
|
||||
throws IOException {
|
||||
if (!file.toString().endsWith(".java")) {
|
||||
info("Skipping [" + file.toString() + "]");
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
JavaUnit unit = Roaster.parseUnit(Files.newInputStream(file));
|
||||
JavaClassSource myClass = unit.getGoverningType();
|
||||
info("Checking [" + myClass.getName() + "]");
|
||||
List<FieldSource<JavaClassSource>> fields = myClass.getFields();
|
||||
for (FieldSource<JavaClassSource> field : fields) {
|
||||
List<AnnotationSource<JavaClassSource>> annotations = field.getAnnotations();
|
||||
for (AnnotationSource<JavaClassSource> annotation : annotations) {
|
||||
if ("org.springframework.beans.factory.annotation.Value".equals(annotation.getQualifiedName())) {
|
||||
info("Field [" + field.getName() + "] has @Value annotation");
|
||||
JavaDocSource<FieldSource<JavaClassSource>> javaDoc = field.getJavaDoc();
|
||||
String description = javaDoc.getFullText();
|
||||
// ${foo:asd}
|
||||
String annotationValue = annotation.getStringValue();
|
||||
// foo:asd
|
||||
annotationValue = annotationValue.substring(2, annotationValue.length() - 1);
|
||||
String[] parsed = annotationValue.split(":");
|
||||
String defaultValue = "";
|
||||
String name = parsed[0];
|
||||
if (parsed.length == 2) {
|
||||
defaultValue = parsed[1];
|
||||
}
|
||||
envVars.add(new EnvVar(name, description, defaultValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
info("Found [" + envVars.size() + "] env var field entries");
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
Files.walkFileTree(path, fv);
|
||||
Path output = new File(rootDir(), "build/appProps.adoc").toPath();
|
||||
StringBuilder stringBuilder = new StringBuilder().append(ADOC_HEADER);
|
||||
Collections.sort(envVars);
|
||||
envVars.forEach(envVar -> stringBuilder.append(envVar.toString()).append("\n"));
|
||||
stringBuilder.append("|===");
|
||||
Files.write(output, stringBuilder.toString().getBytes());
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
String sourcePath() {
|
||||
return "src/test/java/contracts";
|
||||
}
|
||||
|
||||
File rootDir() {
|
||||
return project.getRootDir();
|
||||
}
|
||||
|
||||
void info(String log) {
|
||||
this.project.getLogger().info(log);
|
||||
}
|
||||
}
|
||||
|
||||
class EnvVar implements Comparable<EnvVar> {
|
||||
final String name;
|
||||
final String description;
|
||||
final String defaultValue;
|
||||
|
||||
EnvVar(String name, String description, String defaultValue) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.defaultValue = defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
EnvVar envVar = (EnvVar) o;
|
||||
return Objects.equals(name, envVar.name) &&
|
||||
Objects.equals(description, envVar.description) &&
|
||||
Objects.equals(defaultValue, envVar.defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name, description, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(EnvVar o) {
|
||||
return name.compareTo(o.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "|" + name + "|" + description + "|" + defaultValue;
|
||||
}
|
||||
}
|
||||
@@ -1,2 +1,4 @@
|
||||
org.gradle.daemon=false
|
||||
verifierVersion=3.0.0-SNAPSHOT
|
||||
springBootVersion=2.4.0-SNAPSHOT
|
||||
camelVersion=3.4.3
|
||||
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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 contracts;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.TestInfo;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.web.client.RestTemplateBuilder;
|
||||
import org.springframework.cloud.contract.verifier.converter.YamlContract;
|
||||
import org.springframework.cloud.contract.verifier.messaging.MessageVerifier;
|
||||
import org.springframework.cloud.contract.verifier.messaging.amqp.AmqpMetadata;
|
||||
import org.springframework.cloud.contract.verifier.messaging.boot.AutoConfigureMessageVerifier;
|
||||
import org.springframework.cloud.contract.verifier.messaging.camel.StandaloneMetadata;
|
||||
import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessageMetadata;
|
||||
import org.springframework.cloud.contract.verifier.util.ContractVerifierUtil;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
@SpringBootTest(classes = ContractTestsBase.Config.class, webEnvironment = SpringBootTest.WebEnvironment.NONE)
|
||||
@AutoConfigureMessageVerifier
|
||||
public abstract class ContractTestsBase {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ContractTestsBase.class);
|
||||
|
||||
/**
|
||||
* URL at which the application is running.
|
||||
*/
|
||||
@Value("${APPLICATION_BASE_URL}")
|
||||
String url;
|
||||
|
||||
/**
|
||||
* Optional username to access the application.
|
||||
*/
|
||||
@Value("${APPLICATION_USERNAME:}")
|
||||
String username;
|
||||
|
||||
/**
|
||||
* Optional password to access the application.
|
||||
*/
|
||||
@Value("${APPLICATION_PASSWORD:}")
|
||||
String password;
|
||||
|
||||
/**
|
||||
* Timeout to connect to the application to trigger a message.
|
||||
*/
|
||||
@Value("${MESSAGING_TRIGGER_CONNECT_TIMEOUT:5000}")
|
||||
Integer connectTimeout;
|
||||
|
||||
/**
|
||||
* Timeout to read the response from the application to trigger a message.
|
||||
*/
|
||||
@Value("${MESSAGING_TRIGGER_READ_TIMEOUT:5000}")
|
||||
Integer readTimeout;
|
||||
|
||||
/**
|
||||
* Defines the messaging type when dealing with message based contracts.
|
||||
*/
|
||||
@Value("${MESSAGING_TYPE:}")
|
||||
String messagingType;
|
||||
|
||||
@Autowired
|
||||
MessageVerifier messageVerifier;
|
||||
|
||||
@BeforeEach
|
||||
public void setup(TestInfo testInfo) {
|
||||
RestAssured.baseURI = this.url;
|
||||
if (StringUtils.hasText(this.username)) {
|
||||
RestAssured.authentication = RestAssured.basic(this.username, this.password);
|
||||
}
|
||||
setupMessagingFromContract(testInfo);
|
||||
}
|
||||
|
||||
private void setupMessagingFromContract(TestInfo testInfo) {
|
||||
try {
|
||||
YamlContract contract = ContractVerifierUtil.contract(this, testInfo.getDisplayName());
|
||||
setupMessagingIfPresent(contract);
|
||||
} catch (Exception e) {
|
||||
log.warn("An exception occurred while trying to setup messaging from contract", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupMessagingIfPresent(YamlContract contract) {
|
||||
if (contract.input == null && contract.outputMessage == null) {
|
||||
return;
|
||||
}
|
||||
setupAmqpIfPresent(contract);
|
||||
setupStandaloneIfPresent(contract);
|
||||
}
|
||||
|
||||
private void setupAmqpIfPresent(YamlContract contract) {
|
||||
AmqpMetadata amqpMetadata = AmqpMetadata.fromMetadata(contract.metadata);
|
||||
if (isMessagingType("rabbit") && hasDeclaredOutputQueue(amqpMetadata) || isMessagingType("kafka")) {
|
||||
log.info("First will try to receive a message to setup the connection with the broker");
|
||||
if (contract.input != null && StringUtils.hasText(contract.input.messageFrom)) {
|
||||
setupConnection(contract.input.messageFrom, contract);
|
||||
}
|
||||
if (contract.outputMessage != null && StringUtils.hasText(contract.outputMessage.sentTo)){
|
||||
setupConnection(contract.outputMessage.sentTo, contract);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setupStandaloneIfPresent(YamlContract contract) {
|
||||
StandaloneMetadata metadata = StandaloneMetadata.fromMetadata(contract.metadata);
|
||||
if (StringUtils.hasText(metadata.getSetup().getOptions())) {
|
||||
log.info("First will try to receive a message to setup the connection with the broker");
|
||||
setMessageType(contract, ContractVerifierMessageMetadata.MessageType.SETUP);
|
||||
setupConnection(metadata.getSetup().getOptions(), contract);
|
||||
}
|
||||
}
|
||||
|
||||
private void setMessageType(YamlContract contract,
|
||||
ContractVerifierMessageMetadata.MessageType output) {
|
||||
contract.metadata.put(ContractVerifierMessageMetadata.METADATA_KEY,
|
||||
new ContractVerifierMessageMetadata(output));
|
||||
}
|
||||
|
||||
private void setupConnection(String destination, YamlContract contract) {
|
||||
if (StringUtils.isEmpty(destination)) {
|
||||
return;
|
||||
}
|
||||
log.info("Setting up destination [{}]", destination);
|
||||
this.messageVerifier.receive(destination, 100, TimeUnit.MILLISECONDS, contract);
|
||||
}
|
||||
|
||||
private boolean hasDeclaredOutputQueue(AmqpMetadata amqpMetadata) {
|
||||
return StringUtils.hasText(amqpMetadata.getOutputMessage().getConnectToBroker().getDeclareQueueWithName());
|
||||
}
|
||||
|
||||
private boolean isMessagingType(String rabbit) {
|
||||
return rabbit.equalsIgnoreCase(this.messagingType);
|
||||
}
|
||||
|
||||
public void triggerMessage(String label) {
|
||||
String url = this.url + "/springcloudcontract/" + label;
|
||||
log.info("Will send a request to [{}] in order to trigger a message", url);
|
||||
restTemplate().postForObject(url, "", String.class);
|
||||
}
|
||||
|
||||
private RestTemplate restTemplate() {
|
||||
RestTemplateBuilder builder = new RestTemplateBuilder()
|
||||
.setConnectTimeout(Duration.ofMillis(this.connectTimeout))
|
||||
.setReadTimeout(Duration.ofMillis(this.readTimeout));
|
||||
if (StringUtils.hasText(this.username)) {
|
||||
builder = builder.basicAuthentication(this.username, this.password);
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import(MessagingAutoConfig.class)
|
||||
@EnableAutoConfiguration
|
||||
protected static class Config {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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 contracts;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.camel.ConsumerTemplate;
|
||||
import org.apache.camel.Exchange;
|
||||
import org.apache.camel.Message;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.amqp.core.MessageProperties;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.cloud.contract.verifier.converter.YamlContract;
|
||||
import org.springframework.cloud.contract.verifier.messaging.MessageVerifier;
|
||||
import org.springframework.cloud.contract.verifier.messaging.amqp.AmqpMetadata;
|
||||
import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessage;
|
||||
import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessageMetadata;
|
||||
import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessaging;
|
||||
import org.springframework.cloud.contract.verifier.messaging.kafka.KafkaMetadata;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnProperty("MESSAGING_TYPE")
|
||||
@Profile("messagingtype")
|
||||
public class MessagingAutoConfig {
|
||||
|
||||
/**
|
||||
* Type of messaging. Can be either [rabbit] or [kafka].
|
||||
*/
|
||||
@Value("${MESSAGING_TYPE:}")
|
||||
String messagingType;
|
||||
|
||||
/**
|
||||
* For RabbitMQ - brokers addresses.
|
||||
*/
|
||||
@Value("${SPRING_RABBITMQ_ADDRESSES:}")
|
||||
String springRabbitmqAddresses;
|
||||
|
||||
/**
|
||||
* For Kafka - brokers addresses.
|
||||
*/
|
||||
@Value("${SPRING_KAFKA_BOOTSTRAP_SERVERS:}")
|
||||
String springKafkaBootstrapServers;
|
||||
|
||||
@Bean
|
||||
public ContractVerifierMessaging<Message> contractVerifierMessaging(
|
||||
MessageVerifier<Message> exchange) {
|
||||
return new ContractVerifierCamelHelper(exchange);
|
||||
}
|
||||
|
||||
@Bean
|
||||
MessageVerifier<Message> manualMessageVerifier(ConsumerTemplate consumerTemplate) {
|
||||
return new MessageVerifier<Message>() {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(MessageVerifier.class);
|
||||
|
||||
@Override
|
||||
public Message receive(String destination, long timeout, TimeUnit timeUnit, YamlContract yamlContract) {
|
||||
String uri = messagingType() + "://" + destination + additionalOptions(yamlContract);
|
||||
log.info("Camel URI [{}]", uri);
|
||||
Exchange exchange = consumerTemplate.receive(uri, timeUnit.toMillis(timeout));
|
||||
if (exchange == null) {
|
||||
return null;
|
||||
}
|
||||
return exchange.getMessage();
|
||||
}
|
||||
|
||||
private String messagingType() {
|
||||
if (messagingType.equalsIgnoreCase("kafka")) {
|
||||
return "kafka";
|
||||
}
|
||||
return "rabbitmq";
|
||||
}
|
||||
|
||||
private String additionalOptions(YamlContract contract) {
|
||||
if (contract == null) {
|
||||
return "";
|
||||
}
|
||||
if (messagingType.equalsIgnoreCase("kafka")) {
|
||||
return setKafkaOpts(contract);
|
||||
}
|
||||
return setRabbitOpts(contract);
|
||||
}
|
||||
|
||||
private String setKafkaOpts(YamlContract contract) {
|
||||
String opts = defaultOpts(contract);
|
||||
KafkaMetadata metadata = KafkaMetadata.fromMetadata(contract.metadata);
|
||||
ContractVerifierMessageMetadata messageMetadata = ContractVerifierMessageMetadata.fromMetadata(contract.metadata);
|
||||
if (inputMessage(messageMetadata) && StringUtils.hasText(metadata.getInput().getConnectToBroker().getAdditionalOptions())) {
|
||||
return opts + "&" + metadata.getInput().getConnectToBroker().getAdditionalOptions();
|
||||
}
|
||||
else if (StringUtils.hasText(metadata.getOutputMessage().getConnectToBroker().getAdditionalOptions())) {
|
||||
return opts + "&" + metadata.getOutputMessage().getConnectToBroker().getAdditionalOptions();
|
||||
}
|
||||
return opts;
|
||||
}
|
||||
|
||||
private String defaultOpts(YamlContract contract) {
|
||||
String consumerGroup = sameConsumerGroupForSameContract(contract);
|
||||
return "?brokers=" + getRequiredProperty("SPRING_KAFKA_BOOTSTRAP_SERVERS", springKafkaBootstrapServers) + "&autoOffsetReset=latest&groupId=" + consumerGroup + "&shutdownTimeout=5";
|
||||
}
|
||||
|
||||
private String sameConsumerGroupForSameContract(YamlContract contract) {
|
||||
return contract.input.hashCode() + "_" + contract.outputMessage.hashCode();
|
||||
}
|
||||
|
||||
private String setRabbitOpts(YamlContract contract) {
|
||||
String opts = "?addresses=" + getRequiredProperty("SPRING_RABBITMQ_ADDRESSES", springRabbitmqAddresses);
|
||||
AmqpMetadata metadata = AmqpMetadata.fromMetadata(contract.metadata);
|
||||
ContractVerifierMessageMetadata messageMetadata = ContractVerifierMessageMetadata.fromMetadata(contract.metadata);
|
||||
if (inputMessage(messageMetadata) && StringUtils.hasText(metadata.getInput().getConnectToBroker().getAdditionalOptions())) {
|
||||
return opts + "&" + metadata.getInput().getConnectToBroker().getAdditionalOptions();
|
||||
}
|
||||
else if (StringUtils.hasText(metadata.getOutputMessage().getConnectToBroker().getAdditionalOptions())) {
|
||||
return opts + "&" + metadata.getOutputMessage().getConnectToBroker().getAdditionalOptions();
|
||||
}
|
||||
return defaultOpts(opts, metadata, messageMetadata);
|
||||
}
|
||||
|
||||
private String getRequiredProperty(String name, String value) {
|
||||
if (StringUtils.isEmpty(value)) {
|
||||
throw new IllegalStateException("The property [" + name + "] must not be empty!");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private boolean inputMessage(ContractVerifierMessageMetadata messageMetadata) {
|
||||
return messageMetadata.getMessageType() == ContractVerifierMessageMetadata.MessageType.INPUT;
|
||||
}
|
||||
|
||||
private String defaultOpts(String opts, AmqpMetadata amqpMetadata, ContractVerifierMessageMetadata messageMetadata) {
|
||||
AmqpMetadata.ConnectToBroker connectToBroker = inputMessage(messageMetadata) ? amqpMetadata.getInput().getConnectToBroker() : amqpMetadata.getOutputMessage().getConnectToBroker();
|
||||
MessageProperties messageProperties = inputMessage(messageMetadata) ? amqpMetadata.getInput().getMessageProperties() : amqpMetadata.getOutputMessage().getMessageProperties();
|
||||
if (StringUtils.hasText(connectToBroker.getDeclareQueueWithName())) {
|
||||
opts = opts + "&queue=" + connectToBroker.getDeclareQueueWithName();
|
||||
}
|
||||
if (messageProperties != null && StringUtils.hasText(messageProperties.getReceivedRoutingKey())) {
|
||||
opts = opts + "&routingKey=" + messageProperties.getReceivedRoutingKey();
|
||||
}
|
||||
return opts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message receive(String destination, YamlContract yamlContract) {
|
||||
return receive(destination, 5, TimeUnit.SECONDS, yamlContract);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Message message, String destination, YamlContract yamlContract) {
|
||||
throw new UnsupportedOperationException("Currently supports only receiving");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Object payload, Map headers, String destination, YamlContract yamlContract) {
|
||||
throw new UnsupportedOperationException("Currently supports only receiving");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ContractVerifierCamelHelper extends ContractVerifierMessaging<Message> {
|
||||
|
||||
ContractVerifierCamelHelper(MessageVerifier<Message> exchange) {
|
||||
super(exchange);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ContractVerifierMessage convert(Message receive) {
|
||||
if (receive == null) {
|
||||
return null;
|
||||
}
|
||||
return new ContractVerifierMessage(receive.getBody(), receive.getHeaders());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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 contracts;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
@SpringBootTest(classes = RestBase.Config.class, webEnvironment = SpringBootTest.WebEnvironment.NONE)
|
||||
public abstract class RestBase {
|
||||
|
||||
@Value("${APPLICATION_BASE_URL}")
|
||||
String url;
|
||||
|
||||
@Value("${APPLICATION_USERNAME:}")
|
||||
String username;
|
||||
|
||||
@Value("${APPLICATION_PASSWORD:}")
|
||||
String password;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
RestAssured.baseURI = this.url;
|
||||
if (StringUtils.hasText(this.username)) {
|
||||
RestAssured.authentication = RestAssured.basic(this.username, this.password);
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
protected static class Config {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
# Auto Configuration
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
contracts.MessagingAutoConfig
|
||||
@@ -0,0 +1 @@
|
||||
stubrunner.camel.enabled: false
|
||||
Reference in New Issue
Block a user