From 3382f2c2976bfa005e64379acad8af3919730d19 Mon Sep 17 00:00:00 2001 From: Eric Wittmann Date: Thu, 23 Jan 2025 13:55:15 -0500 Subject: [PATCH 1/3] Add support for properly configuring the CORS allowed origins header --- .../operator/EnvironmentVariables.java | 2 + .../apicurio/registry/operator/feat/Cors.java | 68 +++++++++++++ .../resource/app/AppDeploymentResource.java | 16 ++- .../registry/operator/utils/IngressUtils.java | 34 +++++-- .../registry/operator/utils/Mapper.java | 8 ++ .../operator/it/AppFeaturesITTest.java | 4 - .../registry/operator/it/SmokeITTest.java | 12 +++ .../registry/operator/unit/CorsTest.java | 98 +++++++++++++++++++ 8 files changed, 225 insertions(+), 17 deletions(-) create mode 100644 operator/controller/src/main/java/io/apicurio/registry/operator/feat/Cors.java create mode 100644 operator/controller/src/test/java/io/apicurio/registry/operator/unit/CorsTest.java diff --git a/operator/controller/src/main/java/io/apicurio/registry/operator/EnvironmentVariables.java b/operator/controller/src/main/java/io/apicurio/registry/operator/EnvironmentVariables.java index a97a5961a0..3d72573cf4 100644 --- a/operator/controller/src/main/java/io/apicurio/registry/operator/EnvironmentVariables.java +++ b/operator/controller/src/main/java/io/apicurio/registry/operator/EnvironmentVariables.java @@ -10,4 +10,6 @@ public class EnvironmentVariables { public static final String APICURIO_REST_DELETION_ARTIFACT_ENABLED = "APICURIO_REST_DELETION_ARTIFACT_ENABLED"; public static final String APICURIO_REST_DELETION_GROUP_ENABLED = "APICURIO_REST_DELETION_GROUP_ENABLED"; + public static final String APICURIO_REST_MUTABILITY_ARTIFACT_VERSION_CONTENT_ENABLED = "APICURIO_REST_MUTABILITY_ARTIFACT-VERSION-CONTENT_ENABLED"; + } diff --git a/operator/controller/src/main/java/io/apicurio/registry/operator/feat/Cors.java b/operator/controller/src/main/java/io/apicurio/registry/operator/feat/Cors.java new file mode 100644 index 0000000000..d3a30dee6a --- /dev/null +++ b/operator/controller/src/main/java/io/apicurio/registry/operator/feat/Cors.java @@ -0,0 +1,68 @@ +package io.apicurio.registry.operator.feat; + +import io.apicurio.registry.operator.EnvironmentVariables; +import io.apicurio.registry.operator.api.v1.ApicurioRegistry3; +import io.apicurio.registry.operator.api.v1.ApicurioRegistry3Spec; +import io.apicurio.registry.operator.api.v1.spec.ComponentSpec; +import io.apicurio.registry.operator.resource.ResourceFactory; +import io.apicurio.registry.operator.utils.IngressUtils; +import io.fabric8.kubernetes.api.model.EnvVar; +import io.fabric8.kubernetes.api.model.EnvVarBuilder; + +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.Optional; +import java.util.Set; +import java.util.TreeSet; + +/** + * Helper class used to handle CORS related configuration. + */ +public class Cors { + /** + * Configure the QUARKUS_HTTP_CORS_ORIGINS environment variable with the following: + * + * + * @param primary + * @param envVars + */ + public static void configureAllowedOrigins(ApicurioRegistry3 primary, + LinkedHashMap envVars) { + TreeSet allowedOrigins = new TreeSet<>(); + + // If the QUARKUS_HTTP_CORS_ORIGINS env var is configured in the "env" section of the CR, + // then make sure to add those configured values to the set of allowed origins we want to + // configure. + Optional.ofNullable(primary.getSpec()).map(ApicurioRegistry3Spec::getApp).map(ComponentSpec::getEnv) + .ifPresent(env -> { + env.stream().filter( + envVar -> envVar.getName().equals(EnvironmentVariables.QUARKUS_HTTP_CORS_ORIGINS)) + .forEach(envVar -> { + Optional.ofNullable(envVar.getValue()).ifPresent(envVarValue -> { + Arrays.stream(envVarValue.split(",")).forEach(allowedOrigins::add); + }); + }); + }); + + // If there is a configured Ingress host for the UI or the Studio UI, add them to the allowed origins. + Set.of(ResourceFactory.COMPONENT_UI, ResourceFactory.COMPONENT_STUDIO_UI).forEach(component -> { + String host = IngressUtils.getConfiguredHost(component, primary); + if (host != null) { + allowedOrigins.add("http://" + host); + allowedOrigins.add("https://" + host); + } + }); + + if (allowedOrigins.isEmpty()) { + allowedOrigins.add("*"); + } + + // Join the values in allowedOrigins into a String and set it as the new value of the env var. + String envVarValue = String.join(",", allowedOrigins); + envVars.put(EnvironmentVariables.QUARKUS_HTTP_CORS_ORIGINS, new EnvVarBuilder() + .withName(EnvironmentVariables.QUARKUS_HTTP_CORS_ORIGINS).withValue(envVarValue).build()); + } +} diff --git a/operator/controller/src/main/java/io/apicurio/registry/operator/resource/app/AppDeploymentResource.java b/operator/controller/src/main/java/io/apicurio/registry/operator/resource/app/AppDeploymentResource.java index 00361bd198..8eeba252e6 100644 --- a/operator/controller/src/main/java/io/apicurio/registry/operator/resource/app/AppDeploymentResource.java +++ b/operator/controller/src/main/java/io/apicurio/registry/operator/resource/app/AppDeploymentResource.java @@ -7,6 +7,7 @@ import io.apicurio.registry.operator.api.v1.spec.AppFeaturesSpec; import io.apicurio.registry.operator.api.v1.spec.AppSpec; import io.apicurio.registry.operator.api.v1.spec.StorageSpec; +import io.apicurio.registry.operator.feat.Cors; import io.apicurio.registry.operator.feat.KafkaSql; import io.apicurio.registry.operator.feat.PostgresSql; import io.fabric8.kubernetes.api.model.Container; @@ -60,7 +61,6 @@ protected Deployment desired(ApicurioRegistry3 primary, Context { addEnvVar(envVars, - new EnvVarBuilder().withName("APICURIO_REST_MUTABILITY_ARTIFACT-VERSION-CONTENT_ENABLED") + new EnvVarBuilder().withName(EnvironmentVariables.APICURIO_REST_MUTABILITY_ARTIFACT_VERSION_CONTENT_ENABLED) .withValue("true").build()); }); + // spotless:on + + // Configure the storage (Postgresql or KafkaSql). ofNullable(primary.getSpec()).map(ApicurioRegistry3Spec::getApp).map(AppSpec::getStorage) .map(StorageSpec::getType).ifPresent(storageType -> { switch (storageType) { @@ -92,6 +97,7 @@ protected Deployment desired(ApicurioRegistry3 primary, Context ofNullable(p.getSpec()).map(ApicurioRegistry3Spec::getApp) + case COMPONENT_APP -> ofNullable(primary.getSpec()).map(ApicurioRegistry3Spec::getApp) .map(AppSpec::getIngress).map(IngressSpec::getHost).filter(h -> !isBlank(h)).orElse(null); - case COMPONENT_UI -> ofNullable(p.getSpec()).map(ApicurioRegistry3Spec::getUi) + case COMPONENT_UI -> ofNullable(primary.getSpec()).map(ApicurioRegistry3Spec::getUi) .map(UiSpec::getIngress).map(IngressSpec::getHost).filter(h -> !isBlank(h)).orElse(null); - case COMPONENT_STUDIO_UI -> - ofNullable(p.getSpec()).map(ApicurioRegistry3Spec::getStudioUi).map(StudioUiSpec::getIngress) - .map(IngressSpec::getHost).filter(h -> !isBlank(h)).orElse(null); + case COMPONENT_STUDIO_UI -> ofNullable(primary.getSpec()).map(ApicurioRegistry3Spec::getStudioUi) + .map(StudioUiSpec::getIngress).map(IngressSpec::getHost).filter(h -> !isBlank(h)) + .orElse(null); default -> throw new OperatorException("Unexpected value: " + component); }; + return host; + } + + /** + * Get the host for an ingress. If not configured, a default value is returned. + * + * @param component + * @param primary + */ + public static String getHost(String component, ApicurioRegistry3 primary) { + String host = getConfiguredHost(component, primary); if (host == null) { // TODO: This is not used because of the current activation conditions. - host = "%s-%s.%s%s".formatted(p.getMetadata().getName(), component, - p.getMetadata().getNamespace(), Configuration.getDefaultBaseHost()); + host = "%s-%s.%s%s".formatted(primary.getMetadata().getName(), component, + primary.getMetadata().getNamespace(), Configuration.getDefaultBaseHost()); } log.debug("Host for component {} is {}", component, host); return host; diff --git a/operator/controller/src/main/java/io/apicurio/registry/operator/utils/Mapper.java b/operator/controller/src/main/java/io/apicurio/registry/operator/utils/Mapper.java index 69147fa58e..26d62d445f 100644 --- a/operator/controller/src/main/java/io/apicurio/registry/operator/utils/Mapper.java +++ b/operator/controller/src/main/java/io/apicurio/registry/operator/utils/Mapper.java @@ -24,6 +24,14 @@ public class Mapper { YAML_MAPPER.configure(FAIL_ON_UNKNOWN_PROPERTIES, true); } + public static T deserialize(String data, Class klass) { + try { + return YAML_MAPPER.readValue(data, klass); + } catch (JsonProcessingException ex) { + throw new OperatorException("Could not deserialize resource.", ex); + } + } + public static String toYAML(Object value) { try { return YAML_MAPPER.writeValueAsString(value); diff --git a/operator/controller/src/test/java/io/apicurio/registry/operator/it/AppFeaturesITTest.java b/operator/controller/src/test/java/io/apicurio/registry/operator/it/AppFeaturesITTest.java index 2420afebc2..aaadc08dc8 100644 --- a/operator/controller/src/test/java/io/apicurio/registry/operator/it/AppFeaturesITTest.java +++ b/operator/controller/src/test/java/io/apicurio/registry/operator/it/AppFeaturesITTest.java @@ -7,8 +7,6 @@ import io.fabric8.kubernetes.api.model.EnvVar; import io.quarkus.test.junit.QuarkusTest; import org.junit.jupiter.api.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import static io.apicurio.registry.operator.api.v1.ContainerNames.REGISTRY_APP_CONTAINER_NAME; import static io.apicurio.registry.operator.resource.app.AppDeploymentResource.getContainerFromDeployment; @@ -17,8 +15,6 @@ @QuarkusTest public class AppFeaturesITTest extends ITBase { - private static final Logger log = LoggerFactory.getLogger(AppFeaturesITTest.class); - @Test void testAllowDeletesTrue() { ApicurioRegistry3 registry = ResourceFactory diff --git a/operator/controller/src/test/java/io/apicurio/registry/operator/it/SmokeITTest.java b/operator/controller/src/test/java/io/apicurio/registry/operator/it/SmokeITTest.java index eb8a51a074..78b6fc3d95 100644 --- a/operator/controller/src/test/java/io/apicurio/registry/operator/it/SmokeITTest.java +++ b/operator/controller/src/test/java/io/apicurio/registry/operator/it/SmokeITTest.java @@ -1,5 +1,6 @@ package io.apicurio.registry.operator.it; +import io.apicurio.registry.operator.EnvironmentVariables; import io.apicurio.registry.operator.api.v1.ApicurioRegistry3; import io.apicurio.registry.operator.resource.ResourceFactory; import io.fabric8.kubernetes.api.model.Container; @@ -15,9 +16,11 @@ import java.net.URI; +import static io.apicurio.registry.operator.api.v1.ContainerNames.REGISTRY_APP_CONTAINER_NAME; import static io.apicurio.registry.operator.api.v1.ContainerNames.REGISTRY_UI_CONTAINER_NAME; import static io.apicurio.registry.operator.resource.ResourceFactory.COMPONENT_APP; import static io.apicurio.registry.operator.resource.ResourceFactory.COMPONENT_UI; +import static io.apicurio.registry.operator.resource.app.AppDeploymentResource.getContainerFromDeployment; import static io.restassured.RestAssured.given; import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; @@ -70,6 +73,15 @@ void smoke() { .get(0).getHost()).isEqualTo(registry.getSpec().getUi().getIngress().getHost()); return true; }); + + // Check CORS allowed origins is set on the app, with the value based on the UI ingress host + var appEnv = getContainerFromDeployment( + client.apps().deployments().inNamespace(namespace) + .withName(registry.getMetadata().getName() + "-app-deployment").get(), + REGISTRY_APP_CONTAINER_NAME).getEnv(); + assertThat(appEnv).map(ev -> ev.getName() + "=" + ev.getValue()) + .contains(EnvironmentVariables.QUARKUS_HTTP_CORS_ORIGINS + + "=http://simple-ui.apps.cluster.example,https://simple-ui.apps.cluster.example"); } @Test diff --git a/operator/controller/src/test/java/io/apicurio/registry/operator/unit/CorsTest.java b/operator/controller/src/test/java/io/apicurio/registry/operator/unit/CorsTest.java new file mode 100644 index 0000000000..92c81ff02f --- /dev/null +++ b/operator/controller/src/test/java/io/apicurio/registry/operator/unit/CorsTest.java @@ -0,0 +1,98 @@ +package io.apicurio.registry.operator.unit; + +import io.apicurio.registry.operator.EnvironmentVariables; +import io.apicurio.registry.operator.OperatorException; +import io.apicurio.registry.operator.api.v1.ApicurioRegistry3; +import io.apicurio.registry.operator.feat.Cors; +import io.apicurio.registry.operator.utils.Mapper; +import io.fabric8.kubernetes.api.model.EnvVar; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.nio.charset.Charset; +import java.util.LinkedHashMap; +import java.util.Set; + +public class CorsTest { + + private static final String DEFAULT = """ + apiVersion: registry.apicur.io/v1 + kind: ApicurioRegistry3 + metadata: + name: simple + spec: {} + """; + + private static final String WITH_INGRESS = """ + apiVersion: registry.apicur.io/v1 + kind: ApicurioRegistry3 + metadata: + name: simple + spec: + app: + ingress: + host: simple-app.apps.cluster.example + ui: + ingress: + host: simple-ui.apps.cluster.example + """; + + private static final String WITH_ENV_VAR = """ + apiVersion: registry.apicur.io/v1 + kind: ApicurioRegistry3 + metadata: + name: simple + spec: + app: + env: + - name: QUARKUS_HTTP_CORS_ORIGINS + value: https://ui.example.org + """; + + private static final String WITH_ENV_VAR_AND_INGRESS = """ + apiVersion: registry.apicur.io/v1 + kind: ApicurioRegistry3 + metadata: + name: simple + spec: + app: + ingress: + host: simple-app.apps.cluster.example + env: + - name: QUARKUS_HTTP_CORS_ORIGINS + value: https://ui.example.org + ui: + ingress: + host: simple-ui.apps.cluster.example + """; + + @Test + public void testConfigureAllowedOrigins() throws Exception { + doTestAllowedOrigins(DEFAULT, "*"); + doTestAllowedOrigins(WITH_INGRESS, "http://simple-ui.apps.cluster.example", + "https://simple-ui.apps.cluster.example"); + doTestAllowedOrigins(WITH_ENV_VAR, "https://ui.example.org"); + doTestAllowedOrigins(WITH_ENV_VAR_AND_INGRESS, "http://simple-ui.apps.cluster.example", + "https://simple-ui.apps.cluster.example", "https://ui.example.org"); + } + + private void doTestAllowedOrigins(String cr, String... values) { + ApicurioRegistry3 registry = Mapper.deserialize(cr, ApicurioRegistry3.class); + + LinkedHashMap envVars = new LinkedHashMap<>(); + Cors.configureAllowedOrigins(registry, envVars); + Assertions.assertThat(envVars.keySet()).contains(EnvironmentVariables.QUARKUS_HTTP_CORS_ORIGINS); + String allowedOriginsValue = envVars.get(EnvironmentVariables.QUARKUS_HTTP_CORS_ORIGINS).getValue(); + Set allowedOrigins = Set.of(allowedOriginsValue.split(",")); + Assertions.assertThat(allowedOrigins).containsExactlyInAnyOrder(values); + } + + public static String load(String path) { + try (var stream = Thread.currentThread().getContextClassLoader().getResourceAsStream(path)) { + return new String(stream.readAllBytes(), Charset.defaultCharset()); + } catch (Exception ex) { + throw new OperatorException("Could not read resource: " + path, ex); + } + } + +} From 16c411b0af304abd9607f6b3f032e9c7a4757ae4 Mon Sep 17 00:00:00 2001 From: Eric Wittmann Date: Thu, 23 Jan 2025 14:39:39 -0500 Subject: [PATCH 2/3] Fix smoke test to get expected CORS allowed origins from the actual ingress --- .../java/io/apicurio/registry/operator/it/SmokeITTest.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/operator/controller/src/test/java/io/apicurio/registry/operator/it/SmokeITTest.java b/operator/controller/src/test/java/io/apicurio/registry/operator/it/SmokeITTest.java index 78b6fc3d95..33d69ec956 100644 --- a/operator/controller/src/test/java/io/apicurio/registry/operator/it/SmokeITTest.java +++ b/operator/controller/src/test/java/io/apicurio/registry/operator/it/SmokeITTest.java @@ -75,13 +75,16 @@ void smoke() { }); // Check CORS allowed origins is set on the app, with the value based on the UI ingress host + String uiIngressHost = client.network().v1().ingresses().inNamespace(namespace) + .withName(registry.getMetadata().getName() + "-ui-ingress").get().getSpec().getRules().get(0) + .getHost(); + String corsOriginsExpectedValue = "http://" + uiIngressHost + "," + "https://" + uiIngressHost; var appEnv = getContainerFromDeployment( client.apps().deployments().inNamespace(namespace) .withName(registry.getMetadata().getName() + "-app-deployment").get(), REGISTRY_APP_CONTAINER_NAME).getEnv(); assertThat(appEnv).map(ev -> ev.getName() + "=" + ev.getValue()) - .contains(EnvironmentVariables.QUARKUS_HTTP_CORS_ORIGINS - + "=http://simple-ui.apps.cluster.example,https://simple-ui.apps.cluster.example"); + .contains(EnvironmentVariables.QUARKUS_HTTP_CORS_ORIGINS + "=" + corsOriginsExpectedValue); } @Test From 15a5a648df6e726a054824ce2a255913159f8b3c Mon Sep 17 00:00:00 2001 From: Eric Wittmann Date: Fri, 24 Jan 2025 12:41:19 -0500 Subject: [PATCH 3/3] Moved CORS test examples to test/resources. Updated Cors logic. --- .../apicurio/registry/operator/feat/Cors.java | 23 +++--- .../operator/resource/ResourceFactory.java | 14 +++- .../registry/operator/utils/Mapper.java | 8 --- .../registry/operator/unit/CorsTest.java | 70 +++---------------- .../k8s/examples/cors/example-default.yaml | 5 ++ .../cors/example-env-vars-and-ingress.yaml | 14 ++++ .../k8s/examples/cors/example-env-vars.yaml | 9 +++ .../k8s/examples/cors/example-ingress.yaml | 11 +++ 8 files changed, 76 insertions(+), 78 deletions(-) create mode 100644 operator/controller/src/test/resources/k8s/examples/cors/example-default.yaml create mode 100644 operator/controller/src/test/resources/k8s/examples/cors/example-env-vars-and-ingress.yaml create mode 100644 operator/controller/src/test/resources/k8s/examples/cors/example-env-vars.yaml create mode 100644 operator/controller/src/test/resources/k8s/examples/cors/example-ingress.yaml diff --git a/operator/controller/src/main/java/io/apicurio/registry/operator/feat/Cors.java b/operator/controller/src/main/java/io/apicurio/registry/operator/feat/Cors.java index d3a30dee6a..21397369fe 100644 --- a/operator/controller/src/main/java/io/apicurio/registry/operator/feat/Cors.java +++ b/operator/controller/src/main/java/io/apicurio/registry/operator/feat/Cors.java @@ -23,7 +23,7 @@ public class Cors { * Configure the QUARKUS_HTTP_CORS_ORIGINS environment variable with the following: *
    *
  • Add the ingress host
  • - *
  • Include anything specifically configured for QUARKUS_HTTP_CORS_ORIGINS in the "env" section
  • + *
  • Override if QUARKUS_HTTP_CORS_ORIGINS is configured in the "env" section
  • *
* * @param primary @@ -47,15 +47,20 @@ public static void configureAllowedOrigins(ApicurioRegistry3 primary, }); }); - // If there is a configured Ingress host for the UI or the Studio UI, add them to the allowed origins. - Set.of(ResourceFactory.COMPONENT_UI, ResourceFactory.COMPONENT_STUDIO_UI).forEach(component -> { - String host = IngressUtils.getConfiguredHost(component, primary); - if (host != null) { - allowedOrigins.add("http://" + host); - allowedOrigins.add("https://" + host); - } - }); + // If not, let's try to figure it out from other sources. + if (allowedOrigins.isEmpty()) { + // If there is a configured Ingress host for the UI or the Studio UI, add them to the allowed + // origins. + Set.of(ResourceFactory.COMPONENT_UI, ResourceFactory.COMPONENT_STUDIO_UI).forEach(component -> { + String host = IngressUtils.getConfiguredHost(component, primary); + if (host != null) { + allowedOrigins.add("http://" + host); + allowedOrigins.add("https://" + host); + } + }); + } + // If we still do not have anything, then default to "*" if (allowedOrigins.isEmpty()) { allowedOrigins.add("*"); } diff --git a/operator/controller/src/main/java/io/apicurio/registry/operator/resource/ResourceFactory.java b/operator/controller/src/main/java/io/apicurio/registry/operator/resource/ResourceFactory.java index 9f232cf525..dd65faaab2 100644 --- a/operator/controller/src/main/java/io/apicurio/registry/operator/resource/ResourceFactory.java +++ b/operator/controller/src/main/java/io/apicurio/registry/operator/resource/ResourceFactory.java @@ -274,8 +274,20 @@ public static T deserialize(String path, Class klass) { } } + public static T deserialize(String path, Class klass, ClassLoader classLoader) { + try { + return YAML_MAPPER.readValue(load(path, classLoader), klass); + } catch (JsonProcessingException ex) { + throw new OperatorException("Could not deserialize resource: " + path, ex); + } + } + public static String load(String path) { - try (var stream = Thread.currentThread().getContextClassLoader().getResourceAsStream(path)) { + return load(path, Thread.currentThread().getContextClassLoader()); + } + + public static String load(String path, ClassLoader classLoader) { + try (var stream = classLoader.getResourceAsStream(path)) { return new String(stream.readAllBytes(), Charset.defaultCharset()); } catch (Exception ex) { throw new OperatorException("Could not read resource: " + path, ex); diff --git a/operator/controller/src/main/java/io/apicurio/registry/operator/utils/Mapper.java b/operator/controller/src/main/java/io/apicurio/registry/operator/utils/Mapper.java index 26d62d445f..69147fa58e 100644 --- a/operator/controller/src/main/java/io/apicurio/registry/operator/utils/Mapper.java +++ b/operator/controller/src/main/java/io/apicurio/registry/operator/utils/Mapper.java @@ -24,14 +24,6 @@ public class Mapper { YAML_MAPPER.configure(FAIL_ON_UNKNOWN_PROPERTIES, true); } - public static T deserialize(String data, Class klass) { - try { - return YAML_MAPPER.readValue(data, klass); - } catch (JsonProcessingException ex) { - throw new OperatorException("Could not deserialize resource.", ex); - } - } - public static String toYAML(Object value) { try { return YAML_MAPPER.writeValueAsString(value); diff --git a/operator/controller/src/test/java/io/apicurio/registry/operator/unit/CorsTest.java b/operator/controller/src/test/java/io/apicurio/registry/operator/unit/CorsTest.java index 92c81ff02f..cd6d203cdc 100644 --- a/operator/controller/src/test/java/io/apicurio/registry/operator/unit/CorsTest.java +++ b/operator/controller/src/test/java/io/apicurio/registry/operator/unit/CorsTest.java @@ -4,7 +4,7 @@ import io.apicurio.registry.operator.OperatorException; import io.apicurio.registry.operator.api.v1.ApicurioRegistry3; import io.apicurio.registry.operator.feat.Cors; -import io.apicurio.registry.operator.utils.Mapper; +import io.apicurio.registry.operator.resource.ResourceFactory; import io.fabric8.kubernetes.api.model.EnvVar; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; @@ -15,69 +15,19 @@ public class CorsTest { - private static final String DEFAULT = """ - apiVersion: registry.apicur.io/v1 - kind: ApicurioRegistry3 - metadata: - name: simple - spec: {} - """; - - private static final String WITH_INGRESS = """ - apiVersion: registry.apicur.io/v1 - kind: ApicurioRegistry3 - metadata: - name: simple - spec: - app: - ingress: - host: simple-app.apps.cluster.example - ui: - ingress: - host: simple-ui.apps.cluster.example - """; - - private static final String WITH_ENV_VAR = """ - apiVersion: registry.apicur.io/v1 - kind: ApicurioRegistry3 - metadata: - name: simple - spec: - app: - env: - - name: QUARKUS_HTTP_CORS_ORIGINS - value: https://ui.example.org - """; - - private static final String WITH_ENV_VAR_AND_INGRESS = """ - apiVersion: registry.apicur.io/v1 - kind: ApicurioRegistry3 - metadata: - name: simple - spec: - app: - ingress: - host: simple-app.apps.cluster.example - env: - - name: QUARKUS_HTTP_CORS_ORIGINS - value: https://ui.example.org - ui: - ingress: - host: simple-ui.apps.cluster.example - """; - @Test public void testConfigureAllowedOrigins() throws Exception { - doTestAllowedOrigins(DEFAULT, "*"); - doTestAllowedOrigins(WITH_INGRESS, "http://simple-ui.apps.cluster.example", - "https://simple-ui.apps.cluster.example"); - doTestAllowedOrigins(WITH_ENV_VAR, "https://ui.example.org"); - doTestAllowedOrigins(WITH_ENV_VAR_AND_INGRESS, "http://simple-ui.apps.cluster.example", - "https://simple-ui.apps.cluster.example", "https://ui.example.org"); + doTestAllowedOrigins("k8s/examples/cors/example-default.yaml", "*"); + doTestAllowedOrigins("k8s/examples/cors/example-ingress.yaml", + "http://simple-ui.apps.cluster.example", "https://simple-ui.apps.cluster.example"); + doTestAllowedOrigins("k8s/examples/cors/example-env-vars.yaml", "https://ui.example.org"); + doTestAllowedOrigins("k8s/examples/cors/example-env-vars-and-ingress.yaml", "https://ui.example.org"); } - private void doTestAllowedOrigins(String cr, String... values) { - ApicurioRegistry3 registry = Mapper.deserialize(cr, ApicurioRegistry3.class); + private void doTestAllowedOrigins(String crPath, String... values) { + ClassLoader classLoader = CorsTest.class.getClassLoader(); + ApicurioRegistry3 registry = ResourceFactory.deserialize(crPath, ApicurioRegistry3.class, + classLoader); LinkedHashMap envVars = new LinkedHashMap<>(); Cors.configureAllowedOrigins(registry, envVars); diff --git a/operator/controller/src/test/resources/k8s/examples/cors/example-default.yaml b/operator/controller/src/test/resources/k8s/examples/cors/example-default.yaml new file mode 100644 index 0000000000..53e6d43ef7 --- /dev/null +++ b/operator/controller/src/test/resources/k8s/examples/cors/example-default.yaml @@ -0,0 +1,5 @@ +apiVersion: registry.apicur.io/v1 +kind: ApicurioRegistry3 +metadata: + name: simple +spec: {} diff --git a/operator/controller/src/test/resources/k8s/examples/cors/example-env-vars-and-ingress.yaml b/operator/controller/src/test/resources/k8s/examples/cors/example-env-vars-and-ingress.yaml new file mode 100644 index 0000000000..10a0a16c8a --- /dev/null +++ b/operator/controller/src/test/resources/k8s/examples/cors/example-env-vars-and-ingress.yaml @@ -0,0 +1,14 @@ +apiVersion: registry.apicur.io/v1 +kind: ApicurioRegistry3 +metadata: + name: simple +spec: + app: + ingress: + host: simple-app.apps.cluster.example + env: + - name: QUARKUS_HTTP_CORS_ORIGINS + value: https://ui.example.org + ui: + ingress: + host: simple-ui.apps.cluster.example diff --git a/operator/controller/src/test/resources/k8s/examples/cors/example-env-vars.yaml b/operator/controller/src/test/resources/k8s/examples/cors/example-env-vars.yaml new file mode 100644 index 0000000000..9525aee1ac --- /dev/null +++ b/operator/controller/src/test/resources/k8s/examples/cors/example-env-vars.yaml @@ -0,0 +1,9 @@ +apiVersion: registry.apicur.io/v1 +kind: ApicurioRegistry3 +metadata: + name: simple +spec: + app: + env: + - name: QUARKUS_HTTP_CORS_ORIGINS + value: https://ui.example.org diff --git a/operator/controller/src/test/resources/k8s/examples/cors/example-ingress.yaml b/operator/controller/src/test/resources/k8s/examples/cors/example-ingress.yaml new file mode 100644 index 0000000000..2cd8be6262 --- /dev/null +++ b/operator/controller/src/test/resources/k8s/examples/cors/example-ingress.yaml @@ -0,0 +1,11 @@ +apiVersion: registry.apicur.io/v1 +kind: ApicurioRegistry3 +metadata: + name: simple +spec: + app: + ingress: + host: simple-app.apps.cluster.example + ui: + ingress: + host: simple-ui.apps.cluster.example