You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ac...@apache.org on 2018/07/18 11:23:32 UTC

[camel] 01/04: CAMEL-11158 - Camel-Kubernetes: Add support for Job resources

This is an automated email from the ASF dual-hosted git repository.

acosentino pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 7a954c3ad13854c3745d3ac99b70f07c307ac6f3
Author: Andrea Cosentino <an...@gmail.com>
AuthorDate: Wed Jul 18 12:24:19 2018 +0200

    CAMEL-11158 - Camel-Kubernetes: Add support for Job resources
---
 .../component/kubernetes/KubernetesConstants.java  |   3 +
 .../component/kubernetes/KubernetesOperations.java |   7 +
 .../kubernetes/job/KubernetesJobComponent.java     |  28 ++++
 .../kubernetes/job/KubernetesJobEndpoint.java      |  51 ++++++
 .../kubernetes/job/KubernetesJobProducer.java      | 173 +++++++++++++++++++++
 .../org/apache/camel/component/kubernetes-job      |  18 +++
 .../producer/KubernetesJobProducerTest.java        | 112 +++++++++++++
 .../KubernetesJobComponentAutoConfiguration.java   | 129 +++++++++++++++
 .../KubernetesJobComponentConfiguration.java       |  50 ++++++
 .../src/main/resources/META-INF/spring.factories   |   4 +-
 10 files changed, 574 insertions(+), 1 deletion(-)

diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/KubernetesConstants.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/KubernetesConstants.java
index 47d546a..3f5b3d9 100644
--- a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/KubernetesConstants.java
+++ b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/KubernetesConstants.java
@@ -60,6 +60,9 @@ public interface KubernetesConstants {
     String KUBERNETES_DEPLOYMENT_REPLICAS = "CamelKubernetesDeploymentReplicas";
     String KUBERNETES_HPA_NAME = "CamelKubernetesHPAName";
     String KUBERNETES_HPA_SPEC = "CamelKubernetesHPASpec";
+    String KUBERNETES_JOB_NAME = "CamelKubernetesJobName";
+    String KUBERNETES_JOB_SPEC = "CamelKubernetesJobSpec";
+    String KUBERNETES_JOB_LABELS = "CamelKubernetesJobLabels";
 
     // Consumer
     String KUBERNETES_EVENT_ACTION = "CamelKubernetesEventAction";
diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/KubernetesOperations.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/KubernetesOperations.java
index ea4666a..936d6a7 100644
--- a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/KubernetesOperations.java
+++ b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/KubernetesOperations.java
@@ -116,4 +116,11 @@ public interface KubernetesOperations {
     String LIST_BUILD_CONFIGS = "listBuildConfigs";
     String LIST_BUILD_CONFIGS_BY_LABELS_OPERATION = "listBuildConfigsByLabels";
     String GET_BUILD_CONFIG_OPERATION = "getBuildConfig";
+    
+    // Secrets
+    String LIST_JOB = "listJob";
+    String LIST_JOB_BY_LABELS_OPERATION = "listJobByLabels";
+    String GET_JOB_OPERATION = "getJob";
+    String CREATE_JOB_OPERATION = "createJob";
+    String DELETE_JOB_OPERATION = "deleteJob";
 }
diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/job/KubernetesJobComponent.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/job/KubernetesJobComponent.java
new file mode 100644
index 0000000..35464bc
--- /dev/null
+++ b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/job/KubernetesJobComponent.java
@@ -0,0 +1,28 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.camel.component.kubernetes.job;
+
+import org.apache.camel.component.kubernetes.AbstractKubernetesComponent;
+import org.apache.camel.component.kubernetes.KubernetesConfiguration;
+
+public class KubernetesJobComponent extends AbstractKubernetesComponent {
+
+    protected KubernetesJobEndpoint doCreateEndpoint(String uri, String remaining, KubernetesConfiguration config) throws Exception {
+        KubernetesJobEndpoint endpoint = new KubernetesJobEndpoint(uri, this, config);
+        return endpoint;
+    }
+}
diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/job/KubernetesJobEndpoint.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/job/KubernetesJobEndpoint.java
new file mode 100644
index 0000000..4d920da
--- /dev/null
+++ b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/job/KubernetesJobEndpoint.java
@@ -0,0 +1,51 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.camel.component.kubernetes.job;
+
+import org.apache.camel.Consumer;
+import org.apache.camel.Processor;
+import org.apache.camel.Producer;
+import org.apache.camel.component.kubernetes.AbstractKubernetesEndpoint;
+import org.apache.camel.component.kubernetes.KubernetesConfiguration;
+import org.apache.camel.spi.UriEndpoint;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The Kubernetes Jobs component provides a producer to execute kubernetes job operations
+ */
+@UriEndpoint(firstVersion = "2.23.0", scheme = "kubernetes-job", title = "Kubernetes Job",
+    syntax = "kubernetes-job:masterUrl", label = "container,cloud,paas")
+public class KubernetesJobEndpoint extends AbstractKubernetesEndpoint {
+
+    private static final Logger LOG = LoggerFactory.getLogger(KubernetesJobEndpoint.class);
+
+    public KubernetesJobEndpoint(String uri, KubernetesJobComponent component, KubernetesConfiguration config) {
+        super(uri, component, config);
+    }
+
+    @Override
+    public Producer createProducer() throws Exception {
+        return new KubernetesJobProducer(this);
+    }
+
+    @Override
+    public Consumer createConsumer(Processor processor) throws Exception {
+        throw new IllegalArgumentException("The kubernetes-job doesn't support consumer");
+    }
+
+}
diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/job/KubernetesJobProducer.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/job/KubernetesJobProducer.java
new file mode 100644
index 0000000..0566e3f
--- /dev/null
+++ b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/job/KubernetesJobProducer.java
@@ -0,0 +1,173 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.camel.component.kubernetes.job;
+
+import java.util.Map;
+
+import io.fabric8.kubernetes.api.model.batch.Job;
+import io.fabric8.kubernetes.api.model.batch.JobBuilder;
+import io.fabric8.kubernetes.api.model.batch.JobList;
+import io.fabric8.kubernetes.api.model.batch.JobSpec;
+import io.fabric8.kubernetes.client.Watch;
+import io.fabric8.kubernetes.client.Watcher;
+import io.fabric8.kubernetes.client.dsl.FilterWatchListMultiDeletable;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.component.kubernetes.AbstractKubernetesEndpoint;
+import org.apache.camel.component.kubernetes.KubernetesConstants;
+import org.apache.camel.component.kubernetes.KubernetesOperations;
+import org.apache.camel.impl.DefaultProducer;
+import org.apache.camel.util.MessageHelper;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class KubernetesJobProducer extends DefaultProducer {
+
+    private static final Logger LOG = LoggerFactory.getLogger(KubernetesJobProducer.class);
+
+    public KubernetesJobProducer(AbstractKubernetesEndpoint endpoint) {
+        super(endpoint);
+    }
+
+    @Override
+    public AbstractKubernetesEndpoint getEndpoint() {
+        return (AbstractKubernetesEndpoint)super.getEndpoint();
+    }
+
+    @Override
+    public void process(Exchange exchange) throws Exception {
+        String operation;
+
+        if (ObjectHelper.isEmpty(getEndpoint().getKubernetesConfiguration().getOperation())) {
+            operation = exchange.getIn().getHeader(KubernetesConstants.KUBERNETES_OPERATION, String.class);
+        } else {
+            operation = getEndpoint().getKubernetesConfiguration().getOperation();
+        }
+
+        switch (operation) {
+
+        case KubernetesOperations.LIST_JOB:
+            doList(exchange, operation);
+            break;
+
+        case KubernetesOperations.LIST_JOB_BY_LABELS_OPERATION:
+            doListJobByLabel(exchange, operation);
+            break;
+
+        case KubernetesOperations.GET_JOB_OPERATION:
+            doGetJob(exchange, operation);
+            break;
+
+        case KubernetesOperations.CREATE_JOB_OPERATION:
+            doCreateJob(exchange, operation);
+            break;
+
+        case KubernetesOperations.DELETE_JOB_OPERATION:
+        	doDeleteJob(exchange, operation);
+            break;
+
+        default:
+            throw new IllegalArgumentException("Unsupported operation " + operation);
+        }
+    }
+
+    protected void doList(Exchange exchange, String operation) throws Exception {
+        JobList jobList = getEndpoint().getKubernetesClient().batch().jobs().list();
+
+        MessageHelper.copyHeaders(exchange.getIn(), exchange.getOut(), true);
+        exchange.getOut().setBody(jobList.getItems());
+    }
+
+    protected void doListJobByLabel(Exchange exchange, String operation) {
+        Map<String, String> labels = exchange.getIn().getHeader(KubernetesConstants.KUBERNETES_JOB_LABELS, Map.class);
+        if (ObjectHelper.isEmpty(labels)) {
+            LOG.error("Get Job by labels require specify a labels set");
+            throw new IllegalArgumentException("Get Job by labels require specify a labels set");
+        }
+
+        FilterWatchListMultiDeletable<Job, JobList, Boolean, Watch, Watcher<Job>> jobs = getEndpoint()
+            .getKubernetesClient().batch().jobs();
+        for (Map.Entry<String, String> entry : labels.entrySet()) {
+            jobs.withLabel(entry.getKey(), entry.getValue());
+        }
+        JobList jobList = jobs.list();
+
+        MessageHelper.copyHeaders(exchange.getIn(), exchange.getOut(), true);
+        exchange.getOut().setBody(jobList.getItems());
+    }
+
+    protected void doGetJob(Exchange exchange, String operation) throws Exception {
+        Job job = null;
+        String jobName = exchange.getIn().getHeader(KubernetesConstants.KUBERNETES_JOB_NAME, String.class);
+        String namespaceName = exchange.getIn().getHeader(KubernetesConstants.KUBERNETES_NAMESPACE_NAME, String.class);
+        if (ObjectHelper.isEmpty(jobName)) {
+            LOG.error("Get a specific job require specify a job name");
+            throw new IllegalArgumentException("Get a specific job require specify a job name");
+        }
+        if (ObjectHelper.isEmpty(namespaceName)) {
+            LOG.error("Get a specific job require specify a namespace name");
+            throw new IllegalArgumentException("Get a specific job require specify a namespace name");
+        }
+        job = getEndpoint().getKubernetesClient().batch().jobs().inNamespace(namespaceName).withName(jobName).get();
+
+        MessageHelper.copyHeaders(exchange.getIn(), exchange.getOut(), true);
+        exchange.getOut().setBody(job);
+    }
+
+    protected void doCreateJob(Exchange exchange, String operation) throws Exception {
+    	Job job = null;
+        String jobName = exchange.getIn().getHeader(KubernetesConstants.KUBERNETES_JOB_NAME, String.class);
+        String namespaceName = exchange.getIn().getHeader(KubernetesConstants.KUBERNETES_NAMESPACE_NAME, String.class);
+        JobSpec jobSpec = exchange.getIn().getHeader(KubernetesConstants.KUBERNETES_JOB_SPEC, JobSpec.class);
+        if (ObjectHelper.isEmpty(jobName)) {
+            LOG.error("Create a specific job require specify a job name");
+            throw new IllegalArgumentException("Create a specific job require specify a job name");
+        }
+        if (ObjectHelper.isEmpty(namespaceName)) {
+            LOG.error("Create a specific job require specify a namespace name");
+            throw new IllegalArgumentException("Create a specific job require specify a namespace name");
+        }
+        if (ObjectHelper.isEmpty(jobSpec)) {
+            LOG.error("Create a specific job require specify a hpa spec bean");
+            throw new IllegalArgumentException("Create a specific job require specify a hpa spec bean");
+        }
+        Map<String, String> labels = exchange.getIn().getHeader(KubernetesConstants.KUBERNETES_JOB_LABELS, Map.class);
+        Job jobCreating = new JobBuilder().withNewMetadata().withName(jobName).withLabels(labels).endMetadata().withSpec(jobSpec).build();
+        job = getEndpoint().getKubernetesClient().batch().jobs().inNamespace(namespaceName).create(jobCreating);
+
+        MessageHelper.copyHeaders(exchange.getIn(), exchange.getOut(), true);
+        exchange.getOut().setBody(job);
+    }
+
+    protected void doDeleteJob(Exchange exchange, String operation) throws Exception {
+        String jobName = exchange.getIn().getHeader(KubernetesConstants.KUBERNETES_JOB_NAME, String.class);
+        String namespaceName = exchange.getIn().getHeader(KubernetesConstants.KUBERNETES_NAMESPACE_NAME, String.class);
+        if (ObjectHelper.isEmpty(jobName)) {
+            LOG.error("Delete a specific job require specify a job name");
+            throw new IllegalArgumentException("Delete a specific job require specify a job name");
+        }
+        if (ObjectHelper.isEmpty(namespaceName)) {
+            LOG.error("Delete a specific job require specify a namespace name");
+            throw new IllegalArgumentException("Delete a specific job require specify a namespace name");
+        }
+
+        getEndpoint().getKubernetesClient().batch().jobs().inNamespace(namespaceName).withName(jobName).delete();
+
+        MessageHelper.copyHeaders(exchange.getIn(), exchange.getOut(), true);
+    }
+}
diff --git a/components/camel-kubernetes/src/main/resources/META-INF/services/org/apache/camel/component/kubernetes-job b/components/camel-kubernetes/src/main/resources/META-INF/services/org/apache/camel/component/kubernetes-job
new file mode 100644
index 0000000..eba1856
--- /dev/null
+++ b/components/camel-kubernetes/src/main/resources/META-INF/services/org/apache/camel/component/kubernetes-job
@@ -0,0 +1,18 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+#
+
+class=org.apache.camel.component.kubernetes.job.KubernetesJobComponent
diff --git a/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/producer/KubernetesJobProducerTest.java b/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/producer/KubernetesJobProducerTest.java
new file mode 100644
index 0000000..5f6035c
--- /dev/null
+++ b/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/producer/KubernetesJobProducerTest.java
@@ -0,0 +1,112 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.camel.component.kubernetes.producer;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import io.fabric8.kubernetes.api.model.HorizontalPodAutoscaler;
+import io.fabric8.kubernetes.api.model.HorizontalPodAutoscalerBuilder;
+import io.fabric8.kubernetes.api.model.Secret;
+import io.fabric8.kubernetes.api.model.batch.Job;
+import io.fabric8.kubernetes.api.model.batch.JobBuilder;
+import io.fabric8.kubernetes.api.model.batch.JobListBuilder;
+import io.fabric8.kubernetes.client.server.mock.KubernetesServer;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.kubernetes.KubernetesConstants;
+import org.apache.camel.component.kubernetes.KubernetesTestSupport;
+import org.apache.camel.impl.JndiRegistry;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class KubernetesJobProducerTest extends KubernetesTestSupport {
+
+    @Rule
+    public KubernetesServer server = new KubernetesServer();
+
+    @Override
+    protected JndiRegistry createRegistry() throws Exception {
+        JndiRegistry registry = super.createRegistry();
+        registry.bind("kubernetesClient", server.getClient());
+        return registry;
+    }
+
+    @Test
+    public void listTest() throws Exception {
+        server.expect().withPath("/apis/batch/v1/namespaces/test/jobs").andReturn(200, new JobListBuilder().addNewItem().and().addNewItem().and().addNewItem().and().build()).once();
+        List<Secret> result = template.requestBody("direct:list", "", List.class);
+
+        assertEquals(3, result.size());
+    }
+
+    @Test
+    public void listByLabelsTest() throws Exception {
+        server.expect().withPath("/apis/batch/v1/namespaces/test/jobs?labelSelector=" + toUrlEncoded("key1=value1,key2=value2"))
+            .andReturn(200, new JobListBuilder().addNewItem().and().addNewItem().and().addNewItem().and().build()).once();
+        Exchange ex = template.request("direct:listByLabels", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) throws Exception {
+                Map<String, String> labels = new HashMap<>();
+                labels.put("key1", "value1");
+                labels.put("key2", "value2");
+                exchange.getIn().setHeader(KubernetesConstants.KUBERNETES_JOB_LABELS, labels);
+            }
+        });
+
+        List<Job> result = ex.getOut().getBody(List.class);
+
+        assertEquals(3, result.size());
+    }
+
+    @Test
+    public void getJobTest() throws Exception {
+        Job sc1 = new JobBuilder().withNewMetadata().withName("sc1").withNamespace("test").and().build();
+
+        server.expect().withPath("/apis/batch/v1/namespaces/test/jobs/sc1").andReturn(200, sc1).once();
+        Exchange ex = template.request("direct:get", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setHeader(KubernetesConstants.KUBERNETES_NAMESPACE_NAME, "test");
+                exchange.getIn().setHeader(KubernetesConstants.KUBERNETES_JOB_NAME, "sc1");
+            }
+        });
+
+        Job result = ex.getOut().getBody(Job.class);
+
+        assertNotNull(result);
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:list").to("kubernetes-job:///?kubernetesClient=#kubernetesClient&operation=listJob");
+                from("direct:listByLabels").to("kubernetes-job:///?kubernetesClient=#kubernetesClient&operation=listJobByLabels");
+                from("direct:get").to("kubernetes-job:///?kubernetesClient=#kubernetesClient&operation=getJob");
+                from("direct:create").to("kubernetes-job:///?kubernetesClient=#kubernetesClient&operation=createJob");
+                from("direct:delete").to("kubernetes-job:///?kubernetesClient=#kubernetesClient&operation=deleteJob");
+            }
+        };
+    }
+}
diff --git a/platforms/spring-boot/components-starter/camel-kubernetes-starter/src/main/java/org/apache/camel/component/kubernetes/job/springboot/KubernetesJobComponentAutoConfiguration.java b/platforms/spring-boot/components-starter/camel-kubernetes-starter/src/main/java/org/apache/camel/component/kubernetes/job/springboot/KubernetesJobComponentAutoConfiguration.java
new file mode 100644
index 0000000..97caa65
--- /dev/null
+++ b/platforms/spring-boot/components-starter/camel-kubernetes-starter/src/main/java/org/apache/camel/component/kubernetes/job/springboot/KubernetesJobComponentAutoConfiguration.java
@@ -0,0 +1,129 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.camel.component.kubernetes.job.springboot;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Generated;
+import org.apache.camel.CamelContext;
+import org.apache.camel.component.kubernetes.job.KubernetesJobComponent;
+import org.apache.camel.spi.ComponentCustomizer;
+import org.apache.camel.spi.HasId;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.spring.boot.ComponentConfigurationProperties;
+import org.apache.camel.spring.boot.util.CamelPropertiesHelper;
+import org.apache.camel.spring.boot.util.ConditionalOnCamelContextAndAutoConfigurationBeans;
+import org.apache.camel.spring.boot.util.GroupCondition;
+import org.apache.camel.spring.boot.util.HierarchicalPropertiesEvaluator;
+import org.apache.camel.util.IntrospectionSupport;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Conditional;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Lazy;
+
+/**
+ * Generated by camel-package-maven-plugin - do not edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.SpringBootAutoConfigurationMojo")
+@Configuration
+@Conditional({ConditionalOnCamelContextAndAutoConfigurationBeans.class,
+        KubernetesJobComponentAutoConfiguration.GroupConditions.class})
+@AutoConfigureAfter(CamelAutoConfiguration.class)
+@EnableConfigurationProperties({ComponentConfigurationProperties.class,
+        KubernetesJobComponentConfiguration.class})
+public class KubernetesJobComponentAutoConfiguration {
+
+    private static final Logger LOGGER = LoggerFactory
+            .getLogger(KubernetesJobComponentAutoConfiguration.class);
+    @Autowired
+    private ApplicationContext applicationContext;
+    @Autowired
+    private CamelContext camelContext;
+    @Autowired
+    private KubernetesJobComponentConfiguration configuration;
+    @Autowired(required = false)
+    private List<ComponentCustomizer<KubernetesJobComponent>> customizers;
+
+    static class GroupConditions extends GroupCondition {
+        public GroupConditions() {
+            super("camel.component", "camel.component.kubernetes-job");
+        }
+    }
+
+    @Lazy
+    @Bean(name = "kubernetes-job-component")
+    @ConditionalOnMissingBean(KubernetesJobComponent.class)
+    public KubernetesJobComponent configureKubernetesJobComponent()
+            throws Exception {
+        KubernetesJobComponent component = new KubernetesJobComponent();
+        component.setCamelContext(camelContext);
+        Map<String, Object> parameters = new HashMap<>();
+        IntrospectionSupport.getProperties(configuration, parameters, null,
+                false);
+        for (Map.Entry<String, Object> entry : parameters.entrySet()) {
+            Object value = entry.getValue();
+            Class<?> paramClass = value.getClass();
+            if (paramClass.getName().endsWith("NestedConfiguration")) {
+                Class nestedClass = null;
+                try {
+                    nestedClass = (Class) paramClass.getDeclaredField(
+                            "CAMEL_NESTED_CLASS").get(null);
+                    HashMap<String, Object> nestedParameters = new HashMap<>();
+                    IntrospectionSupport.getProperties(value, nestedParameters,
+                            null, false);
+                    Object nestedProperty = nestedClass.newInstance();
+                    CamelPropertiesHelper.setCamelProperties(camelContext,
+                            nestedProperty, nestedParameters, false);
+                    entry.setValue(nestedProperty);
+                } catch (NoSuchFieldException e) {
+                }
+            }
+        }
+        CamelPropertiesHelper.setCamelProperties(camelContext, component,
+                parameters, false);
+        if (ObjectHelper.isNotEmpty(customizers)) {
+            for (ComponentCustomizer<KubernetesJobComponent> customizer : customizers) {
+                boolean useCustomizer = (customizer instanceof HasId)
+                        ? HierarchicalPropertiesEvaluator.evaluate(
+                                applicationContext.getEnvironment(),
+                                "camel.component.customizer",
+                                "camel.component.kubernetes-job.customizer",
+                                ((HasId) customizer).getId())
+                        : HierarchicalPropertiesEvaluator.evaluate(
+                                applicationContext.getEnvironment(),
+                                "camel.component.customizer",
+                                "camel.component.kubernetes-job.customizer");
+                if (useCustomizer) {
+                    LOGGER.debug("Configure component {}, with customizer {}",
+                            component, customizer);
+                    customizer.customize(component);
+                }
+            }
+        }
+        return component;
+    }
+}
\ No newline at end of file
diff --git a/platforms/spring-boot/components-starter/camel-kubernetes-starter/src/main/java/org/apache/camel/component/kubernetes/job/springboot/KubernetesJobComponentConfiguration.java b/platforms/spring-boot/components-starter/camel-kubernetes-starter/src/main/java/org/apache/camel/component/kubernetes/job/springboot/KubernetesJobComponentConfiguration.java
new file mode 100644
index 0000000..9524594
--- /dev/null
+++ b/platforms/spring-boot/components-starter/camel-kubernetes-starter/src/main/java/org/apache/camel/component/kubernetes/job/springboot/KubernetesJobComponentConfiguration.java
@@ -0,0 +1,50 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.camel.component.kubernetes.job.springboot;
+
+import javax.annotation.Generated;
+import org.apache.camel.spring.boot.ComponentConfigurationPropertiesCommon;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * The Kubernetes Jobs component provides a producer to execute kubernetes job
+ * operations
+ * 
+ * Generated by camel-package-maven-plugin - do not edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.SpringBootAutoConfigurationMojo")
+@ConfigurationProperties(prefix = "camel.component.kubernetes-job")
+public class KubernetesJobComponentConfiguration
+        extends
+            ComponentConfigurationPropertiesCommon {
+
+    /**
+     * Whether the component should resolve property placeholders on itself when
+     * starting. Only properties which are of String type can use property
+     * placeholders.
+     */
+    private Boolean resolvePropertyPlaceholders = true;
+
+    public Boolean getResolvePropertyPlaceholders() {
+        return resolvePropertyPlaceholders;
+    }
+
+    public void setResolvePropertyPlaceholders(
+            Boolean resolvePropertyPlaceholders) {
+        this.resolvePropertyPlaceholders = resolvePropertyPlaceholders;
+    }
+}
\ No newline at end of file
diff --git a/platforms/spring-boot/components-starter/camel-kubernetes-starter/src/main/resources/META-INF/spring.factories b/platforms/spring-boot/components-starter/camel-kubernetes-starter/src/main/resources/META-INF/spring.factories
index 0a8bdfd..2bb6766 100644
--- a/platforms/spring-boot/components-starter/camel-kubernetes-starter/src/main/resources/META-INF/spring.factories
+++ b/platforms/spring-boot/components-starter/camel-kubernetes-starter/src/main/resources/META-INF/spring.factories
@@ -33,7 +33,9 @@ org.apache.camel.component.kubernetes.deployments.springboot.KubernetesDeploymen
 org.apache.camel.component.kubernetes.service_accounts.springboot.KubernetesServiceAccountsComponentAutoConfiguration,\
 org.apache.camel.component.openshift.builds.springboot.OpenshiftBuildsComponentAutoConfiguration,\
 org.apache.camel.component.openshift.build_configs.springboot.OpenshiftBuildConfigsComponentAutoConfiguration,\
-org.apache.camel.component.kubernetes.hpa.springboot.KubernetesHPAComponentAutoConfiguration
+org.apache.camel.component.kubernetes.hpa.springboot.KubernetesHPAComponentAutoConfiguration,\
+org.apache.camel.component.kubernetes.job.springboot.KubernetesJobComponentAutoConfiguration
+