Skip to content
This repository has been archived by the owner on May 16, 2023. It is now read-only.

Commit

Permalink
Feature/enrich app config (#726)
Browse files Browse the repository at this point in the history
* Added supported countries to app config with application.yaml parameter

* Fixed Test failures

* Remove unused code

* Added app version parameters to application.yaml

* Added tests for app version parameters

* Refacted country list implementation

Co-authored-by: Hilmar Falkenberg <hilmar.falkenberg@sap.com>
  • Loading branch information
KevponSAP and hilmarf authored Aug 25, 2020
1 parent db18b68 commit 5e81409
Show file tree
Hide file tree
Showing 17 changed files with 238 additions and 158 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,6 @@ message ApplicationConfiguration {
app.coronawarn.server.common.protocols.internal.ApplicationVersionConfiguration appVersion = 5;

app.coronawarn.server.common.protocols.internal.AppFeatures appFeatures = 6;

repeated string supportedCountries = 7;
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,17 @@
import app.coronawarn.server.common.protocols.internal.AppFeatures;
import app.coronawarn.server.common.protocols.internal.ApplicationConfiguration;
import app.coronawarn.server.common.protocols.internal.ApplicationConfiguration.Builder;
import app.coronawarn.server.common.protocols.internal.ApplicationVersionConfiguration;
import app.coronawarn.server.common.protocols.internal.ApplicationVersionInfo;
import app.coronawarn.server.common.protocols.internal.SemanticVersion;
import app.coronawarn.server.services.distribution.config.DistributionServiceConfig;
import app.coronawarn.server.services.distribution.config.DistributionServiceConfig.AppVersions;
import java.util.List;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;



/**
* Provides the application configuration needed for the mobile client. Contains all necessary sub-configs, including:
* <ul>
Expand Down Expand Up @@ -54,9 +61,47 @@ public class ApplicationConfigurationPublicationConfig {
@Bean
public ApplicationConfiguration createMasterConfiguration(DistributionServiceConfig distributionServiceConfig)
throws UnableToLoadFileException {

return YamlLoader.loadYamlIntoProtobufBuilder(MASTER_FILE, Builder.class)
.setAppFeatures(
AppFeatures.newBuilder().addAllAppFeatures(distributionServiceConfig.getAppFeaturesProto()).build())
AppFeatures.newBuilder().addAllAppFeatures(distributionServiceConfig.getAppFeaturesProto()).build()
)
.addAllSupportedCountries(List.of(distributionServiceConfig.getSupportedCountries()))
.setAppVersion(buildApplicationVersionConfiguration(distributionServiceConfig))
.build();
}

/**
* Fetches the master configuration as a ApplicationConfiguration instance.
*
* @return test.
*/
public ApplicationVersionConfiguration buildApplicationVersionConfiguration(
DistributionServiceConfig distributionServiceConfig) {
AppVersions appVersions = distributionServiceConfig.getAppVersions();
return ApplicationVersionConfiguration.newBuilder()
.setAndroid(buildApplicationVersionInfo(appVersions.getLatestAndroid(), appVersions.getMinAndroid()))
.setIos(buildApplicationVersionInfo(appVersions.getLatestIos(), appVersions.getMinIos()))
.build();
}

private ApplicationVersionInfo buildApplicationVersionInfo(String latestVersion, String minVersion) {
return ApplicationVersionInfo.newBuilder()
.setLatest(buildSemanticVersion(latestVersion))
.setMin(buildSemanticVersion(minVersion))
.build();
}

private SemanticVersion buildSemanticVersion(String version) {
return SemanticVersion.newBuilder()
.setMajor(getSemanticVersionNumber(version, 0))
.setMinor(getSemanticVersionNumber(version, 1))
.setPatch(getSemanticVersionNumber(version, 2))
.build();
}

private int getSemanticVersionNumber(String version, int position) {
String[] items = version.split("\\.");
return Integer.valueOf(items[position]);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
package app.coronawarn.server.services.distribution.config;

import app.coronawarn.server.common.protocols.external.exposurenotification.SignatureInfo;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import javax.validation.constraints.Max;
Expand All @@ -47,6 +49,7 @@ public class DistributionServiceConfig {
private static final String ALGORITHM_OID_REGEX = "^[0-9]+[\\.[0-9]+]*$";
private static final String BUNDLE_REGEX = "^[a-z-]+[\\.[a-z-]+]*$";
private static final String PRIVATE_KEY_REGEX = "^(classpath:|file:[/]+)[a-zA-Z0-9_-]+[/[a-zA-Z0-9_-]+]*(.pem)?$";
private static final String SUPPORTED_COUNTRY_CODES_REGEX = "^([a-zA-Z]{2}(\\,*[a-zA-Z]{2})*)$";

private Paths paths;
private TestData testData;
Expand All @@ -71,6 +74,9 @@ public class DistributionServiceConfig {
private Api api;
private ObjectStore objectStore;
private List<AppFeature> appFeatures;
@Pattern(regexp = SUPPORTED_COUNTRY_CODES_REGEX)
private String supportedCountries;
private AppVersions appVersions;

public Paths getPaths() {
return paths;
Expand Down Expand Up @@ -185,8 +191,26 @@ public void setAppFeatures(List<AppFeature> appFeatures) {
this.appFeatures = appFeatures;
}

public String[] getSupportedCountries() {
return supportedCountries.split(",");
}

public void setSupportedCountries(String supportedCountries) {
this.supportedCountries = supportedCountries;
}

public AppVersions getAppVersions() {
return appVersions;
}

public void setAppVersions(AppVersions appVersions) {
this.appVersions = appVersions;
}


/**
* Get app features as list of protobuf objects.
*
* @return list of {@link app.coronawarn.server.common.protocols.internal.AppFeature}
*/
public List<app.coronawarn.server.common.protocols.internal.AppFeature> getAppFeaturesProto() {
Expand Down Expand Up @@ -583,4 +607,46 @@ public void setValue(Integer value) {
this.value = value;
}
}

public static class AppVersions {

private String latestIos;
private String minIos;
private String latestAndroid;
private String minAndroid;


public String getLatestIos() {
return latestIos;
}

public void setLatestIos(String latestIos) {
this.latestIos = latestIos;
}

public String getMinIos() {
return minIos;
}

public void setMinIos(String minIos) {
this.minIos = minIos;
}

public String getLatestAndroid() {
return latestAndroid;
}

public void setLatestAndroid(String latestAndroid) {
this.latestAndroid = latestAndroid;
}

public String getMinAndroid() {
return minAndroid;
}

public void setMinAndroid(String minAndroid) {
this.minAndroid = minAndroid;
}

}
}
11 changes: 9 additions & 2 deletions services/distribution/src/main/resources/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,14 @@ services:
force-update-keyfiles: ${FORCE_UPDATE_KEYFILES:false}

app-features:
- label: isPlausibleDeniabilityActive
value: ${PLAUSIBLE_DENIABILITY_ACTIVE:1}
- label: reserved
value: ${reserved:1}
supported-countries: ${SUPPORTED_COUNTRIES:DE}
app-versions:
latest-ios: ${LATEST_IOS_VERSION:0.8.2}
min-ios: ${MIN_IOS_VERSION:0.5.0}
latest-android: ${LATEST_IOS_VERSION:1.0.4}
min-android: ${MIN_ANDROID_VERSION:1.0.4}

spring:
main:
Expand All @@ -98,6 +104,7 @@ spring:

datasource:
driver-class-name: org.postgresql.Driver

url: jdbc:postgresql://${POSTGRESQL_SERVICE_HOST}:${POSTGRESQL_SERVICE_PORT}/${POSTGRESQL_DATABASE}?ssl=true&sslmode=verify-full&sslrootcert=${SSL_POSTGRES_CERTIFICATE_PATH}&sslcert=${SSL_DISTRIBUTION_CERTIFICATE_PATH}&sslkey=${SSL_DISTRIBUTION_PRIVATE_KEY_PATH}
username: ${POSTGRESQL_USER_DISTRIBUTION:local_setup_distribution}
password: ${POSTGRESQL_PASSWORD_DISTRIBUTION:local_setup_distribution}
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,3 @@ min-risk-score: 11
attenuation-duration: !include attenuation-duration.yaml
risk-score-classes: !include risk-score-classification.yaml
exposure-config: !include exposure-config.yaml
app-version: !include app-version-config.yaml

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -26,36 +26,128 @@
import static org.assertj.core.api.Assertions.assertThat;

import app.coronawarn.server.common.protocols.internal.ApplicationVersionConfiguration;
import app.coronawarn.server.services.distribution.assembly.appconfig.UnableToLoadFileException;
import app.coronawarn.server.services.distribution.assembly.appconfig.YamlLoader;
import app.coronawarn.server.services.distribution.assembly.appconfig.ApplicationConfigurationPublicationConfig;
import app.coronawarn.server.services.distribution.assembly.appconfig.validation.ValidationError.ErrorType;
import app.coronawarn.server.services.distribution.config.DistributionServiceConfig;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.context.ConfigFileApplicationContextInitializer;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.util.stream.Stream;

@EnableConfigurationProperties(value = DistributionServiceConfig.class)
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {DistributionServiceConfig.class,ApplicationConfigurationPublicationConfig.class},
initializers = ConfigFileApplicationContextInitializer.class)

class ApplicationVersionConfigurationValidatorTest {

private static final ValidationResult SUCCESS = new ValidationResult();

@Test
void succeedsIfLatestEqualsMin() throws UnableToLoadFileException {
var validator = buildValidator("app-version/latest-equals-min.yaml");
private ConfigurationValidator buildValidator(DistributionServiceConfig distributionServiceConfig) {
ApplicationVersionConfiguration appConfig = applicationConfigurationPublicationConfig
.buildApplicationVersionConfiguration(distributionServiceConfig);
return new ApplicationVersionConfigurationValidator(appConfig);
}

@Autowired
DistributionServiceConfig distributionServiceConfig;

@Autowired
ApplicationConfigurationPublicationConfig applicationConfigurationPublicationConfig;

@ParameterizedTest
@MethodSource("setSemanticVersionsLatestHigherThanMin")
void succeedsIfLatestHigherThanMin(String latestAndroid, String minAndroid, String latestIos, String minIos) {
distributionServiceConfig.getAppVersions().setLatestAndroid(latestAndroid);
distributionServiceConfig.getAppVersions().setMinAndroid(minAndroid);
distributionServiceConfig.getAppVersions().setLatestIos(latestIos);
distributionServiceConfig.getAppVersions().setMinIos(minIos);

var validator = buildValidator(distributionServiceConfig);
assertThat(validator.validate()).isEqualTo(SUCCESS);
}
private static Stream<Arguments> setSemanticVersionsLatestHigherThanMin() {
return Stream.of(
Arguments.of("2.0.0", "1.0.0", "1.0.0", "1.0.0"),
Arguments.of("0.2.0", "0.1.0", "1.0.0", "1.0.0"),
Arguments.of("0.0.2", "0.0.1", "1.0.0", "1.0.0"),
Arguments.of("1.0.0", "1.0.0", "2.0.0", "1.0.0"),
Arguments.of("1.0.0", "1.0.0", "0.2.0", "0.1.0"),
Arguments.of("1.0.0", "1.0.0", "0.0.2", "0.0.1")
);
}

@ParameterizedTest
@MethodSource("setSemanticVersionsLatestEqualsMin")
void succeedsWithEqualSemanticVersion(String latestAndroid, String minAndroid, String latestIos, String minIos) {

@Test
void succeedsIfLatestHigherThanMin() throws UnableToLoadFileException {
var validator = buildValidator("app-version/latest-higher-than-min.yaml");
distributionServiceConfig.getAppVersions().setLatestAndroid(latestAndroid);
distributionServiceConfig.getAppVersions().setMinAndroid(minAndroid);
distributionServiceConfig.getAppVersions().setLatestIos(latestIos);
distributionServiceConfig.getAppVersions().setMinIos(minIos);

var validator = buildValidator(distributionServiceConfig);
assertThat(validator.validate()).isEqualTo(SUCCESS);
}

@Test
void failsIfLatestLowerThanMin() throws UnableToLoadFileException {
var validator = buildValidator("app-version/latest-lower-than-min.yaml");
assertThat(validator.validate()).isEqualTo(
buildExpectedResult(buildError(CONFIG_PREFIX + "ios.[latest|min]", "1.2.2", ErrorType.MIN_GREATER_THAN_MAX)));
private static Stream<Arguments> setSemanticVersionsLatestEqualsMin() {
return Stream.of(
Arguments.of("1.0.0", "1.0.0", "1.0.0", "1.0.0"),
Arguments.of("0.1.0", "0.1.0", "1.0.0", "1.0.0"),
Arguments.of("0.0.1", "0.0.1", "1.0.0", "1.0.0"),
Arguments.of("1.0.0", "1.0.0", "1.0.0", "1.0.0"),
Arguments.of("1.0.0", "1.0.0", "0.1.0", "0.1.0"),
Arguments.of("1.0.0", "1.0.0", "0.0.1", "0.0.1")
);
}

@ParameterizedTest
@MethodSource("setSemanticVersionsLatestLowerThanMinAndroid")
void failsWithBadSemanticVersionAndroid(String latestAndroid, String minAndroid, String latestIos, String minIos) {

distributionServiceConfig.getAppVersions().setLatestAndroid(latestAndroid);
distributionServiceConfig.getAppVersions().setMinAndroid(minAndroid);
distributionServiceConfig.getAppVersions().setLatestIos(latestIos);
distributionServiceConfig.getAppVersions().setMinIos(minIos);

var validator = buildValidator(distributionServiceConfig);

assertThat(validator.validate()).isEqualTo(buildExpectedResult(buildError(CONFIG_PREFIX + "android.[latest|min]", minAndroid, ErrorType.MIN_GREATER_THAN_MAX)));
}
private static Stream<Arguments> setSemanticVersionsLatestLowerThanMinAndroid() {
return Stream.of(
Arguments.of("1.0.0", "2.0.0", "1.0.0", "1.0.0"),
Arguments.of("1.0.0", "1.1.0", "1.0.0", "1.0.0"),
Arguments.of("1.0.0", "1.0.1", "1.0.0", "1.0.0")
);
}

@ParameterizedTest
@MethodSource("setSemanticVersionsLatestLowerThanMinIos")
void failsWithBadSemanticVersionIos(String latestAndroid, String minAndroid, String latestIos, String minIos) {

distributionServiceConfig.getAppVersions().setLatestAndroid(latestAndroid);
distributionServiceConfig.getAppVersions().setMinAndroid(minAndroid);
distributionServiceConfig.getAppVersions().setLatestIos(latestIos);
distributionServiceConfig.getAppVersions().setMinIos(minIos);

var validator = buildValidator(distributionServiceConfig);

assertThat(validator.validate()).isEqualTo(buildExpectedResult(buildError(CONFIG_PREFIX + "ios.[latest|min]", minIos, ErrorType.MIN_GREATER_THAN_MAX)));
}
private static Stream<Arguments> setSemanticVersionsLatestLowerThanMinIos() {
return Stream.of(

private ConfigurationValidator buildValidator(String filePath) throws UnableToLoadFileException {
var configBuilder = YamlLoader.loadYamlIntoProtobufBuilder(filePath, ApplicationVersionConfiguration.Builder.class);
return new ApplicationVersionConfigurationValidator(configBuilder.build());
Arguments.of("1.0.0", "1.0.0", "1.0.0", "2.0.0"),
Arguments.of("1.0.0", "1.0.0", "1.0.0", "1.1.0"),
Arguments.of("1.0.0", "1.0.0", "1.0.0", "1.0.1")
);
}
}
18 changes: 0 additions & 18 deletions services/distribution/src/test/resources/app-version/all_ok.yaml

This file was deleted.

Loading

0 comments on commit 5e81409

Please sign in to comment.