diff --git a/annotations/kind-annotations/pom.xml b/annotations/kind-annotations/pom.xml index 2aa1b0213..1a1eb81d5 100644 --- a/annotations/kind-annotations/pom.xml +++ b/annotations/kind-annotations/pom.xml @@ -43,7 +43,12 @@ limitations under the License. docker-annotations ${project.version} - + + io.dekorate + kubernetes-annotations + ${project.version} + + io.sundr builder-annotations compile @@ -60,7 +65,7 @@ limitations under the License. sundr-codegen-velocity compile true - + io.dekorate dekorate-templates @@ -115,7 +120,7 @@ limitations under the License. - + org.apache.maven.plugins maven-shade-plugin ${version.maven-shade-plugin} @@ -138,7 +143,7 @@ limitations under the License. *:* - io/dekorate/kubernetes/annotation/** + io/dekorate/kind/annotation/** META-INF/MANIFEST.MF @@ -158,14 +163,14 @@ limitations under the License. *:* - io/dekorate/kubernetes/adapter/** - io/dekorate/kubernetes/apt/** - io/dekorate/kubernetes/config/** - io/dekorate/kubernetes/configurator/** - io/dekorate/kubernetes/decorator/** - io/dekorate/kubernetes/manifest/** - io/dekorate/kubernetes/hook/** - io/dekorate/kubernetes/listener/** + io/dekorate/kind/adapter/** + io/dekorate/kind/apt/** + io/dekorate/kind/config/** + io/dekorate/kind/configurator/** + io/dekorate/kind/decorator/** + io/dekorate/kind/manifest/** + io/dekorate/kind/hook/** + io/dekorate/kind/listener/** META-INF/services/* META-INF/MANIFEST.MF @@ -186,14 +191,14 @@ limitations under the License. *:* - io/dekorate/kubernetes/adapter/** - io/dekorate/kubernetes/annotation/** - io/dekorate/kubernetes/config/** - io/dekorate/kubernetes/configurator/** - io/dekorate/kubernetes/decorator/** - io/dekorate/kubernetes/manifest/** - io/dekorate/kubernetes/hook/** - io/dekorate/kubernetes/listener/** + io/dekorate/kind/adapter/** + io/dekorate/kind/annotation/** + io/dekorate/kind/config/** + io/dekorate/kind/configurator/** + io/dekorate/kind/decorator/** + io/dekorate/kind/manifest/** + io/dekorate/kind/hook/** + io/dekorate/kind/listener/** META-INF/services/io.dekorate.* META-INF/MANIFEST.MF @@ -203,6 +208,6 @@ limitations under the License. - + 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 c96506e51..033464767 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 @@ -20,17 +20,37 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import io.dekorate.kubernetes.annotation.ImagePullPolicy; +import io.dekorate.kubernetes.annotation.Port; +import io.dekorate.kubernetes.annotation.ServiceType; import io.dekorate.kubernetes.config.BaseConfig; import io.sundr.builder.annotations.Adapter; import io.sundr.builder.annotations.Buildable; import io.sundr.builder.annotations.Pojo; @Buildable(builderPackage = "io.fabric8.kubernetes.api.builder") -@Pojo(name = "KindLoadConfig", relativePath = "../config", autobox = true, mutable = true, superClass = BaseConfig.class, withStaticBuilderMethod = true, withStaticAdapterMethod = false, adapter = @Adapter(name = "KindLoadConfigAdapter", relativePath = "../adapter", withMapAdapterMethod = true)) +@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 }) @Retention(RetentionPolicy.RUNTIME) public @interface Kind { boolean enabled() default true; + /** + * Image pull policy. + * + * @return The image pull policy. + */ + ImagePullPolicy imagePullPolicy() default ImagePullPolicy.IfNotPresent; + + /** + * The application ports. + */ + Port[] ports() default {}; + + /** + * The type of service that will be generated for the application. + */ + ServiceType serviceType() default ServiceType.NodePort; + } diff --git a/annotations/kind-annotations/src/main/java/io/dekorate/kind/apt/KindAnnotationProcessor.java b/annotations/kind-annotations/src/main/java/io/dekorate/kind/apt/KindAnnotationProcessor.java index 400995190..b9bbcf8f5 100644 --- a/annotations/kind-annotations/src/main/java/io/dekorate/kind/apt/KindAnnotationProcessor.java +++ b/annotations/kind-annotations/src/main/java/io/dekorate/kind/apt/KindAnnotationProcessor.java @@ -15,6 +15,9 @@ */ package io.dekorate.kind.apt; +import static io.dekorate.kind.config.KindConfigGenerator.KIND; + +import java.util.HashSet; import java.util.Set; import javax.annotation.processing.RoundEnvironment; @@ -22,29 +25,27 @@ import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; -import io.dekorate.Logger; -import io.dekorate.LoggerFactory; -import io.dekorate.doc.Description; import io.dekorate.kind.annotation.Kind; import io.dekorate.processor.AbstractAnnotationProcessor; -@Description("Generates kubernetes manifests.") @SupportedAnnotationTypes("io.dekorate.kind.annotation.Kind") public class KindAnnotationProcessor extends AbstractAnnotationProcessor { - private final Logger LOGGER = LoggerFactory.getLogger(); - public boolean process(Set annotations, RoundEnvironment roundEnv) { if (roundEnv.processingOver()) { getSession().close(); return true; } + Set mainClasses = new HashSet<>(); for (TypeElement typeElement : annotations) { for (Element mainClass : roundEnv.getElementsAnnotatedWith(typeElement)) { - LOGGER.info("Found @Kind on: " + mainClass.toString()); - process("kind", mainClass, Kind.class); + mainClasses.add(mainClass); } } + + for (Element mainClass : mainClasses) { + process(KIND, mainClass, Kind.class); + } return false; } } diff --git a/annotations/kind-annotations/src/main/java/io/dekorate/kind/config/DefaultKindConfigGenerator.java b/annotations/kind-annotations/src/main/java/io/dekorate/kind/config/DefaultKindConfigGenerator.java index 83e6f38ef..8a9ff644c 100644 --- a/annotations/kind-annotations/src/main/java/io/dekorate/kind/config/DefaultKindConfigGenerator.java +++ b/annotations/kind-annotations/src/main/java/io/dekorate/kind/config/DefaultKindConfigGenerator.java @@ -25,7 +25,7 @@ public class DefaultKindConfigGenerator implements KindConfigGenerator { public DefaultKindConfigGenerator(ConfigurationRegistry configurationRegistry) { this.configurationRegistry = configurationRegistry; this.configurationRegistry.add(new ApplyKindImageAutoloadConfiguration()); - add(new DefaultConfiguration(KindLoadConfig.newKindLoadConfigBuilderFromDefaults())); + add(new DefaultConfiguration(KindConfig.newKindConfigBuilderFromDefaults())); } @Override diff --git a/annotations/kind-annotations/src/main/java/io/dekorate/kind/config/KindConfigGenerator.java b/annotations/kind-annotations/src/main/java/io/dekorate/kind/config/KindConfigGenerator.java index d27051c0c..d1228590c 100644 --- a/annotations/kind-annotations/src/main/java/io/dekorate/kind/config/KindConfigGenerator.java +++ b/annotations/kind-annotations/src/main/java/io/dekorate/kind/config/KindConfigGenerator.java @@ -22,7 +22,7 @@ import io.dekorate.config.AnnotationConfiguration; import io.dekorate.config.ConfigurationSupplier; import io.dekorate.config.PropertyConfiguration; -import io.dekorate.kind.adapter.KindLoadConfigAdapter; +import io.dekorate.kind.adapter.KindConfigAdapter; import io.dekorate.kubernetes.config.Configuration; public interface KindConfigGenerator extends ConfigurationGenerator, WithProject { @@ -34,20 +34,20 @@ default String getKey() { } default Class getConfigType() { - return KindLoadConfig.class; + return KindConfig.class; } @Override default void addAnnotationConfiguration(Map map) { - add(new AnnotationConfiguration<>(KindLoadConfigAdapter.newBuilder(propertiesMap(map, KindLoadConfig.class)))); + add(new AnnotationConfiguration<>(KindConfigAdapter.newBuilder(propertiesMap(map, KindConfig.class)))); } @Override default void addPropertyConfiguration(Map map) { - add(new PropertyConfiguration<>(KindLoadConfigAdapter.newBuilder(propertiesMap(map, KindLoadConfig.class)))); + add(new PropertyConfiguration<>(KindConfigAdapter.newBuilder(propertiesMap(map, KindConfig.class)))); } - default void add(ConfigurationSupplier config) { + default void add(ConfigurationSupplier config) { getConfigurationRegistry().add(config); } } diff --git a/annotations/kind-annotations/src/main/java/io/dekorate/kind/decorator/ApplyPortToKindServiceDecorator.java b/annotations/kind-annotations/src/main/java/io/dekorate/kind/decorator/ApplyPortToKindServiceDecorator.java new file mode 100644 index 000000000..7dbc3ced1 --- /dev/null +++ b/annotations/kind-annotations/src/main/java/io/dekorate/kind/decorator/ApplyPortToKindServiceDecorator.java @@ -0,0 +1,44 @@ +/** + * 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.kind.decorator; + +import io.dekorate.kubernetes.config.Port; +import io.dekorate.kubernetes.decorator.NamedResourceDecorator; +import io.dekorate.utils.Ports; +import io.fabric8.kubernetes.api.model.ObjectMeta; +import io.fabric8.kubernetes.api.model.ServicePortFluent; + +public class ApplyPortToKindServiceDecorator extends NamedResourceDecorator { + + private final Port port; + + public ApplyPortToKindServiceDecorator(String name, Port port) { + super(name); + this.port = port; + } + + @Override + public void andThenVisit(ServicePortFluent servicePort, ObjectMeta resourceMeta) { + if (port.getNodePort() > 0) { + servicePort.withNodePort(port.getNodePort()); + } else { + servicePort.withNodePort(Ports.calculateNodePort(getName(), port)); + } + } + +} diff --git a/annotations/kind-annotations/src/main/java/io/dekorate/kind/decorator/ApplyServiceTypeToKindServiceDecorator.java b/annotations/kind-annotations/src/main/java/io/dekorate/kind/decorator/ApplyServiceTypeToKindServiceDecorator.java new file mode 100644 index 000000000..2210ac9eb --- /dev/null +++ b/annotations/kind-annotations/src/main/java/io/dekorate/kind/decorator/ApplyServiceTypeToKindServiceDecorator.java @@ -0,0 +1,38 @@ +/** + * 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.kind.decorator; + +import io.dekorate.kind.config.KindConfig; +import io.dekorate.kubernetes.decorator.NamedResourceDecorator; +import io.fabric8.kubernetes.api.model.ObjectMeta; +import io.fabric8.kubernetes.api.model.ServiceSpecFluent; + +public class ApplyServiceTypeToKindServiceDecorator extends NamedResourceDecorator { + + private final KindConfig config; + + public ApplyServiceTypeToKindServiceDecorator(String name, KindConfig config) { + super(name); + this.config = config; + } + + @Override + public void andThenVisit(ServiceSpecFluent spec, ObjectMeta resourceMeta) { + spec.withType(config.getServiceType() != null ? config.getServiceType().name() : "NodePort"); + } +} diff --git a/annotations/kind-annotations/src/main/java/io/dekorate/kind/manifest/KindManifestGenerator.java b/annotations/kind-annotations/src/main/java/io/dekorate/kind/manifest/KindManifestGenerator.java new file mode 100644 index 000000000..99cc2a626 --- /dev/null +++ b/annotations/kind-annotations/src/main/java/io/dekorate/kind/manifest/KindManifestGenerator.java @@ -0,0 +1,65 @@ +package io.dekorate.kind.manifest; + +import java.util.Arrays; + +import io.dekorate.ConfigurationRegistry; +import io.dekorate.ResourceRegistry; +import io.dekorate.kind.config.KindConfig; +import io.dekorate.kind.decorator.ApplyPortToKindServiceDecorator; +import io.dekorate.kind.decorator.ApplyServiceTypeToKindServiceDecorator; +import io.dekorate.kubernetes.config.KubernetesConfig; +import io.dekorate.kubernetes.decorator.AddServiceResourceDecorator; +import io.dekorate.kubernetes.decorator.ApplyImagePullPolicyDecorator; +import io.dekorate.kubernetes.manifest.KubernetesManifestGenerator; + +public class KindManifestGenerator extends KubernetesManifestGenerator { + + private static final String KIND = "kind"; + + public KindManifestGenerator() { + this(new ResourceRegistry(), new ConfigurationRegistry()); + } + + public KindManifestGenerator(ResourceRegistry resourceRegistry, ConfigurationRegistry configurationRegistry) { + super(resourceRegistry, configurationRegistry); + } + + @Override + public int order() { + return 400; + } + + @Override + public String getKey() { + return KIND; + } + + @Override + protected void addDecorators(String group, KubernetesConfig config) { + super.addDecorators(group, config); + if (config.getPorts().length > 0) { + resourceRegistry.decorate(group, new AddServiceResourceDecorator(config)); + } + } + + @Override + public void generate(KubernetesConfig kubernetesConfig) { + initializeRegistry(kubernetesConfig); + addDecorators(KIND, kubernetesConfig); + + configurationRegistry.get(KindConfig.class).ifPresent(c -> { + resourceRegistry.decorate(KIND, new ApplyImagePullPolicyDecorator(kubernetesConfig.getName(), c.getImagePullPolicy())); + resourceRegistry.decorate(KIND, new ApplyServiceTypeToKindServiceDecorator(kubernetesConfig.getName(), c)); + // Check if MinikubeConfig defines port, else fallback to KubernetesConfig + if (c.getPorts().length > 0) { + Arrays.stream(c.getPorts()).forEach(p -> { + resourceRegistry.decorate(KIND, new ApplyPortToKindServiceDecorator(kubernetesConfig.getName(), p)); + }); + } else { + Arrays.stream(kubernetesConfig.getPorts()).forEach(p -> { + resourceRegistry.decorate(KIND, new ApplyPortToKindServiceDecorator(kubernetesConfig.getName(), p)); + }); + } + }); + } +} diff --git a/annotations/kind-annotations/src/main/java/io/dekorate/kind/manifest/KindManifestGeneratorFactory.java b/annotations/kind-annotations/src/main/java/io/dekorate/kind/manifest/KindManifestGeneratorFactory.java new file mode 100644 index 000000000..7115f41f1 --- /dev/null +++ b/annotations/kind-annotations/src/main/java/io/dekorate/kind/manifest/KindManifestGeneratorFactory.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.kind.manifest; + +import io.dekorate.ConfigurationRegistry; +import io.dekorate.ManifestGeneratorFactory; +import io.dekorate.ResourceRegistry; + +public class KindManifestGeneratorFactory implements ManifestGeneratorFactory { + + public KindManifestGenerator create(ResourceRegistry resourceRegistry, ConfigurationRegistry configurationRegistry) { + return new KindManifestGenerator(resourceRegistry, configurationRegistry); + } +} diff --git a/annotations/kind-annotations/src/main/resources/META-INF/services/io.dekorate.ManifestGeneratorFactory b/annotations/kind-annotations/src/main/resources/META-INF/services/io.dekorate.ManifestGeneratorFactory new file mode 100644 index 000000000..4366ce715 --- /dev/null +++ b/annotations/kind-annotations/src/main/resources/META-INF/services/io.dekorate.ManifestGeneratorFactory @@ -0,0 +1 @@ +io.dekorate.kind.manifest.KindManifestGeneratorFactory diff --git a/docs/_data/sidebar.yml b/docs/_data/sidebar.yml index c61e6b53d..e2418a494 100644 --- a/docs/_data/sidebar.yml +++ b/docs/_data/sidebar.yml @@ -21,6 +21,8 @@ url: /docs/openshift - title: Minikube url: /docs/minikube + - title: Kind + url: /docs/kind - title: Tekton url: /docs/tekton - title: Helm diff --git a/docs/configuration-guide.md b/docs/configuration-guide.md index 25f985a5a..e870a83a4 100644 --- a/docs/configuration-guide.md +++ b/docs/configuration-guide.md @@ -126,6 +126,13 @@ The document is structured as follows. | dekorate.minikube.ports | Port[] | The application ports. | {} | | dekorate.minikube.service-type | ServiceType | The type of service that will be generated for the application. | io.dekorate.kubernetes.annotation.ServiceType.NodePort | +### Kind + +| Property | Type | Description | Default Value | +|-- ----------------------------------------------- | ------------------------------- | ----------------------------------------------------------------- | ----------------------- | +| dekorate.kind.image-pull-policy | ImagePullPolicy | Image pull policy. | IfNotPresent | +| dekorate.kind.ports | Port[] | The application ports. | {} | +| dekorate.kind.service-type | ServiceType | The type of service that will be generated for the application. | io.dekorate.kubernetes.annotation.ServiceType.NodePort | ### Global Types The section below describes all the available subtypes. diff --git a/docs/documentation/kind.md b/docs/documentation/kind.md new file mode 100644 index 000000000..c97d26839 --- /dev/null +++ b/docs/documentation/kind.md @@ -0,0 +1,45 @@ +--- +title: Kind +description: Kind +layout: docs +permalink: /docs/kind +--- + +### Kind + +[@Kind](https://raw.githubusercontent.com/dekorateio/dekorate/main/annotations/kind-annotations/src/main/java/io/dekorate/kind/annotation/Kind.java) is a more specialized form of [@KubernetesApplication](https://raw.githubusercontent.com/dekorateio/dekorate/main/annotations/kubernetes-annotations/src/main/java/io/dekorate/kubernetes/annotation/KubernetesApplication.java). +It can be added to your project like: + +```java +import io.dekorate.kind.annotation.Kind; + +@Kind +public class Main { + + public static void main(String[] args) { + //Your application code goes here. + } +} +``` + +When the project gets compiled, the annotation will trigger the generation of a `Deployment` in both `kind.json` and `kind.yml` that +will end up under 'target/classes/META-INF/dekorate'. Also, if the deployment is enabled, it will automate the process of loading images to the cluster +when performing container image builds. + +#### Adding the kind annotation processor to the classpath + +This module can be added to the project using: + +```xml + + io.dekorate + kind-annotations + {{site.data.project.release.current-version}} + +``` + +The `@Kind` annotation can be used in combination with `@KubernetesApplication`. In that case the `@Kind` configuration will take precedence over the one specified using `@KubernetesApplication` in the generated Kind manifests. + +**REMINDER**: A complete reference on all the supported properties can be found in the [configuration options guide]({{site.baseurl}}/configuration-guide). + +Check the Kind example [here](https://github.com/dekorateio/dekorate/tree/main/examples/kind-example). diff --git a/examples/kind-example/Dockerfile b/examples/kind-example/Dockerfile new file mode 100644 index 000000000..b901d2ee8 --- /dev/null +++ b/examples/kind-example/Dockerfile @@ -0,0 +1,4 @@ +FROM openjdk:8u171-alpine3.7 +RUN apk --no-cache add curl +COPY target/*.jar kind-example.jar +CMD java ${JAVA_OPTS} -jar kind-example.jar diff --git a/examples/kind-example/pom.xml b/examples/kind-example/pom.xml new file mode 100644 index 000000000..d2dacd7e6 --- /dev/null +++ b/examples/kind-example/pom.xml @@ -0,0 +1,106 @@ + + 4.0.0 + + io.dekorate + kind-example + 3.1-SNAPSHOT + Dekorate :: Examples :: Kind cluster + + + UTF-8 + UTF-8 + 1.8 + + 3.8.0 + 3.0.0-M3 + 3.0.0-M3 + 3.2.0 + 2.5.12 + + + + + + io.dekorate + kubernetes-spring-starter + ${project.version} + + + io.dekorate + kind-annotations + ${project.version} + + + org.springframework.boot + spring-boot-starter-web + ${version.spring-boot} + + + + org.springframework.boot + spring-boot-starter-actuator + ${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 + + + + org.apache.maven.plugins + maven-failsafe-plugin + ${version.maven-failsafe-plugin} + + + + integration-test + verify + + integration-test + + + **/*IT.class + + + + + + + + diff --git a/examples/kind-example/readme.md b/examples/kind-example/readme.md new file mode 100644 index 000000000..bf5759887 --- /dev/null +++ b/examples/kind-example/readme.md @@ -0,0 +1,95 @@ +# Kind example + +A very simple example that demonstrates the use of `@Kind` in its simplest form. +Check the [Main.java](src/main/java/io/dekorate/example/App.java) which bears the annotation. +To access the `@Kind` annotation you just need to have the following dependency in your +class path: + +``` + + io.dekorate + kind-annotations + ${project.version} + +``` +```java +@Kind +public class App +{ + + public static void main(String[] args) { + //do stuff + } +} +``` + +Users that configure dekorate in the annotationless fashion (via application.properties or application.yaml), can: + +``` +dekorate.kind.ports[0].name=http +dekorate.kind.ports[0].containerPort=8080 +``` + +or + +``` +dekorate: + kind: + ports: + - name: http + containerPort: 8080 +``` + + +Check, if necessary, the [App.java](src/main/java/io/dekorate/example/App.java). + +Compile the project using: + + mvn clean install + + +The Kind module will calculate a few values by default: +- ImagePullPolicy will be set to `IfNotPresent`. + +You can find the generated deployment under: `target/classes/META-INF/dekorate/kind.yml` that should look like: + +``` +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/name: kind-example + app.kubernetes.io/version: 2.8-SNAPSHOT + name: kind-example +spec: + ports: + - name: http + port: 80 + targetPort: 8080 + selector: + app.kubernetes.io/name: kind-example + app.kubernetes.io/version: 2.8-SNAPSHOT + type: NodePort +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/version: 2.8-SNAPSHOT + app.kubernetes.io/name: kind-example + name: kind-example +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/version: 2.8-SNAPSHOT + app.kubernetes.io/name: kind-example + template: + metadata: + labels: + app.kubernetes.io/version: 2.8-SNAPSHOT + app.kubernetes.io/name: kind-example + spec: {} +``` + + diff --git a/examples/kind-example/src/main/java/io/dekorate/example/App.java b/examples/kind-example/src/main/java/io/dekorate/example/App.java new file mode 100644 index 000000000..4ef5a18f4 --- /dev/null +++ b/examples/kind-example/src/main/java/io/dekorate/example/App.java @@ -0,0 +1,30 @@ +package io.dekorate.example; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.InetSocketAddress; + +import org.springframework.boot.autoconfigure.SpringBootApplication; + +import com.sun.net.httpserver.HttpServer; + +@SpringBootApplication +public class App +{ + public static void main(String[] args) throws IOException { + int serverPort = 8080; + HttpServer server = HttpServer.create(new InetSocketAddress(serverPort), 0); + server.createContext("/api/hello", (exchange -> { + String respText = "Hello world from Kind!"; + exchange.sendResponseHeaders(200, respText.getBytes().length); + OutputStream output = exchange.getResponseBody(); + output.write(respText.getBytes()); + output.flush(); + exchange.close(); + })); + server.setExecutor(null); // creates a default executor + System.out.println("Listening in port "+serverPort); + server.start(); + } + +} diff --git a/examples/kind-example/src/main/resources/application.properties b/examples/kind-example/src/main/resources/application.properties new file mode 100644 index 000000000..523dca290 --- /dev/null +++ b/examples/kind-example/src/main/resources/application.properties @@ -0,0 +1,2 @@ +dekorate.kind.imagePullPolicy=Never +dekorate.kubernetes.imagePullPolicy=Always diff --git a/examples/kind-example/src/test/java/io/dekorate/example/KindExampleTest.java b/examples/kind-example/src/test/java/io/dekorate/example/KindExampleTest.java new file mode 100644 index 000000000..9f07f939c --- /dev/null +++ b/examples/kind-example/src/test/java/io/dekorate/example/KindExampleTest.java @@ -0,0 +1,52 @@ +/** + * 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 static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import java.util.Optional; + +import org.junit.jupiter.api.Test; + +import io.dekorate.kubernetes.annotation.ImagePullPolicy; +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.apps.Deployment; + +class KindExampleTest { + + @Test + public void shouldExpectedConfiguration() { + KubernetesList kindList = Serialization.unmarshalAsList(KindExampleTest.class.getClassLoader().getResourceAsStream("META-INF/dekorate/kind.yml")); + assertNotNull(kindList); + Deployment kindDeployment = findFirst(kindList, Deployment.class).orElseThrow(() -> new IllegalStateException("Deployment not found in kind.yml!")); + assertEquals(ImagePullPolicy.Never.name(), kindDeployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImagePullPolicy()); + + KubernetesList kubernetes = Serialization.unmarshalAsList(KindExampleTest.class.getClassLoader().getResourceAsStream("META-INF/dekorate/kubernetes.yml")); + assertNotNull(kubernetes); + Deployment kubernetesDeployment = findFirst(kubernetes, Deployment.class).orElseThrow(() -> new IllegalStateException("Deployment not found in kubernetes.yml!")); + assertEquals(ImagePullPolicy.Always.name(), kubernetesDeployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImagePullPolicy()); + } + + Optional findFirst(KubernetesList list, Class t) { + return (Optional) list.getItems().stream() + .filter(i -> t.isInstance(i)) + .findFirst(); + } +} diff --git a/examples/pom.xml b/examples/pom.xml index f13feee94..ac239246a 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -52,6 +52,7 @@ minikube-example-with-properties helm-on-kubernetes-example helm-on-openshift-example + kind-example