diff --git a/annotations/kind-annotations/src/main/java/io/dekorate/kind/annotation/Kind.java b/annotations/kind-annotations/src/main/java/io/dekorate/kind/annotation/Kind.java index 1e349f75a..95489fa77 100644 --- a/annotations/kind-annotations/src/main/java/io/dekorate/kind/annotation/Kind.java +++ b/annotations/kind-annotations/src/main/java/io/dekorate/kind/annotation/Kind.java @@ -50,7 +50,8 @@ @BuildableReference(io.dekorate.kubernetes.config.HostAlias.class), @BuildableReference(io.dekorate.kubernetes.config.Container.class), @BuildableReference(io.dekorate.kubernetes.config.Job.class), - @BuildableReference(io.dekorate.kubernetes.config.CronJob.class) + @BuildableReference(io.dekorate.kubernetes.config.CronJob.class), + @BuildableReference(io.dekorate.kubernetes.config.NodeSelector.class) }) @Pojo(name = "KindConfig", relativePath = "../config", autobox = true, mutable = true, superClass = BaseConfig.class, withStaticBuilderMethod = true, withStaticAdapterMethod = false, adapter = @Adapter(name = "KindConfigAdapter", relativePath = "../adapter", withMapAdapterMethod = true)) @Target({ ElementType.CONSTRUCTOR, ElementType.TYPE }) diff --git a/annotations/knative-annotations/src/main/java/io/dekorate/knative/annotation/KnativeApplication.java b/annotations/knative-annotations/src/main/java/io/dekorate/knative/annotation/KnativeApplication.java index 4cfdcd25d..25992f721 100644 --- a/annotations/knative-annotations/src/main/java/io/dekorate/knative/annotation/KnativeApplication.java +++ b/annotations/knative-annotations/src/main/java/io/dekorate/knative/annotation/KnativeApplication.java @@ -45,6 +45,7 @@ import io.dekorate.kubernetes.annotation.ServiceType; import io.dekorate.kubernetes.config.BaseConfig; import io.dekorate.kubernetes.config.HostAlias; +import io.dekorate.kubernetes.config.NodeSelector; import io.dekorate.kubernetes.config.RollingUpdate; import io.dekorate.project.BuildInfo; import io.dekorate.project.Project; @@ -57,7 +58,8 @@ @BuildableReference(Project.class), @BuildableReference(BuildInfo.class), @BuildableReference(HostAlias.class), - @BuildableReference(RollingUpdate.class) + @BuildableReference(RollingUpdate.class), + @BuildableReference(NodeSelector.class) }) @Pojo(name = "KnativeConfig", autobox = true, mutable = true, superClass = BaseConfig.class, relativePath = "../config", withStaticAdapterMethod = false, adapter = @Adapter(relativePath = "../adapter", withMapAdapterMethod = true)) @Target({ ElementType.CONSTRUCTOR, ElementType.TYPE }) diff --git a/annotations/knative-annotations/src/main/java/io/dekorate/knative/decorator/AddNodeSelectorToRevisionDecorator.java b/annotations/knative-annotations/src/main/java/io/dekorate/knative/decorator/AddNodeSelectorToRevisionDecorator.java new file mode 100644 index 000000000..2c852d353 --- /dev/null +++ b/annotations/knative-annotations/src/main/java/io/dekorate/knative/decorator/AddNodeSelectorToRevisionDecorator.java @@ -0,0 +1,71 @@ +/** + * Copyright 2018 The original 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * +**/ + +package io.dekorate.knative.decorator; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +import io.dekorate.kubernetes.config.NodeSelector; +import io.dekorate.kubernetes.decorator.NamedResourceDecorator; +import io.dekorate.utils.Strings; +import io.fabric8.knative.serving.v1.RevisionSpecFluent; +import io.fabric8.kubernetes.api.model.ObjectMeta; + +public class AddNodeSelectorToRevisionDecorator extends NamedResourceDecorator> { + + private final NodeSelector nodeSelector; + + public AddNodeSelectorToRevisionDecorator(NodeSelector nodeSelector) { + this(ANY, nodeSelector); + } + + public AddNodeSelectorToRevisionDecorator(String deploymentName, NodeSelector nodeSelector) { + super(deploymentName); + this.nodeSelector = nodeSelector; + } + + public void andThenVisit(RevisionSpecFluent revisionSpec, ObjectMeta resourceMeta) { + if (Strings.isNotNullOrEmpty(nodeSelector.getKey()) && Strings.isNotNullOrEmpty(nodeSelector.getValue())) { + Map existing = revisionSpec.getNodeSelector(); + + if (existing == null) + existing = new HashMap<>(); + else + existing.clear(); + + existing.put(nodeSelector.getKey(), nodeSelector.getValue()); + revisionSpec.withNodeSelector(existing); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + AddNodeSelectorToRevisionDecorator that = (AddNodeSelectorToRevisionDecorator) o; + return Objects.equals(nodeSelector, that.nodeSelector); + } + + @Override + public int hashCode() { + return Objects.hash(nodeSelector); + } +} diff --git a/annotations/knative-annotations/src/main/java/io/dekorate/knative/manifest/KnativeManifestGenerator.java b/annotations/knative-annotations/src/main/java/io/dekorate/knative/manifest/KnativeManifestGenerator.java index a12afcfdc..5c6abeb0b 100644 --- a/annotations/knative-annotations/src/main/java/io/dekorate/knative/manifest/KnativeManifestGenerator.java +++ b/annotations/knative-annotations/src/main/java/io/dekorate/knative/manifest/KnativeManifestGenerator.java @@ -36,6 +36,7 @@ import io.dekorate.knative.decorator.AddConfigMapVolumeToRevisionDecorator; import io.dekorate.knative.decorator.AddEmptyDirVolumeToRevisionDecorator; import io.dekorate.knative.decorator.AddHostAliasesToRevisionDecorator; +import io.dekorate.knative.decorator.AddNodeSelectorToRevisionDecorator; import io.dekorate.knative.decorator.AddPvcVolumeToRevisionDecorator; import io.dekorate.knative.decorator.AddSecretVolumeToRevisionDecorator; import io.dekorate.knative.decorator.AddSidecarToRevisionDecorator; @@ -292,6 +293,10 @@ public void generate(KnativeConfig config) { resourceRegistry.decorate(KNATIVE, new AddHostAliasesToRevisionDecorator(hostAlias)); } + if (config.getNodeSelector() != null) { + resourceRegistry.decorate(KNATIVE, new AddNodeSelectorToRevisionDecorator(config.getNodeSelector())); + } + } @Override @@ -331,7 +336,7 @@ public boolean accepts(Class type) { /** * Creates a {@link Service} for the {@link KnativeConfig}. - * + * * @param config The sesssion. * @return The deployment config. */ diff --git a/annotations/kubernetes-annotations/src/main/java/io/dekorate/kubernetes/annotation/KubernetesApplication.java b/annotations/kubernetes-annotations/src/main/java/io/dekorate/kubernetes/annotation/KubernetesApplication.java index 4d6320696..9567080d8 100644 --- a/annotations/kubernetes-annotations/src/main/java/io/dekorate/kubernetes/annotation/KubernetesApplication.java +++ b/annotations/kubernetes-annotations/src/main/java/io/dekorate/kubernetes/annotation/KubernetesApplication.java @@ -228,6 +228,11 @@ */ HostAlias[] hostAliases() default {}; + /** + * The nodeSelector + */ + NodeSelector nodeSelector() default @NodeSelector(); + /** * The liveness probe. * diff --git a/annotations/minikube-annotations/src/main/java/io/dekorate/minikube/annotation/Minikube.java b/annotations/minikube-annotations/src/main/java/io/dekorate/minikube/annotation/Minikube.java index 4a32cfaaa..6c1c34e4f 100644 --- a/annotations/minikube-annotations/src/main/java/io/dekorate/minikube/annotation/Minikube.java +++ b/annotations/minikube-annotations/src/main/java/io/dekorate/minikube/annotation/Minikube.java @@ -48,7 +48,8 @@ @BuildableReference(io.dekorate.kubernetes.config.HostAlias.class), @BuildableReference(io.dekorate.kubernetes.config.Container.class), @BuildableReference(io.dekorate.kubernetes.config.Job.class), - @BuildableReference(io.dekorate.kubernetes.config.CronJob.class) + @BuildableReference(io.dekorate.kubernetes.config.CronJob.class), + @BuildableReference(io.dekorate.kubernetes.config.NodeSelector.class) }) @Pojo(name = "MinikubeConfig", relativePath = "../config", autobox = true, mutable = true, superClass = BaseConfig.class, withStaticBuilderMethod = true, withStaticAdapterMethod = false, adapter = @Adapter(suffix = "Adapter", relativePath = "../adapter", withMapAdapterMethod = true)) @Target({ ElementType.CONSTRUCTOR, ElementType.TYPE }) diff --git a/annotations/openshift-annotations/src/main/java/io/dekorate/openshift/annotation/OpenshiftApplication.java b/annotations/openshift-annotations/src/main/java/io/dekorate/openshift/annotation/OpenshiftApplication.java index 03c27b43b..423385c1c 100644 --- a/annotations/openshift-annotations/src/main/java/io/dekorate/openshift/annotation/OpenshiftApplication.java +++ b/annotations/openshift-annotations/src/main/java/io/dekorate/openshift/annotation/OpenshiftApplication.java @@ -44,6 +44,7 @@ import io.dekorate.kubernetes.config.BaseConfig; import io.dekorate.kubernetes.config.DeploymentStrategy; import io.dekorate.kubernetes.config.HostAlias; +import io.dekorate.kubernetes.config.NodeSelector; import io.dekorate.project.BuildInfo; import io.dekorate.project.Project; import io.sundr.builder.annotations.Adapter; @@ -54,7 +55,8 @@ @Buildable(builderPackage = "io.fabric8.kubernetes.api.builder", refs = { @BuildableReference(Project.class), @BuildableReference(BuildInfo.class), - @BuildableReference(HostAlias.class) + @BuildableReference(HostAlias.class), + @BuildableReference(NodeSelector.class) }) @Pojo(name = "OpenshiftConfig", autobox = true, mutable = true, superClass = BaseConfig.class, relativePath = "../config", withStaticAdapterMethod = false, adapter = @Adapter(relativePath = "../adapter", withMapAdapterMethod = true)) @Target({ ElementType.CONSTRUCTOR, ElementType.TYPE }) diff --git a/core/src/main/java/io/dekorate/AbstractKubernetesManifestGenerator.java b/core/src/main/java/io/dekorate/AbstractKubernetesManifestGenerator.java index 0928c9b69..cba4efd64 100644 --- a/core/src/main/java/io/dekorate/AbstractKubernetesManifestGenerator.java +++ b/core/src/main/java/io/dekorate/AbstractKubernetesManifestGenerator.java @@ -54,6 +54,7 @@ import io.dekorate.kubernetes.decorator.AddLivenessProbeDecorator; import io.dekorate.kubernetes.decorator.AddMetadataToTemplateDecorator; import io.dekorate.kubernetes.decorator.AddMountDecorator; +import io.dekorate.kubernetes.decorator.AddNodeSelectorDecorator; import io.dekorate.kubernetes.decorator.AddPortDecorator; import io.dekorate.kubernetes.decorator.AddPvcVolumeDecorator; import io.dekorate.kubernetes.decorator.AddReadinessProbeDecorator; @@ -80,7 +81,7 @@ /** * An abstract generator. * A generator is meant to populate the initial resources to the {@link Session} as well as adding decorator etc. - * + * * @param The config type (its expected to vary between processors). */ public abstract class AbstractKubernetesManifestGenerator implements ManifestGenerator, WithProject { @@ -97,7 +98,7 @@ public AbstractKubernetesManifestGenerator(ResourceRegistry resources, Configura /** * Generate / populate the resources. - * + * * @param config */ public abstract void generate(C config); @@ -106,7 +107,7 @@ public AbstractKubernetesManifestGenerator(ResourceRegistry resources, Configura * Add all decorator to the resources. * This method will read the config and then add all the required decorator to the resources. * The method is intended to be called from the generate method and thus marked as protected. - * + * * @param group The group. * @param config The config. */ @@ -150,15 +151,22 @@ protected void addDecorators(String group, C config) { resourceRegistry.decorate(new AddHostAliasesDecorator(config.getName(), hostAlias)); } + if (config.getNodeSelector() != null) { + resourceRegistry.decorate(new AddNodeSelectorDecorator(config.getName(), config.getNodeSelector())); + } + for (Container container : config.getSidecars()) { resourceRegistry.decorate(group, new AddSidecarDecorator(config.getName(), container)); } + for (Env env : config.getEnvVars()) { resourceRegistry.decorate(group, new AddEnvVarDecorator(config.getName(), config.getName(), env)); } + for (Port port : config.getPorts()) { resourceRegistry.decorate(group, new AddPortDecorator(config.getName(), config.getName(), port)); } + for (Mount mount : config.getMounts()) { resourceRegistry.decorate(group, new AddMountDecorator(config.getName(), config.getName(), mount)); } diff --git a/core/src/main/java/io/dekorate/kubernetes/annotation/Base.java b/core/src/main/java/io/dekorate/kubernetes/annotation/Base.java index 48fb34eba..de85775c2 100644 --- a/core/src/main/java/io/dekorate/kubernetes/annotation/Base.java +++ b/core/src/main/java/io/dekorate/kubernetes/annotation/Base.java @@ -195,6 +195,13 @@ */ HostAlias[] hostAliases() default {}; + /** + * Node Selector + * + * @return The nodeSelector + */ + NodeSelector nodeSelector(); + /** * The liveness probe. * diff --git a/core/src/main/java/io/dekorate/kubernetes/annotation/NodeSelector.java b/core/src/main/java/io/dekorate/kubernetes/annotation/NodeSelector.java new file mode 100644 index 000000000..318b141c0 --- /dev/null +++ b/core/src/main/java/io/dekorate/kubernetes/annotation/NodeSelector.java @@ -0,0 +1,23 @@ +/** + * Copyright 2018 The original 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.dekorate.kubernetes.annotation; + +public @interface NodeSelector { + + String key() default ""; + + String value() default ""; +} diff --git a/core/src/main/java/io/dekorate/kubernetes/decorator/AddNodeSelectorDecorator.java b/core/src/main/java/io/dekorate/kubernetes/decorator/AddNodeSelectorDecorator.java new file mode 100644 index 000000000..9d8561108 --- /dev/null +++ b/core/src/main/java/io/dekorate/kubernetes/decorator/AddNodeSelectorDecorator.java @@ -0,0 +1,57 @@ +/** + * Copyright 2018 The original 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * +**/ + +package io.dekorate.kubernetes.decorator; + +import java.util.Objects; + +import io.dekorate.kubernetes.config.NodeSelector; +import io.dekorate.utils.Strings; +import io.fabric8.kubernetes.api.model.ObjectMeta; +import io.fabric8.kubernetes.api.model.PodSpecFluent; + +public class AddNodeSelectorDecorator extends NamedResourceDecorator> { + + private final NodeSelector nodeSelector; + + public AddNodeSelectorDecorator(String deploymentName, NodeSelector nodeSelector) { + super(deploymentName); + this.nodeSelector = nodeSelector; + } + + public void andThenVisit(PodSpecFluent podSpec, ObjectMeta resourceMeta) { + if (Strings.isNotNullOrEmpty(nodeSelector.getKey()) && Strings.isNotNullOrEmpty(nodeSelector.getValue())) { + podSpec.removeFromNodeSelector(nodeSelector.getKey()); + podSpec.addToNodeSelector(nodeSelector.getKey(), nodeSelector.getValue()); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + AddNodeSelectorDecorator that = (AddNodeSelectorDecorator) o; + return Objects.equals(nodeSelector, that.nodeSelector); + } + + @Override + public int hashCode() { + return Objects.hash(nodeSelector); + } +} diff --git a/examples/kubernetes-with-nodeselectors-example/Dockerfile b/examples/kubernetes-with-nodeselectors-example/Dockerfile new file mode 100644 index 000000000..c8183caaf --- /dev/null +++ b/examples/kubernetes-with-nodeselectors-example/Dockerfile @@ -0,0 +1,4 @@ +FROM openjdk:8u171-alpine3.7 +RUN apk --no-cache add curl +COPY target/*.jar kubernetes-with-nodeselectors-example.jar +CMD java ${JAVA_OPTS} -jar kubernetes-with-nodeselectors-example.jar diff --git a/examples/kubernetes-with-nodeselectors-example/pom.xml b/examples/kubernetes-with-nodeselectors-example/pom.xml new file mode 100644 index 000000000..fb30a10f4 --- /dev/null +++ b/examples/kubernetes-with-nodeselectors-example/pom.xml @@ -0,0 +1,94 @@ + + + + 4.0.0 + + io.dekorate + kubernetes-with-nodeselectors-example + 999-SNAPSHOT + Dekorate :: Examples :: Kubernetes with nodeSelectors + + + UTF-8 + UTF-8 + 1.8 + + 2.5.12 + 3.8.0 + 3.0.0-M3 + + + + + io.dekorate + kubernetes-annotations + ${project.version} + + + + org.springframework.boot + spring-boot-starter-web + ${version.spring-boot} + + + + + io.dekorate + kubernetes-junit-starter + ${project.version} + test + + + + + + + maven-compiler-plugin + ${version.maven-compiler-plugin} + + ${java.version} + ${java.version} + + + + org.springframework.boot + spring-boot-maven-plugin + ${version.spring-boot} + + + + repackage + + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${version.maven-surefire-plugin} + true + + false + false + + + + + + + diff --git a/examples/kubernetes-with-nodeselectors-example/readme.md b/examples/kubernetes-with-nodeselectors-example/readme.md new file mode 100644 index 000000000..ee8ba18fc --- /dev/null +++ b/examples/kubernetes-with-nodeselectors-example/readme.md @@ -0,0 +1,71 @@ +# Add nodeSelector example + +An example that demonstrates the use of `@KubernetesApplication` in order to add nodeSelector property to a deployment. +To access the `@KubernetesApplication` annotation you just need to have the following dependency in your +class path: + + + io.dekorate + kubernetes-annotations + ${project.version} + + +So as to add the nodeSelector section of the Deployment specification you need pass the `nodeSelector` parameter containing they key and the value of the `nodeSelector` `@KubernetesApplication` in the Spring Boot annotated class. The code would look as follow: + +``` +@KubernetesApplication(nodeSelector = @NodeSelector(key = "diskType", value = "ssd")) +@SpringBootApplication +public class Main { + + public static void main(String[] args) { + SpringApplication.run(Main.class, args); + } +} +``` +Check, if necessary, the [Main.java](src/main/java/io/dekorate/example/Main.java). + +Compile the project using: + + mvn clean install + +You can find the generated deployment under: `target/classes/META-INF/dekorate/kubernetes.yml` that should look like: +```--- +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + app.dekorate.io/vcs-url: <> + app.dekorate.io/commit-id: 31df9b1860543a31fc710f8461b160ea65ce7c7a + labels: + app.kubernetes.io/name: kubernetes-with-nodeselectors-example + app.kubernetes.io/version: 999-SNAPSHOT + name: kubernetes-with-nodeselectors-example +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: kubernetes-with-nodeselectors-example + app.kubernetes.io/version: 999-SNAPSHOT + template: + metadata: + annotations: + app.dekorate.io/vcs-url: <> + app.dekorate.io/commit-id: 31df9b1860543a31fc710f8461b160ea65ce7c7a + labels: + app.kubernetes.io/name: kubernetes-with-nodeselectors-example + app.kubernetes.io/version: 999-SNAPSHOT + spec: + containers: + - env: + - name: KUBERNETES_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + image: vinche/kubernetes-with-nodeselectors-example:999-SNAPSHOT + imagePullPolicy: IfNotPresent + name: kubernetes-with-nodeselectors-example + nodeSelector: + diskType: ssd +``` + + diff --git a/examples/kubernetes-with-nodeselectors-example/src/main/java/io/dekorate/example/Controller.java b/examples/kubernetes-with-nodeselectors-example/src/main/java/io/dekorate/example/Controller.java new file mode 100644 index 000000000..ca675cb4a --- /dev/null +++ b/examples/kubernetes-with-nodeselectors-example/src/main/java/io/dekorate/example/Controller.java @@ -0,0 +1,28 @@ +/** + * Copyright 2018 The original 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.dekorate.example; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class Controller { + + @RequestMapping("/") + public String hello() { + return "Hello world"; + } +} diff --git a/examples/kubernetes-with-nodeselectors-example/src/main/java/io/dekorate/example/Main.java b/examples/kubernetes-with-nodeselectors-example/src/main/java/io/dekorate/example/Main.java new file mode 100644 index 000000000..c24247cc9 --- /dev/null +++ b/examples/kubernetes-with-nodeselectors-example/src/main/java/io/dekorate/example/Main.java @@ -0,0 +1,30 @@ +/** + * Copyright 2018 The original 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.dekorate.example; + +import io.dekorate.kubernetes.annotation.KubernetesApplication; +import io.dekorate.kubernetes.annotation.NodeSelector; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@KubernetesApplication(nodeSelector = @NodeSelector(key = "diskType", value = "ssd")) +@SpringBootApplication +public class Main { + + public static void main(String[] args) { + SpringApplication.run(Main.class, args); + } +} diff --git a/examples/kubernetes-with-nodeselectors-example/src/test/java/io/dekorate/example/KubernetesExampleTest.java b/examples/kubernetes-with-nodeselectors-example/src/test/java/io/dekorate/example/KubernetesExampleTest.java new file mode 100644 index 000000000..cba3c1341 --- /dev/null +++ b/examples/kubernetes-with-nodeselectors-example/src/test/java/io/dekorate/example/KubernetesExampleTest.java @@ -0,0 +1,46 @@ +/** + * Copyright 2018 The original 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.dekorate.example; + +import io.dekorate.utils.Serialization; +import org.junit.jupiter.api.Test; +import io.fabric8.kubernetes.api.model.KubernetesList; +import io.fabric8.kubernetes.api.model.apps.Deployment; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class KubernetesExampleTest { + + @Test + public void shouldContainNodeSelection() { + KubernetesList list = Serialization.unmarshalAsList(KubernetesExampleTest.class.getClassLoader().getResourceAsStream("META-INF/dekorate/kubernetes.yml")); + assertNotNull(list); + assertEquals(1, list.getItems().size()); + Deployment deployment = (Deployment) list.getItems().get(0); + + assertEquals(1, deployment.getSpec().getTemplate().getSpec().getNodeSelector().size()); + + assertTrue(deployment.getSpec().getTemplate().getSpec().getNodeSelector().containsKey("diskType")); + assertTrue("ssd".equals(deployment.getSpec().getTemplate().getSpec().getNodeSelector().get("diskType"))); + } +} diff --git a/examples/pom.xml b/examples/pom.xml index d514b649d..dc3c77755 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -23,6 +23,7 @@ kubernetes-with-configmap-volume-example kubernetes-with-custom-image-name-example kubernetes-with-hostaliases-example + kubernetes-with-nodeselectors-example frameworkless-on-kubernetes-example frameworkless-on-openshift-example spring-boot-on-kubernetes-example diff --git a/tests/feat-kubernetes-nodeselector-annotation/pom.xml b/tests/feat-kubernetes-nodeselector-annotation/pom.xml new file mode 100644 index 000000000..37f54ff22 --- /dev/null +++ b/tests/feat-kubernetes-nodeselector-annotation/pom.xml @@ -0,0 +1,59 @@ + + + + 4.0.0 + + io.dekorate + dekorate-tests + 999-SNAPSHOT + ../ + + + io.dekorate + 999-SNAPSHOT + feat-kubernetes-nodeselector-annotation + Dekorate :: Tests :: Annotations :: Kubernetes :: NodeSelector + + + + io.dekorate + kubernetes-annotations + ${project.version} + + + io.dekorate + dekorate-spring-boot + ${project.version} + + + org.springframework.boot + spring-boot-starter-web + ${version.spring-boot} + + + + io.dekorate + kubernetes-junit + ${project.version} + test + + + + diff --git a/tests/feat-kubernetes-nodeselector-annotation/src/main/java/io/dekorate/example/Controller.java b/tests/feat-kubernetes-nodeselector-annotation/src/main/java/io/dekorate/example/Controller.java new file mode 100644 index 000000000..ca675cb4a --- /dev/null +++ b/tests/feat-kubernetes-nodeselector-annotation/src/main/java/io/dekorate/example/Controller.java @@ -0,0 +1,28 @@ +/** + * Copyright 2018 The original 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.dekorate.example; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class Controller { + + @RequestMapping("/") + public String hello() { + return "Hello world"; + } +} diff --git a/tests/feat-kubernetes-nodeselector-annotation/src/main/java/io/dekorate/example/Main.java b/tests/feat-kubernetes-nodeselector-annotation/src/main/java/io/dekorate/example/Main.java new file mode 100644 index 000000000..4ebd29b42 --- /dev/null +++ b/tests/feat-kubernetes-nodeselector-annotation/src/main/java/io/dekorate/example/Main.java @@ -0,0 +1,29 @@ +/** + * Copyright 2018 The original 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.dekorate.example; + +import io.dekorate.kubernetes.annotation.KubernetesApplication; +import io.dekorate.kubernetes.annotation.NodeSelector; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@KubernetesApplication(nodeSelector = @NodeSelector(key = "diskType", value = "ssd")) +@SpringBootApplication +public class Main { + public static void main(String[] args) { + SpringApplication.run(com.sun.tools.javac.Main.class, args); + } +} diff --git a/tests/feat-kubernetes-nodeselector-annotation/src/test/java/io/dekorate/example/NodeSelectorTest.java b/tests/feat-kubernetes-nodeselector-annotation/src/test/java/io/dekorate/example/NodeSelectorTest.java new file mode 100644 index 000000000..313f9598d --- /dev/null +++ b/tests/feat-kubernetes-nodeselector-annotation/src/test/java/io/dekorate/example/NodeSelectorTest.java @@ -0,0 +1,60 @@ +/** + * Copyright 2018 The original 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.dekorate.example; + +import io.dekorate.utils.Serialization; +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.KubernetesList; +import io.fabric8.kubernetes.api.model.PodSpec; +import io.fabric8.kubernetes.api.model.apps.Deployment; +import org.junit.jupiter.api.Test; + +import java.util.Map; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class NodeSelectorTest { + + @Test + public void shouldContainNodeSelector() { + KubernetesList list = Serialization + .unmarshalAsList( + NodeSelectorTest.class.getClassLoader().getResourceAsStream("META-INF/dekorate/kubernetes.yml")); + assertNotNull(list); + + Deployment d = findFirst(list, Deployment.class).orElseThrow(() -> new IllegalStateException()); + assertNotNull(d); + + PodSpec p = d.getSpec().getTemplate().getSpec(); + assertNotNull(p); + + Map ns = p.getNodeSelector(); + assertNotNull(ns); + + assertTrue(ns.containsKey("diskType")); + assertEquals("ssd", ns.get("diskType")); + } + + Optional findFirst(KubernetesList list, Class t) { + return (Optional) list.getItems().stream() + .filter(i -> t.isInstance(i)) + .findFirst(); + } +} diff --git a/tests/feat-kubernetes-nodeselector-properties/pom.xml b/tests/feat-kubernetes-nodeselector-properties/pom.xml new file mode 100644 index 000000000..fe50112e1 --- /dev/null +++ b/tests/feat-kubernetes-nodeselector-properties/pom.xml @@ -0,0 +1,59 @@ + + + + 4.0.0 + + io.dekorate + dekorate-tests + 999-SNAPSHOT + ../ + + + io.dekorate + 999-SNAPSHOT + feat-kubernetes-nodeselector-properties + Dekorate :: Tests :: Annotations :: Kubernetes :: NodeSelector through application.properties + + + + io.dekorate + kubernetes-annotations + ${project.version} + + + io.dekorate + dekorate-spring-boot + ${project.version} + + + org.springframework.boot + spring-boot-starter-web + ${version.spring-boot} + + + + io.dekorate + kubernetes-junit + ${project.version} + test + + + + diff --git a/tests/feat-kubernetes-nodeselector-properties/src/main/java/io/dekorate/example/Main.java b/tests/feat-kubernetes-nodeselector-properties/src/main/java/io/dekorate/example/Main.java new file mode 100644 index 000000000..cf275a1a9 --- /dev/null +++ b/tests/feat-kubernetes-nodeselector-properties/src/main/java/io/dekorate/example/Main.java @@ -0,0 +1,28 @@ +/** + * Copyright 2018 The original 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.dekorate.example; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Main { + + public static void main(String[] args) { + SpringApplication.run(Main.class, args); + } + +} diff --git a/tests/feat-kubernetes-nodeselector-properties/src/main/resources/application.properties b/tests/feat-kubernetes-nodeselector-properties/src/main/resources/application.properties new file mode 100644 index 000000000..a4750d728 --- /dev/null +++ b/tests/feat-kubernetes-nodeselector-properties/src/main/resources/application.properties @@ -0,0 +1,2 @@ +dekorate.kubernetes.nodeSelector.key = diskType +dekorate.kubernetes.nodeSelector.value = ssd diff --git a/tests/feat-kubernetes-nodeselector-properties/src/test/java/io/dekorate/example/NodeSelectorTest.java b/tests/feat-kubernetes-nodeselector-properties/src/test/java/io/dekorate/example/NodeSelectorTest.java new file mode 100644 index 000000000..313f9598d --- /dev/null +++ b/tests/feat-kubernetes-nodeselector-properties/src/test/java/io/dekorate/example/NodeSelectorTest.java @@ -0,0 +1,60 @@ +/** + * Copyright 2018 The original 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.dekorate.example; + +import io.dekorate.utils.Serialization; +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.KubernetesList; +import io.fabric8.kubernetes.api.model.PodSpec; +import io.fabric8.kubernetes.api.model.apps.Deployment; +import org.junit.jupiter.api.Test; + +import java.util.Map; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class NodeSelectorTest { + + @Test + public void shouldContainNodeSelector() { + KubernetesList list = Serialization + .unmarshalAsList( + NodeSelectorTest.class.getClassLoader().getResourceAsStream("META-INF/dekorate/kubernetes.yml")); + assertNotNull(list); + + Deployment d = findFirst(list, Deployment.class).orElseThrow(() -> new IllegalStateException()); + assertNotNull(d); + + PodSpec p = d.getSpec().getTemplate().getSpec(); + assertNotNull(p); + + Map ns = p.getNodeSelector(); + assertNotNull(ns); + + assertTrue(ns.containsKey("diskType")); + assertEquals("ssd", ns.get("diskType")); + } + + Optional findFirst(KubernetesList list, Class t) { + return (Optional) list.getItems().stream() + .filter(i -> t.isInstance(i)) + .findFirst(); + } +} diff --git a/tests/pom.xml b/tests/pom.xml index 56e984401..f63db1c75 100644 --- a/tests/pom.xml +++ b/tests/pom.xml @@ -99,6 +99,8 @@ feat-overwrite-sidecar-containers issue-1201-zero-replicas issue-1271-containers-empty-in-deployment + feat-kubernetes-nodeselector-annotation + feat-kubernetes-nodeselector-properties