Skip to content

Commit

Permalink
Fix fabric8io#2284: Support running/creating a particular image in a …
Browse files Browse the repository at this point in the history
…Pod operation

Add support for client.run() with which we should be able to create
Pod/Deployments just based on few parameters. For example, creating
a simple pod should be like:

client.run().pods().withName("nginx").withImage("nginx:1.39").done()
  • Loading branch information
rohanKanojia committed Aug 25, 2020
1 parent d31483b commit 9da61d4
Show file tree
Hide file tree
Showing 20 changed files with 1,128 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -27,6 +27,7 @@
* Fix #2311: Add Support for creating bootstrap project template
* Fix #2287: Add support for V1 and V1Beta1 CustomResourceDefinition
* Fix #2319: Create Config without using auto-configure functionality or setting env variables
* Fix #2284: Supports create and run a particular image in a pod operation using client

_**Note**_: Some classes have been moved to other packages:
- CustomResourceDefinition has been moved to `io.fabric8.kubernetes.api.model.apiextensions.v1` and `io.fabric8.kubernetes.api.model.apiextensions.v1beta1`
Expand Down
56 changes: 56 additions & 0 deletions doc/CHEATSHEET.md
Expand Up @@ -40,6 +40,8 @@ This document contains common usages of different resources using Fabric8 Kubern
* [Delete Options](#delete-options)
* [Watch Options](#watch-options)
* [Serializing to yaml](#serializing-to-yaml)
* [Running a Pod](#running-a-pod)
* [Running a Deployment](#running-a-deployment)

* [OpenShift Client DSL Usage](#openshift-client-dsl-usage)
* [Initializing OpenShift Client](#initializing-openshift-client)
Expand Down Expand Up @@ -2288,6 +2290,60 @@ String myPodAsYaml = SerializationUtils.dumpAsYaml(myPod);
String myPodAsYamlWithoutRuntimeState = SerializationUtils.dumpWithoutRuntimeStateAsYaml(myPod);
```

#### Running a Pod
Kubernetes Client also provides mechanism similar to `kubectl run` in which you can spin a `Pod` just by specifying it's image and name:
- Running a `Pod` by just providing image and name:
```
try (KubernetesClient client = new DefaultKubernetesClient()) {
client.run().pods().inNamespace("default")
.withName("hazelcast")
.withImage("hazelcast/hazelcast:3.12.9")
.done();
}
```
- You can also provide slighly complex configuration with `withGeneratorConfig` method in which you can specify labels, environment variables, ports etc:
```
try (KubernetesClient client = new DefaultKubernetesClient()) {
client.run().pods().inNamespace("default")
.inNamespace("default")
.withRunConfig(new GeneratorRunConfig.Builder()
.withName("hazelcast")
.withImage("hazelcast/hazelcast:latest")
.withPort(5701)
.withLabels(Collections.singletonMap("rohan", "kumar"))
.withEnv(Collections.singletonMap("KUBERNETES_TEST", "fabric8"))
.build())
.done();
}
```

#### Running a Deployment
Similar to `client.run().pods()`, you can also do `client.run().deployments()` with a very similar syntax, the only difference is that `Deployment` would be generated instead of a `Pod`:
- Create a `Deployment` with just an image and name:
```
try (KubernetesClient client = new DefaultKubernetesClient()) {
client.run().deployments().inNamespace("default")
.withName("nginx")
.withImage("nginx:latest")
.done();
}
```
- Create `Deployment` with `GeneratorRunConfig`:
```
try (KubernetesClient client = new DefaultKubernetesClient()) {
client.run().deployments().inNamespace("default")
.withRunConfig(new GeneratorRunConfig.Builder()
.withName("nginx")
.withReplicas(1)
.withImage("nginx:latest")
.withPort(5701)
.withLabels(Collections.singletonMap("foo", "bar"))
.withEnv(Collections.singletonMap("KUBERNETES_TEST", "fabric8"))
.build())
.done();
}
```

### OpenShift Client DSL Usage

Fabric8 Kubernetes Client also has an extension for OpenShift. It is pretty much the same as Kubernetes Client but has support for some additional OpenShift resources.
Expand Down
Expand Up @@ -261,6 +261,11 @@ public MixedOperation<LimitRange, LimitRangeList, DoneableLimitRange, Resource<L
return delegate.limitRanges();
}

@Override
public GeneratorRunDSL run() {
return delegate.run();
}

@Override
public <C> Boolean isAdaptable(Class<C> type) {
return delegate.isAdaptable(type);
Expand Down
Expand Up @@ -439,4 +439,9 @@ public LeaderElectorBuilder<NamespacedKubernetesClient> leaderElector() {
public MixedOperation<Lease, LeaseList, DoneableLease, Resource<Lease, DoneableLease>> leases() {
return new LeaseOperationsImpl(httpClient, getConfiguration());
}

@Override
public GeneratorRunDSL run() {
return adapt(GeneratorRunClient.class);
}
}
@@ -0,0 +1,39 @@
/**
* Copyright (C) 2015 Red Hat, Inc.
*
* 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.fabric8.kubernetes.client;

import io.fabric8.kubernetes.client.dsl.GeneratorRunDSL;
import io.fabric8.kubernetes.client.utils.DeploymentGeneratorImpl;
import io.fabric8.kubernetes.client.utils.GeneratorRunConfig;
import io.fabric8.kubernetes.client.utils.PodGeneratorImpl;
import okhttp3.OkHttpClient;

public class GeneratorRunClient extends BaseClient implements GeneratorRunDSL {

public GeneratorRunClient(OkHttpClient httpClient, final Config config) {
super(httpClient, config);
}

@Override
public PodGeneratorImpl pods() {
return new PodGeneratorImpl(httpClient, getConfiguration(), null, new GeneratorRunConfig.Builder());
}

@Override
public DeploymentGeneratorImpl deployments() {
return new DeploymentGeneratorImpl(httpClient, getConfiguration(), null, new GeneratorRunConfig.Builder());
}
}
@@ -0,0 +1,36 @@
/**
* Copyright (C) 2015 Red Hat, Inc.
*
* 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.fabric8.kubernetes.client;

import okhttp3.OkHttpClient;

public class GeneratorRunExtensionAdapter extends APIGroupExtensionAdapter<GeneratorRunClient> {

@Override
protected String getAPIGroupName() {
return "run";
}

@Override
public Class<GeneratorRunClient> getExtensionType() {
return GeneratorRunClient.class;
}

@Override
protected GeneratorRunClient newInstance(Client client) {
return new GeneratorRunClient(client.adapt(OkHttpClient.class), client.getConfiguration());
}
}
Expand Up @@ -514,4 +514,12 @@ public interface KubernetesClient extends Client {
* @return V1APIGroupDSL DSL object for core v1 resources
*/
V1APIGroupDSL v1();

/**
* Utility method for quickly creating a Pod or Deployment based on
* some opinionated defaults.
*
* @return {@link GeneratorRunDSL} for run generator options
*/
GeneratorRunDSL run();
}
@@ -0,0 +1,36 @@
/**
* Copyright (C) 2015 Red Hat, Inc.
*
* 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.fabric8.kubernetes.client.dsl;

import io.fabric8.kubernetes.client.Client;
import io.fabric8.kubernetes.client.utils.DeploymentGeneratorImpl;
import io.fabric8.kubernetes.client.utils.PodGeneratorImpl;

public interface GeneratorRunDSL extends Client {
/**
* Run a Pod (core/v1)
*
* @return returns {@link PodGeneratorImpl} that allows you to run a pod based on few parameters(e.g. name, image etc)
*/
PodGeneratorImpl pods();

/**
* Run a Deployment (apps/v1)
*
* @return returns {@link DeploymentGeneratorImpl} that allows you to run a Deployment based on few parameters(e.g. name, image etc)
*/
DeploymentGeneratorImpl deployments();
}
Expand Up @@ -102,6 +102,7 @@
import io.fabric8.kubernetes.client.dsl.Createable;
import io.fabric8.kubernetes.client.dsl.ExtensionsAPIGroupDSL;
import io.fabric8.kubernetes.client.dsl.FunctionCallable;
import io.fabric8.kubernetes.client.dsl.GeneratorRunDSL;
import io.fabric8.kubernetes.client.dsl.KubernetesListMixedOperation;
import io.fabric8.kubernetes.client.dsl.MetricAPIGroupDSL;
import io.fabric8.kubernetes.client.dsl.MixedOperation;
Expand Down Expand Up @@ -557,4 +558,9 @@ public NamespacedKubernetesClient inNamespace(String name) {
public FunctionCallable<NamespacedKubernetesClient> withRequestConfig(RequestConfig requestConfig) {
return delegate.withRequestConfig(requestConfig);
}

@Override
public GeneratorRunDSL run() {
return delegate.run();
}
}
@@ -0,0 +1,94 @@
/**
* Copyright (C) 2015 Red Hat, Inc.
*
* 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.fabric8.kubernetes.client.utils;

import io.fabric8.kubernetes.api.model.apps.Deployment;
import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder;
import io.fabric8.kubernetes.client.Config;
import io.fabric8.kubernetes.client.dsl.internal.apps.v1.DeploymentOperationsImpl;
import okhttp3.OkHttpClient;

public class DeploymentGeneratorImpl {
private final OkHttpClient client;
private final Config config;
private final String namespace;
private final GeneratorRunConfig.Builder generatorRunConfigBuilder;

public DeploymentGeneratorImpl(OkHttpClient client, Config config, String namespace, GeneratorRunConfig.Builder runConfig) {
this.client = client;
this.config = config;
this.namespace = namespace;
this.generatorRunConfigBuilder = runConfig;
}

/**
* Specify namespace for the operation
*
* @param namespace namespace in which resource needs to be created
* @return {@link DeploymentGeneratorImpl} with injected namespace
*/
public DeploymentGeneratorImpl inNamespace(String namespace) {
return new DeploymentGeneratorImpl(this.client, this.config, namespace, this.generatorRunConfigBuilder);
}

/**
* Specify image for the Deployment
*
* @param image image as a string
* @return {@link DeploymentGeneratorImpl} with image injected into {@link GeneratorRunConfig}
*/
public DeploymentGeneratorImpl withImage(String image) {
return new DeploymentGeneratorImpl(this.client, this.config, namespace, this.generatorRunConfigBuilder.withImage(image));
}

/**
* Specify name for the Deployment
*
* @param name name of the pod to be created
* @return {@link DeploymentGeneratorImpl} with name injected into {@link GeneratorRunConfig}
*/
public DeploymentGeneratorImpl withName(String name) {
return new DeploymentGeneratorImpl(this.client, this.config, namespace, this.generatorRunConfigBuilder.withName(name));
}

/**
* Specify complex configuration for Deployment creating using {@link GeneratorRunConfig}
*
* @param generatorRunConfig {@link GeneratorRunConfig} which allows to provide configuring environment variables, labels, resources, ports etc
* @return {@link DeploymentGeneratorImpl} with specified configuration
*/
public DeploymentGeneratorImpl withRunConfig(GeneratorRunConfig generatorRunConfig) {
return new DeploymentGeneratorImpl(this.client, this.config, namespace, new GeneratorRunConfig.Builder(generatorRunConfig));
}

/**
* Apply the {@link GeneratorRunConfig} onto the cluster and create Deployment
*
* @return Deployment which got created from the operation
*/
public Deployment done() {
DeploymentOperationsImpl podOperations = new DeploymentOperationsImpl(client, config, namespace);
return podOperations.create(convertRunConfigIntoDeployment());
}

protected Deployment convertRunConfigIntoDeployment() {
GeneratorRunConfig finalGeneratorConfig = generatorRunConfigBuilder.build();
return new DeploymentBuilder()
.withMetadata(GeneratorRunConfigUtil.getObjectMetadataFromRunConfig(finalGeneratorConfig))
.withSpec(GeneratorRunConfigUtil.getDeploymentSpecFromRunConfig(finalGeneratorConfig))
.build();
}
}

0 comments on commit 9da61d4

Please sign in to comment.