diff --git a/.circleci/config.yml b/.circleci/config.yml index 6e551d6c..0b2966ec 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -46,7 +46,7 @@ jobs: echo $CLASSNAMES TEST_ARG=$(echo $CLASSNAMES | sed 's/ /,/g') echo $TEST_ARG - ./mvnw -s .settings.xml -DfailIfNoTests=false -DtestsToRun=$TEST_ARG -e clean org.jacoco:jacoco-maven-plugin:prepare-agent test -U -P sonar -nsu --batch-mode -Dmaven.test.redirectTestOutputToFile=true -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn + ./mvnw -s .settings.xml -DfailIfNoTests=false -DtestsToRun=$TEST_ARG -e clean org.jacoco:jacoco-maven-plugin:prepare-agent test -U -P sonar -nsu --batch-mode -Dmaven.test.redirectTestOutputToFile=true -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn mkdir -p $HOME/artifacts/junit/ find . -type f -regex ".*/spring-cloud-*.*/target/*.*" -exec cp {} $HOME/artifacts/ \; find . -type f -regex ".*/target/.*-reports/.*" -exec cp {} $HOME/artifacts/junit/ \; diff --git a/.gitignore b/.gitignore index 971ab7b3..ec7f57ba 100644 --- a/.gitignore +++ b/.gitignore @@ -83,3 +83,4 @@ crashlytics-build.properties .attach_pid* .vscode/ .java-version +dockerfile diff --git a/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8SecretsPropertySource.java b/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8SecretsPropertySource.java index 6b71864d..863e52d6 100644 --- a/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8SecretsPropertySource.java +++ b/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8SecretsPropertySource.java @@ -63,8 +63,10 @@ public class Fabric8SecretsPropertySource extends SecretsPropertySource { putDataFromSecret(secret, result, namespace); } - client.secrets().inNamespace(namespace).withLabels(labels).list().getItems() - .forEach(s -> putDataFromSecret(s, result, namespace)); + if (labels != null && !labels.isEmpty()) { + client.secrets().inNamespace(namespace).withLabels(labels).list().getItems() + .forEach(s -> putDataFromSecret(s, result, namespace)); + } } catch (Exception e) { diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/secrets_with_labels/One.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/secrets_with_labels/One.java new file mode 100644 index 00000000..6b167c3c --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/secrets_with_labels/One.java @@ -0,0 +1,34 @@ +/* + * Copyright 2013-2022 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 org.springframework.cloud.kubernetes.fabric8.config.secrets_with_labels; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties("secret") +class One { + + private String property; + + String getProperty() { + return property; + } + + void setProperty(String property) { + this.property = property; + } + +} diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/secrets_with_labels/SecretsWithLabelsApp.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/secrets_with_labels/SecretsWithLabelsApp.java new file mode 100644 index 00000000..b4a720a4 --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/secrets_with_labels/SecretsWithLabelsApp.java @@ -0,0 +1,31 @@ +/* + * Copyright 2013-2022 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 org.springframework.cloud.kubernetes.fabric8.config.secrets_with_labels; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.EnableConfigurationProperties; + +@SpringBootApplication +@EnableConfigurationProperties({ One.class }) +class SecretsWithLabelsApp { + + static void main(String[] args) { + SpringApplication.run(SecretsWithLabelsApp.class, args); + } + +} diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/secrets_with_labels/SecretsWithLabelsController.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/secrets_with_labels/SecretsWithLabelsController.java new file mode 100644 index 00000000..4eec11c6 --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/secrets_with_labels/SecretsWithLabelsController.java @@ -0,0 +1,36 @@ +/* + * Copyright 2013-2022 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 org.springframework.cloud.kubernetes.fabric8.config.secrets_with_labels; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +class SecretsWithLabelsController { + + private final One one; + + SecretsWithLabelsController(One one) { + this.one = one; + } + + @GetMapping("secrets/labels/one") + String one() { + return one.getProperty(); + } + +} diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/secrets_with_labels/SecretsWithLabelsTests.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/secrets_with_labels/SecretsWithLabelsTests.java new file mode 100644 index 00000000..61adb1b4 --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/secrets_with_labels/SecretsWithLabelsTests.java @@ -0,0 +1,91 @@ +/* + * Copyright 2013-2022 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 org.springframework.cloud.kubernetes.fabric8.config.secrets_with_labels; + +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.Collections; +import java.util.Map; + +import io.fabric8.kubernetes.api.model.SecretBuilder; +import io.fabric8.kubernetes.client.Config; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; +import org.hamcrest.Matchers; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.web.reactive.server.WebTestClient; + +/** + * @author wind57 + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = SecretsWithLabelsApp.class, + properties = { "spring.cloud.bootstrap.name=secret-with-labels-config", + "spring.main.cloud-platform=KUBERNETES" }) +@EnableKubernetesMockClient(crud = true, https = false) +class SecretsWithLabelsTests { + + private static KubernetesClient mockClient; + + @Autowired + private WebTestClient webClient; + + @BeforeAll + static void setUpBeforeClass() { + + // Configure the kubernetes master url to point to the mock server + System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, mockClient.getConfiguration().getMasterUrl()); + System.setProperty(Config.KUBERNETES_TRUST_CERT_SYSTEM_PROPERTY, "true"); + System.setProperty(Config.KUBERNETES_AUTH_TRYKUBECONFIG_SYSTEM_PROPERTY, "false"); + System.setProperty(Config.KUBERNETES_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); + System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test"); + System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); + + Map two = Collections.singletonMap("secret.property", + Base64.getEncoder().encodeToString("value".getBytes(StandardCharsets.UTF_8))); + createSecret("secret-two", two); + + Map three = Collections.singletonMap("secret.property", + Base64.getEncoder().encodeToString("diff-value".getBytes(StandardCharsets.UTF_8))); + createSecret("secret-three", three); + + } + + private static void createSecret(String name, Map data) { + mockClient.secrets().inNamespace("spring-k8s") + .create(new SecretBuilder().withNewMetadata().withName(name).endMetadata().addToData(data).build()); + } + + /** + *
+	 *	 1. We have two secrets in a certain namespace: "secret-two" and "secret-three".
+	 *	 2. Both of the above configure the same secret data: "secret.property", but with different
+	 *	    values : "value" and "diff-value"
+	 *	 3. In our configuration we want to read only "secret-two" (the one that stores "value" inside)
+	 *	 4. This test proves that we do not touch "secret-three"
+	 * 
+ */ + @Test + void testOne() { + this.webClient.get().uri("secrets/labels/one").exchange().expectStatus().isOk().expectBody(String.class) + .value(Matchers.equalTo("value")); + } + +} diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/resources/secret-with-labels-config.yaml b/spring-cloud-kubernetes-fabric8-config/src/test/resources/secret-with-labels-config.yaml new file mode 100644 index 00000000..25d8779f --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-config/src/test/resources/secret-with-labels-config.yaml @@ -0,0 +1,10 @@ +spring: + application: + name: with-prefix + cloud: + kubernetes: + secrets: + enableApi: true + namespace: spring-k8s + sources: + - name: secret-two