Fabric8操作Kubernetes(三)

Fetching Metrics

Kubernetes Client also supports fetching metrics from API server if metrics are enabled on it. You can access metrics via client.top(). Here are some examples of its usage:

  • Get NodeMetrics for all nodes:
NodeMetricsList nodeMetricList = client.top().nodes().metrics();

  • Get NodeMetrics for some specific nodes:
NodeMetrics nodeMetric = client.top().nodes().metrics("minikube");

  • Get PodMetrics for all pods in all namespaces:
PodMetricsList podMetricsList = client.top().pods().metrics();

  • Get PodMetrics for all pods in some specific namespace:
PodMetricsList podMetricsList = client.top().pods().metrics("default");

  • Get PodMetrics for a particular pod:
PodMetrics podMetrics = client.top().pods().metrics("default", "nginx-pod");

Resource API

Kubernetes Client also offers a generic API to handle different kind of Kubernetes resources. Most of the Kubernetes resources in Kubernetes Model are extending a class named HasMetadata. Resource API can work with any kind of Kubernetes Resource which extends this class. Here are some examples it it's usage:

  • Get a Kubernetes Resource from Kubernetes API server:
Pod pod = client.resource(pod1).inNamespace("default").get();

  • Create or Replace a Kubernetes Resource:
Pod pod1 = new PodBuilder()
  .withNewMetadata().withName("resource-pod-" + RandomStringUtils.randomAlphanumeric(6).toLowerCase(Locale.ROOT)).endMetadata()
  .withNewSpec()
  .addNewContainer().withName("nginx").withImage("nginx").endContainer()
  .endSpec()
  .build();

client.resource(pod1).inNamespace("default").createOrReplace();

  • Create And Wait until resource is ready:
Pod p = client.resource(pod1).createOrReplaceAnd().waitUntilReady(10, TimeUnit.SECONDS);

  • Delete a Kubernetes Resource:
Boolean isDeleted = client.resource(pod1).inNamespace("default").delete();

ResourceList API

Just like generic Kubernetes Resource API, Kubernetes client also provides a generic API to deal with Kubernetes List. Here are some examples of its usage:

  • Create or Replace a list of Kubernetes resources:
Service service =  new ServiceBuilder()
  .withNewMetadata().withName("my-service").endMetadata()
  .withNewSpec()
  .addToSelector("app", "Myapp")
  .addNewPort().withProtocol("TCP").withPort(80).withTargetPort(new IntOrString(9376)).endPort()
  .endSpec()
  .build();

ConfigMap configMap = new ConfigMapBuilder()
  .withNewMetadata().withName("my-configmap").endMetadata()
  .addToData(Collections.singletonMap("app", "Myapp"))
  .build();

KubernetesList list = new KubernetesListBuilder().withItems(deployment, service, configMap).build();

// Create them for the first time
client.resourceList(list).inNamespace("default").createOrReplace();

  • Create or Replace with delete existing resources before creation:
KubernetesList list = new KubernetesListBuilder().withItems(updatedService, updatedConfigMap).build();
client.resourceList(list).inNamespace("default").deletingExisting().createOrReplace();

  • Delete a list of items:
Boolean deleted = client.resourceList(new PodListBuilder().withItems(pod1, pod2, pod3).build()).inNamespace("default").delete();

CustomResourceDefinition

CustomResourceDefinition which are like templates for CustomResource objects in Kubernetes API are available in Kubernetes Client API via client.customResourceDefinitions(). Here are some examples of it's common usage:

  • Load a CustomResourceDefinition from yaml:
CustomResourceDefinition customResourceDefinition = client.customResourceDefinitions().load(new FileInputStream("/sparkapplication-crd.yml")).get();

  • Get a CustomResourceDefinition from Kubernetes APIServer
CustomResourceDefinition crd = client.customResourceDefinitions().withName("sparkclusters.radanalytics.io").get();

  • Create CustomResourceDefinition:

CustomResourceDefinition customResourceDefinition = new CustomResourceDefinitionBuilder()
      .withApiVersion("apiextensions.k8s.io/v1beta1")
      .withNewMetadata().withName("sparkclusters.radanalytics.io")
      .endMetadata()
      .withNewSpec()
      .withNewNames()
      .withKind("SparkCluster")
      .withPlural("sparkclusters")
      .endNames()
      .withGroup("radanalytics.io")
      .withVersion("v1")
      .withScope("Namespaced")
      .withNewValidation()
      .withNewOpenAPIV3SchemaLike(readSchema())
      .endOpenAPIV3Schema()
      .endValidation()
      .endSpec()
      .build();

CustomResourceDefinition crd = client.customResourceDefinitions().createOrReplace(customResourceDefinition);

  • Create or Replace some CustomResourceDefinition:
CustomResourceDefinition crd = client.customResourceDefinitions().createOrReplace(customResourceDefinition);

  • List CustomResourceDefinition:
CustomResourceDefinitionList crdList = client.customResourceDefinitions().list();

  • Delete CustomResourceDefinition:
Boolean deleted = client.customResourceDefinitions().withName("sparkclusters.radanalytics.io").delete();

CustomResource Typed API

CustomResources are available in Kubernetes API via the client.customResources(...). In order to use typed API, you need to provide POJOs for your Custom Resource which client can use for serialization/deserialization. client.customResources(...) take things like CustomResourceDefinitionContext for locating the CustomResources, CustomResource class, it's list class etc. It returns an instance of a client which you can use for your CustomResource related operations. In order to get some idea of how POJOs should look like. Here's an example of POJO for CronTab CustomResource specified in Kubernetes CustomResource docs my-crontab.yml

apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
  name: my-new-cron-object
spec:
  cronSpec: "* * * * */5"
  image: my-awesome-cron-image

For a CustomResource like this one, we should have a CronTab java class like this:

Note: Please make sure that your CustomResource POJO is implementing Namespaced interface if it's a namespaced resource. Otherwise it would be considered a Cluster scoped resource.

/**
 * 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.mock.crd;

import io.fabric8.kubernetes.api.model.Namespaced;
import io.fabric8.kubernetes.api.model.ObjectMeta;
import io.fabric8.kubernetes.client.CustomResource;

public class CronTab extends CustomResource implements Namespaced {
    private CronTabSpec spec;
    private CronTabStatus status;

    @Override
    public ObjectMeta getMetadata() {
        return super.getMetadata();
    }

    public CronTabSpec getSpec() {
        return spec;
    }

    public void setSpec(CronTabSpec spec) {
        this.spec = spec;
    }

    public CronTabStatus getStatus() {
        return status;
    }

    public void setStatus(CronTabStatus status) {
        this.status = status;
    }

    @Override
    public String getApiVersion() {
        return "stable.example.com/v1";
    }

    @Override
    public String toString() {
        return "CronTab{"+
                "apiVersion='" + getApiVersion() + "'" +
                ", metadata=" + getMetadata() +
                ", spec=" + spec +
                ", status=" + status +
                "}";
    }
}

You can find other helper classes related to CronTab in our tests. For now, we can proceed with it's common usage examples:

  • Get Instance of client for our CustomResource:
// Alternatively use CustomResourceDefinitionContext.fromCrd(crd) if you already have a CustomResourceDefinition
CustomResourceDefinitionContext context = new CustomResourceDefinitionContext.Builder()
      .withGroup("stable.example.com)
      .withVersion("v1")
      .withScope("Namespaced")
      .withName("crontabs.stable.example.com)
      .withPlural("crontabs")
      .withKind("CronTab")
      .build()
MixedOperation<CronTab, CronTabList, DoneableCronTab, Resource<CronTab, DoneableCronTab>> cronTabClient = client
  .customResources(cronTabCrd, CronTab.class, CronTabList.class, DoneableCronTab.class);

  • Register your CustomResource to KubernetesDeserializer:
KubernetesDeserializer.registerCustomKind("stable.example.com/v1", "CronTab", CronTab.class);

  • Get CustomResource from Kubernetes APIServer:
CronTab ct = cronTabClient.inNamespace("default").withName("my-second-cron-object").get();

  • Create CustomResource:
cronTabClient.inNamespace("default").create(cronTab1);

  • List CustomResource:
CronTabList cronTabList = cronTabClient.inNamespace("default").list();

  • Delete CustomResource:
Boolean isDeleted = cronTabClient.inNamespace("default").withName("my-third-cron-object").delete();

  • Update Status of CustomResource:
cronTabClient.inNamespace("default").updateStatus(updatedCronTab);

  • Watch CustomResource, (note: You need to register your CustomResource to KubernetesDeserializer otherwise you won't be able to use watch):
cronTabClient.inNamespace("default").watch(new Watcher<CronTab>() {
  @Override
  public void eventReceived(Action action, CronTab resource) {
    // Do something depending upon action type
  }

  @Override
  public void onClose(KubernetesClientException cause) {

  }
});

CustomResource Typeless API

Although, you should be using Typed API since it's type-safe. But it can get a bit compilcated to maintain your CustomResource POJOs and sometimes people don't even have them. Kubernetes Client also provides a typeless/raw API to handle your CustomResource objects in form of HashMaps. In order to use it, you need to provide it with a CustomResourceDefinitionContext, which carries necessary information about CustomResource. Here is an example on how to create one:

  • Create CustomResourceDefinitionContext:
CustomResourceDefinitionContext customResourceDefinitionContext = new CustomResourceDefinitionContext.Builder()
      .withName("animals.jungle.example.com")
      .withGroup("jungle.example.com")
      .withVersion("v1")
      .withPlural("animals")
      .withScope("Namespaced")
      .build();

Once you have built it, you can pass it to typeless DSL as argument client.customResource(customResourceDefinitionContext). With this in place, you can do your standard CustomResource operations, but you would have to deal with Serialization/Deserialization part yourself. You can convert HashMap to some JSON object using JSON parsing libraries available on internet.

  • Load a CustomResource from yaml:
Map<String, Object> customResource = client.customResource(crdContext).load(new FileInputStream("cr.yaml"));

  • Get a CustomResource from Kubernetes API server:
Map<String, Object> customResourceObject = client.customResource(customResourceDefinitionContext).get(currentNamespace, "otter");

  • Create a CustomResource:
// Create via file
Map<String, Object> object = client.customResource(customResourceDefinitionContext).create(currentNamespace, new FileInputStream("test-rawcustomresource.yml"));

// Create via raw JSON string

String rawJsonCustomResourceObj = "{\"apiVersion\":\"jungle.example.com/v1\"," +
  "\"kind\":\"Animal\",\"metadata\": {\"name\": \"walrus\"}," +
  "\"spec\": {\"image\": \"my-awesome-walrus-image\"}}";
Map<String, Object> object = client.customResource(customResourceDefinitionContext).create(currentNamespace, rawJsonCustomResourceObj);

  • List CustomResource:
Map<String, Object> list = client.customResource(customResourceDefinitionContext).list(currentNamespace);

  • List CustomResource with labels:
Map<String, Object> list = client.customResource(customResourceDefinitionContext).list(currentNamespace, Collections.singletonMap("foo", "bar"));

  • Update CustomResource:
Map<String, Object> object = client.customResource(customResourceDefinitionContext).get(currentNamespace, "walrus");
((HashMap<String, Object>)object.get("spec")).put("image", "my-updated-awesome-walrus-image");
object = client.customResource(customResourceDefinitionContext).edit(currentNamespace, "walrus", new ObjectMapper().writeValueAsString(object));

  • Delete CustomResource:
client.customResource(customResourceDefinitionContext).delete(currentNamespace, "otter");

  • Update Status of CustomResource:
Map<String, Object> result = client.customResource(customResourceDefinitionContext).updateStatus("ns1", "example-hello", objectAsJsonString);

  • Watch CustomResource:

  final CountDownLatch closeLatch = new CountDownLatch(1);
  client.customResource(crdContext).watch(namespace, new Watcher<String>() {
    @Override
    public void eventReceived(Action action, String resource) {
      logger.info("{}: {}", action, resource);
    }

    @Override
    public void onClose(KubernetesClientException e) {
      logger.debug("Watcher onClose");
      closeLatch.countDown();
      if (e != null) {
        logger.error(e.getMessage(), e);
      }
    }
  });
  closeLatch.await(10, TimeUnit.MINUTES);

CertificateSigningRequest

Kubernetes Client provides using CertificateSigningRequest via the client.certificateSigningRequests() DSL interface. Here is an example of creating CertificateSigningRequest using Fabric8 Kubernetes Client:

try (KubernetesClient client = new DefaultKubernetesClient()) {
    CertificateSigningRequest csr = new CertificateSigningRequestBuilder()
            .withNewMetadata().withName("test-k8s-csr").endMetadata()
            .withNewSpec()
            .addNewGroup("system:authenticated")
            .withRequest("LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJRWJqQ0NBbFlDQVFBd0tURVBNQTBHQTFVRUF3d0dhMmxrYjI1bk1SWXdGQVlEVlFRS0RBMWtZWFJoTFdWdQpaMmx1WldWeU1JSUNJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBZzhBTUlJQ0NnS0NBZ0VBc2dVZXl0S0F6ZDkyClN1S2pZL1RqbmRsZ0lkSFVVYWFxbHJIVW1nbTloKzY2RTJCNGs0TSt6Q0tOQmovemlMdWV6NFNUeHJ6SFk3RlUKNGUxWElBU3lMS0dmRGNPaks5NThURThwcXBRM21VdlpWMmxnK25BTVF5dlZUYWdZSmFId2JWUzVlNHgvRmpKcQoxTWpQZ1VoSGFXeEdIYTQrQnZYQU9Kdk5BdnV4alpZaVJET251dGxHVzloQkRKRlhoUk5jOGFKNnFiZWVBWnNiCmozWUFMaUcydWp1VmhoTUVRNEJxdFVHVGZCMzBQNGhRK2t2bWVKc2ZUU3Vsb2xiWFdIdVZGWnh1d0FJek5RbmQKMTd4VHd2cU04OGZFb3ZJazBJV0ZCWTk2aHRvaUVNdThZUms4SEZ6QkJralhsZGlkbVNNSHkwK0plcFRONmdQTQpEYVVsd1cxS0lCcW9TbnZNcjY4cFRVWEVhZVRjc040anMxTUIwK3FwR0JBS1puWWVxM0JmMkxVVFBNaG1VZ2VVCmFUTFlqODI2WVorZjJrOWJ1cngwK1NOSmVZbWoxVTl0N3A2YWM0dDIzZHVYQ1BzYkNrUFNKeGtrU3dudUlVVzkKdmJVVGtJNGtVMlFVMnE0NzRaMW1uMlkvejF2TEdQdEpsTDFYUVFVNEdsb2hrQkVkM1BsUTRtOGU1WGZSRkV6ZgpYZnhMRXFRczFTeEg1ekhjcnVaOWxJdnBkeEw5Tkc5WlR6M0tmT0tIbCtSUzdxMGdKaExac0RubUJKNXZab3p4CldXci9IRW9PamFYbGh0VitDN3M4TUg5Y0lKZENZNnpjcFVrZis1NmZ0Z1FuN0YrT1RYdDI0UVJQYWNFZnRFOTkKVERPb2luTGtOMm1kckxiMTgxQUZNUWJ0bTFLc1k2MENBd0VBQWFBQU1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQwpBUUNQYU1WdDd4YWhkZlF1L1BySFVTTW5LK2I0SlJScEdEYlpWUXk4aUtkSmdHM0VrYnNBZ21qQmN4Q1IvL2t1CkVhU0plSGNWK20xVlFUTEp1ZFU3ZHFUeFBLOVFCNlB2aHlBbCttNnFaQkt1Q25VM1BKc2k5azBYSE5GWXBqRmYKVFNwTlpJSnRuanVEQWVtT05kcjJYMm1rODZmSmpWTEUvYnA1KzM5dFBkN0xjL3dZR2JoRU0xcExtUGpQK0Z6eQpzZnBiYW5PcmZFSG5NMmlsRFpGZURVSEpYL3F5Ykt1RC9BRmdoZk1Ua0x3ODNLNkNRdCtDQm05djRCeEtCS2xqCkdBWEQyUEhUTWlzektUbGpBM3czYUphanZzU0FwQXFCWnFocjB3QzdOb1dYM1h6S0p3ck9MaWVxemo3SXlpUGEKTEI5SmJveFpOQTdBSU5ucEdsa1hDZlRGT2RManZtQkVRQXV5Ym9wLzdqV2RiSzJHRkZKS2UwdlVlbWNUeGdHVwp5c0ZyV2pqMUlvdVBVNFZ6ck82QVBVQnZCZUFtdU1Bbm9yVng5emc4akhlT1pkd2RWdFRnOUwrK0VnWjlxK0htCjVtUlJGVHlZOWo4WVVvd2J6TzRlRUZnaVN0di84T1p0YmtOeDFROWFQWHJ3VUV1Q1I0SUthWG0wNlJUYXJOYXUKTWFsbk5oZm9WYi9Bc1R5d1ArNlc1dGErcTBpckR5cnVkZk5pRkFWbkRMZEU5a2hWZzVrU0lPRzhYbEZUMklwSQpkdVNpcUl0NlNUTlY3UmdaRzBGTFN5akxoc3laWnY2bitpUzl3Ky9OOFpoUzgvalViUUVidG1VTnNJU3Z5WS9JCmZqcHNZQUdleExvVW5mN2pDaUhkbTVhSnJ5SU1kdmZ2akJsMDhIVk5nWG1McVE9PQotLS0tLUVORCBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0K")
            .addNewUsage("client auth")
            .endSpec()
            .build();

    client.certificateSigningRequests().create(csr);
}

SharedInformers

Kubernetes Client also provides SharedInformer support in order to stay updated to events happening to your resource inside Kubernetes. It's implementation is just list and watch operations after a certain interval of time. Here are some of the common usages:

  • Get SharedInformerFactory:
SharedInformerFactory sharedInformerFactory = client.informers();

  • Create SharedIndexInformer for some Kubernetes Resource(requires resource's class, resource's list class, and resync period(when to check with server again while watching something). By default it watches in all namespaces.:
SharedIndexInformer<Pod> podInformer = sharedInformerFactory.sharedIndexInformerFor(Pod.class, PodList.class, 30 * 1000L);
podInformer.addEventHandler(new ResourceEventHandler<Pod>() {
  @Override
  public void onAdd(Pod pod) {
    logger.info("{} pod added", pod.getMetadata().getName());
  }

  @Override
  public void onUpdate(Pod oldPod, Pod newPod) {
    logger.info("{} pod updated", oldPod.getMetadata().getName());
  }

  @Override
  public void onDelete(Pod pod, boolean deletedFinalStateUnknown) {
    logger.info("{} pod deleted", pod.getMetadata().getName());
  }
});

  • Create SharedIndexInformer for some Custom Resource(in our case, Dummy resource provided in our examples . By default it watches in all namespaces.
CustomResourceDefinitionContext crdContext = new CustomResourceDefinitionContext.Builder()
    .withVersion("v1")
    .withScope("Namespaced")
    .withGroup("demo.fabric8.io")
    .withPlural("dummies")
    .build();
SharedIndexInformer<Dummy> dummyInformer = sharedInformerFactory.sharedIndexInformerForCustomResource(crdContext, Dummy.class, DummyList.class, 1 * 60 * 1000);
dummyInformer.addEventHandler(new ResourceEventHandler<Dummy>() {
  @Override
  public void onAdd(Dummy dummy) {
    System.out.printf("%s dummy added\n", dummy.getMetadata().getName());
  }

  @Override
  public void onUpdate(Dummy oldDummy, Dummy newDummy) {
    System.out.printf("%s dummy updated\n", oldDummy.getMetadata().getName());
  }

  @Override
  public void onDelete(Dummy dummy, boolean deletedFinalStateUnknown) {
    System.out.printf("%s dummy deleted \n", dummy.getMetadata().getName());
  }
});

  • Create namespaced SharedIndexInformer (informers specific to a particular Namespace):
SharedInformerFactory sharedInformerFactory = client.informers();
SharedIndexInformer<Pod> podInformer = sharedInformerFactory.sharedIndexInformerFor(
        Pod.class,
        PodList.class,
        new OperationContext().withNamespace("default"),
        30 * 1000L);
logger.info("Informer factory initialized.");

podInformer.addEventHandler(new ResourceEventHandler<Pod>() {
    @Override
    public void onAdd(Pod pod) {
        logger.info("Pod " + pod.getMetadata().getName() + " got added");
    }

    @Override
    public void onUpdate(Pod oldPod, Pod newPod) {
        logger.info("Pod " + oldPod.getMetadata().getName() + " got updated");
    }

    @Override
    public void onDelete(Pod pod, boolean deletedFinalStateUnknown) {
        logger.info("Pod " + pod.getMetadata().getName() + " got deleted");
    }
});

  • Create Namespaced Informer for a Custom Resource(Note: Your CustomResource POJO must implement Namespaced interface like the one used in this example: Dummy.java)
CustomResourceDefinitionContext crdContext = new CustomResourceDefinitionContext.Builder()
    .withVersion("v1")
    .withScope("Namespaced")
    .withGroup("demo.fabric8.io")
    .withPlural("dummies")
    .build();
SharedIndexInformer<Dummy> dummyInformer = sharedInformerFactory.sharedIndexInformerForCustomResource(crdContext,
    Dummy.class,
    DummyList.class,
    new OperationContext().withNamespace("default"), // Namespace to watch
    1 * 60 * 1000);
dummyInformer.addEventHandler(new ResourceEventHandler<Dummy>() {
  @Override
  public void onAdd(Dummy dummy) {
    System.out.printf("%s dummy added\n", dummy.getMetadata().getName());
  }

  @Override
  public void onUpdate(Dummy oldDummy, Dummy newDummy) {
    System.out.printf("%s dummy updated\n", oldDummy.getMetadata().getName());
  }

  @Override
  public void onDelete(Dummy dummy, boolean deletedFinalStateUnknown) {
    System.out.printf("%s dummy deleted \n", dummy.getMetadata().getName());
  }
});

  • Start all registered informers:
sharedInformerFactory.startAllRegisteredInformers();

  • Stop all registered informers:
sharedInformerFactory.stopAllRegisteredInformers();

List Options

There are various options provided by Kubernetes Client API when it comes to listing resources. Here are some of the common examples provided:

  • List with pagination, comes with limit and continue parameters. The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize.
PodList podList = client.pods().inNamespace("myproject").list(5, null);

podList = client.pods().inNamespace("myproject").list(5, podList.getMetadata().getContinue());

  • List resources containing some specific Label:
PodList podList = client.pods().inNamespace("default").withLabel("foo", "bar").list();

  • List resources containing a set of labels:
PodList podList = client.pods().inNamespace("default").withLabels(Collections.singletonMap("foo", "bar")).list();

  • List resources without Label:
PodList podList = client.pods().inNamespace("default").withoutLabel("foo", "bar").list();

  • List resources without a set of Labels:
PodList podList = client.pods().inNamespace("default").withoutLabels(Collections.singletonMap("foo", "bar")).list();

  • List resources with labels in:
PodList podList = client.pods().inNamespace("default").withLabelIn("foo", "bar").list();

  • List resources with labels not in:
PodList podList =client.pods().inNamespace("default").withLabelNotIn("foo", "bar").list();

  • List resources with field:
PodList podList = client.pods().inNamespace("default").withField("foo", "bar").list();

  • List resources with fields:
PodList podList = client.pods().inNamespace("default").withFields(Collections.singletonMap("foo", "bar")).list();

  • List resources without field:
PodList podList = client.pods().inNamespace("default").withoutField("foo", "bar").list();

  • List resources without fields:
PodList podList = client.pods().inNamespace("default").withoutFields(Collections.singletonMap("foo", "bar")).list();

  • List resources with ListOptions:
PodList podList = client.pods().inNamespace("default").list(new ListOptionsBuilder()
  .withLimit(1L)
  .withContinue(null)
  .build());

Delete Options

Kubernetes Client also provides way to delete dependents of some Kubernetes resource. Here are some examples:

  • Providing cascading() in order to either delete dependent resources or leave them orphan. By default it is true meaning it would delete dependent resources too.
Boolean isDeleted = client.apps().deployments().inNamespace("default").withName("nginx-deploy").cascading(true).delete();

  • Providing propagationPolicy(..) to specify how deletion should be performed:
Boolean isDeleted = client.apps().deployments().inNamespace("default").withName("nginx-deploy").withPropagationPolicy("Foreground").delete();

  • Specifying grace period for deletion:
Boolean isDeleted = client.apps().deployments().inNamespace("ns1").withName("mydeployment").withPropagationPolicy(DeletionPropagation.FOREGROUND).withGracePeriod(10).delete();

Watch Options

Kubernetes Client provides namely three different ways of using Watch:

  • Plain Watch without any arguments:
client.pods().inNamespace(namespace).watch(new Watcher<Pod>() {
    @Override
    public void eventReceived(Action action, Pod pod) {
        logger.log(Level.INFO, action.name() + " " + pod.getMetadata().getName());
        switch (action.name()) {
            case "ADDED":
                logger.log(Level.INFO, pod.getMetadata().getName() + "got added");
                break;
            case "DELETED":
                logger.log(Level.INFO, pod.getMetadata().getName() + "got deleted");
                break;
            case "MODIFIED":
                logger.log(Level.INFO, pod.getMetadata().getName() + "got modified");
                break;
            default:
                logger.log(Level.SEVERE, "Unrecognized event: " + action.name());
        }
    }

    @Override
    public void onClose(KubernetesClientException e) {
        logger.log(Level.INFO, "Closed");
        isWatchClosed.countDown();
    }
});

// Wait till watch gets closed
isWatchClosed.await();

  • Deprecated : Watching with resourceVersion provided:
String resourceVersion = "20012";
client.pods().inNamespace(namespace).watch(resourceVersion, new Watcher<Pod>() {
    @Override
    public void eventReceived(Action action, Pod pod) {
        logger.log(Level.INFO, action.name() + " " + pod.getMetadata().getName());
        switch (action.name()) {
            case "ADDED":
                logger.log(Level.INFO, pod.getMetadata().getName() + "got added");
                break;
            case "DELETED":
                logger.log(Level.INFO, pod.getMetadata().getName() + "got deleted");
                break;
            case "MODIFIED":
                logger.log(Level.INFO, pod.getMetadata().getName() + "got modified");
                break;
            default:
                logger.log(Level.SEVERE, "Unrecognized event: " + action.name());
        }
    }

    @Override
    public void onClose(KubernetesClientException e) {
        logger.log(Level.INFO, "Closed");
        isWatchClosed.countDown();
    }
});

// Wait till watch gets closed
isWatchClosed.await();
} catch (InterruptedException interruptedException) {
logger.log(Level.INFO, "Thread Interrupted!");
Thread.currentThread().interrupt();
}

  • Watching with ListOptions object:
client.pods().watch(new ListOptionsBuilder().withTimeoutSeconds(30L).build(), new Watcher<Pod>() {
  @Override
  public void eventReceived(Action action, Pod resource) { }

  @Override
  public void onClose(KubernetesClientException cause) { }
});

Log Options

  • Get logs with pretty output:
client.pods().inNamespace("test").withName("foo").withPrettyOutput().getLog();

  • Get logs of a specific container:
client.pods().inNamespace("test").withName("foo").inContainer("container1").getLog();

  • Get logs for the previous instance of the container in a pod if it exists:
client.pods().inNamespace("test").withName("foo").terminated().getLog();

  • Only return logs after a specific date (RFC3339):
client.pods().inNamespace("test").withName("foo").sinceTime("2020-09-10T12:53:30.154148788Z").getLog();

  • Get logs after a duration of seconds:
client.pods().inNamespace("test").withName("foo").sinceSeconds(10).getLog();

  • Get logs lines of recent log file to display.
client.pods().inNamespace("test").withName("foo").tailingLines(10).getLog();

  • Configure Maximum bytes of logs to return. Defaults to no limit.
client.pods().inNamespace("test").withName("foo").limitBytes(102).getLog();

  • Include timestamps on each line in the log output
client.pods().inNamespace("test").withName("foo").usingTimestamps().getLog();

Serializing to yaml

Resources can be exported to a yaml String via the SerializationUtils class:

Pod myPod;

String myPodAsYaml = SerializationUtils.dumpAsYaml(myPod);
// Your pod might have some state that you don't really care about, to remove it:
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().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().inNamespace("default")
            .withRunConfig(new RunConfigBuilder()
                    .withName("nginx")
                    .withImage("nginx:latest")
                    .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.

Initializing OpenShift Client:

Initializing OpenShift client is the same as Kubernetes Client. Yo

try (final OpenShiftClient client = new DefaultOpenShiftClient()) {
  // Do stuff with client
}

This would pick up default settings, reading your kubeconfig file from ~/.kube/config directory or whatever is defined inside KUBECONFIG environment variable. But if you want to customize creation of client, you can also pass a Config object inside DefaultKubernetesClient like this:

Config kubeConfig = new ConfigBuilder()
            .withMasterUrl("https://api.ci-ln-3sbdl1b-d5d6b.origin-ci-int-aws.dev.examplecloud.com:6443")
            .withOauthToken("xxxxxxxx-41oafKI6iU637-xxxxxxxxxxxxx")
            .build())) {
try (final OpenShiftClient client = new DefaultOpenShiftClient(config)) {
  // Do stuff with client
}

You can also create OpenShiftClient from an existing instance of KubernetesClient. There is a method called adapt(..) for this. Here is an example:

KubernetesClient client = new DefaultKubernetesClient();
OpenShiftClient openShiftClient = client.adapt(OpenShiftClient.class);

DeploymentConfig

DeploymentConfig is available in OpenShift client via client.deploymentConfigs(). Here are some examples of its common usage:

  • Load DeploymentConfig from yaml:
DeploymentConfig deploymentConfig = client.deploymentConfigs().inNamespace(currentNamespace)
  .load(new FileInputStream("test-deploymentconfig.yml")).get();

  • Get DeploymentConfig from OpenShift API server:
DeploymentConfig dc = client.deploymentConfigs().inNamespace(currentNamespace).withName("deploymentconfig1").get();

  • Create DeploymentConfig:
DeploymentConfig dc = new DeploymentConfigBuilder()
      .withNewMetadata().withName("deploymentconfig1").endMetadata()
      .withNewSpec()
      .withReplicas(2)
      .withNewTemplate()
      .withNewMetadata()
      .addToLabels("app", "database")
      .endMetadata()
      .withNewSpec()
      .addNewContainer()
      .withName("mysql")
      .withImage("openshift/mysql-55-centos7")
      .endContainer()
      .endSpec()
      .endTemplate()
      .endSpec()
      .build();

DeploymentConfig dcCreated = client.deploymentConfigs().inNamespace("default").create(dc);

  • Create or Replace an existing DeploymentConfig:
DeploymentConfig dc = client.deploymentConfigs().inNamespace("default").createOrReplace(dcToCreate);

  • List DeploymentConfig in some namespace:
DeploymentConfigList aDeploymentConfigList = client.deploymentConfigs().inNamespace("default").list();

  • List DeploymentConfig in any namespace:
DeploymentConfigList dcList = client.deploymentConfigs().inAnyNamespace().list();

  • List DeploymentConfig in some namespace with some label:
DeploymentConfigList dcList = client.deploymentConfigs().inNamespace("default").withLabel("foo", "bar").list();

  • Update DeploymentConfig:
DeploymentConfig deploymentConfig1 = client.deploymentConfigs().inNamespace(currentNamespace).withName("deploymentconfig1").edit()
  .editSpec().withReplicas(3).endSpec().done();

  • Delete DeploymentConfig:
Boolean bDeleted = client.deploymentConfigs().inNamespace("default").withName("deploymentconfig1").delete();

  • Watch DeploymentConfig:
client.deploymentConfigs().inNamespace("default").watch(new Watcher<DeploymentConfig>() {
  @Override
  public void eventReceived(Action action, DeploymentConfig resource) {
    // Do something depending upon action    
  }

  @Override
  public void onClose(KubernetesClientException cause) {

  }
});

BuildConfig

BuildConfig resource is available in OpenShift Client via client.buildConfigs(). Here are some examples of it's common uses:

  • Load BuildConfig from yaml:
    <main style="box-sizing: border-box; display: block;">

<article class="markdown-body entry-content container-lg" itemprop="text" style="box-sizing: border-box; display: block; max-width: 1012px; margin-right: auto; margin-left: auto; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; font-size: 16px; line-height: 1.5; overflow-wrap: break-word;">

BuildConfig aBuildConfig = client.buildConfigs().inNamespace(currentNamespace)
  .load(new FileInputStream("/test-buildconfig.yml")).get();

  • Get BuildConfig from OpenShift API server:
BuildConfig bc = client.buildConfigs().inNamespace(currentNamespace).withName("bc1").get();

  • Create BuildConfig:
BuildConfig buildConfig1 = new BuildConfigBuilder()
  .withNewMetadata().withName("bc1").endMetadata()
  .withNewSpec()
  .addNewTrigger()
  .withType("GitHub")
  .withNewGithub()
  .withSecret("secret101")
  .endGithub()
  .endTrigger()
  .addNewTrigger()
  .withType("Generic")
  .withNewGeneric()
  .withSecret("secret101")
  .endGeneric()
  .endTrigger()
  .addNewTrigger()
  .withType("ImageChange")
  .endTrigger()
  .withNewSource()
  .withType("Git")
  .withNewGit()
  .withUri("https://github.com/openshift/ruby-hello-world")
  .endGit()
  .withDockerfile("FROM openshift/ruby-22-centos7\\nUSER example")
  .endSource()
  .withNewStrategy()
  .withType("Source")
  .withNewSourceStrategy()
  .withNewFrom()
  .withKind("ImageStreamTag")
  .withName("origin-ruby-sample:latest")
  .endFrom()
  .endSourceStrategy()
  .endStrategy()
  .withNewOutput()
  .withNewTo()
  .withKind("ImageStreamTag")
  .withName("origin-ruby-sample:latest")
  .endTo()
  .endOutput()
  .withNewPostCommit()
  .withScript("bundle exec rake test")
  .endPostCommit()
  .endSpec()
  .build();

client.buildConfigs().inNamespace("default").create(buildConfig1);

  • Create or Replace BuildConfig:
BuildConfig bc = client.buildConfigs().inNamespace("default").create(buildConfig1);

  • List BuildConfig in some namespace:
BuildConfigList bcList = client.buildConfigs().inNamespace("default").list();

  • List BuildConfig in any namespace:
BuildConfigList bcList = client.buildConfigs().inNamespace("default").list();

  • List BuildConfig in some namespace with some label:
BuildConfigList bcList = client.buildConfigs().inNamespace("default").withLabel("foo", "bar").list();

  • Delete BuildConfig:
Boolean bDeleted = client.buildConfigs().inNamespace("default").withName("bc1").delete();

  • Watch BuildConfig:
client.buildConfigs().inNamespace("default").watch(new Watcher<BuildConfig>() {
  @Override
  public void eventReceived(Action action, BuildConfig resource) {
    // Do something depending upon action type    
  }

  @Override
  public void onClose(KubernetesClientException cause) {

  }
});

Route

Route resource is available in OpenShift client API via client.routes(). Here are some examples of its common usage:

  • Load Route from yaml:
Route aRoute = client.routes().inNamespace("default").load(new FileInputStream("test-route.yml")).get();

  • Get Route from OpenShift API server:
Route route1 = client.routes().inNamespace("default").withName("route1").get();

  • Create Route:
Route route1 = new RouteBuilder()
      .withNewMetadata().withName("route1").endMetadata()
      .withNewSpec().withHost("www.example.com").withNewTo().withKind("Service").withName("service-name1").endTo().endSpec()
      .build();

client.routes().inNamespace("defalt").create(route1);

  • Create or Replace Route:
Route route = client.routes().inNamespace("default").createOrReplace(route1);

  • List Route in some namespace:
RouteList aRouteList = client.routes().inNamespace("default").list();

  • List Route in any namespace:
RouteList aRouteList = client.routes().inAnyNamespace().list();

  • List Route in some namespace with some label:
RouteList routeList = client.routes().inNamespace("default").withLabel("foo", "bar").list();

  • Delete Route:
boolean bDeleted = client.routes().inNamespace("default").withName("route1").delete();

Project

OpenShift Project resource can be found in OpenShift Client API via client.projects(). Here are some examples of its usage:

  • Get Project:
Project myProject = client.projects().withName("default").get();

  • Create Project
ProjectRequest request = client.projectrequests().createNew().withNewMetadata().withName("thisisatest").endMetadata().withDescription("Fabric8").withDisplayName("Fabric8).done();

  • List Project
ProjectList projectList = client.projects().list();

  • Delete Project:
Boolean isDeleted = client.projects().withName("default").delete();

ImageStream

ImageStream resource is available in OpenShift client via client.imageStreams(). Here are some examples of its common usage:

  • Load ImageStream from yaml:
ImageStream aImageStream = client.imageStreams()
  .load(new FileInputStream("test-imagestream.yml")).get();

  • Get ImageStream from OpenShift API Server:
ImageStream is =client.imageStreams().inNamespace("default").withName("example-camel-cdi").get();

  • Create ImageStream:
ImageStream imageStream1 = new ImageStreamBuilder()
      .withNewMetadata()
      .withName("example-camel-cdi")
      .endMetadata()
      .withNewSpec()
      .addNewTag()
      .withName("latest")
      .endTag()
      .withDockerImageRepository("fabric8/example-camel-cdi")
      .endSpec()
      .withNewStatus().withDockerImageRepository("").endStatus()
      .build();

client.imageStreams().inNamespace("default").create(imageStream1);

  • Create or Replace ImageStream:
ImageStream is = client.imageStreams().inNamespace("default").createOrReplace(imageStream1);

  • List ImageStream in some namespace:
ImageStreamList aImageStreamList = client.imageStreams().inNamespace("default").list();

  • List ImageStream in any namespace:
ImageStreamList isList = client.imageStreams().inAnyNamespace().list();

  • List ImageStream in some namespace with some labels:
ImageStreamList isList = client.imageStreams().inNamespace("default").withLabel("foo", "bar").list();

  • Delete ImageStream:
Boolean bDeleted = client.imageStreams().inNamespace("default").withName("example-camel-cdi").delete();

CatalogSource

CatalogSource is available for usage in OpenShift Client via client.operatorHub().catalogSources(). Here are some common examples of it's usage:

  • Load CatalogSource from YAML:
CatalogSource cs = client.operatorHub().catalogSources()
  .load(new FileInputStream("/test-catalogsource.yml").get();

  • Create CatalogSource:
CatalogSource cs = new CatalogSourceBuilder()
  .withNewMetadata().withName("foo").endMetadata()
  .withNewSpec()
  .withSourceType("Foo")
  .withImage("nginx:latest")
  .withDisplayName("Foo Bar")
  .withPublisher("Fabric8")
  .endSpec()
  .build();
client.operatorHub().catalogSources().inNamespace("default").createOrReplace(cs);

  • List CatalogSource in some namespace:
CatalogSourceList csList = client.operatorHub().catalogSources().inNamespace("ns1").list();

  • List CatalogSource in any namespace:
CatalogSourceList csList = client.operatorHub().catalogSources().inAnyNamespace().list();

  • List CatalogSource in some namespace with some labels:
CatalogSourceList csList = client.operatorHub().catalogSources().inNamespace("default").withLabel("foo", "bar").list();

  • Delete CatalogSource:
client.operatorHub().catalogSources().inNamespace("default").withName("foo").delete();

PrometheusRule

PrometheusRule is available for usage in OpenShift Client via client.monitoring().prometheusRules(). Here are some common examples of it's usage:

  • Load PrometheusRule from YAML:
PrometheusRule prometheusRule = client.monitoring().prometheusRules()
  .load(new FileInputStream("/test-prometheusrule.yml").get();

  • Create PrometheusRule:
PrometheusRule prometheusRule = new PrometheusRuleBuilder()
    .withNewMetadata().withName("foo").endMetadata()
    .withNewSpec()
    .addNewGroup()
    .withName("./example-rules")
    .addNewRule()
    .withAlert("ExampleAlert")
    .withNewExpr().withStrVal("vector(1)").endExpr()
    .endRule()
    .endGroup()
    .endSpec()
    .build();
client.monitoring().prometheusRules().inNamespace("default").createOrReplace(prometheusRule);

  • List PrometheusRule in some namespace:
PrometheusRuleList prList = client.monitoring().prometheusRules().inNamespace("ns1").list();

  • List PrometheusRule in any namespace:
PrometheusRuleList prList = client.monitoring().prometheusRules().inAnyNamespace().list();

  • List PrometheusRule in some namespace with some labels:
PrometheusRuleList prList = client.monitoring().prometheusRules().inNamespace("default").withLabel("foo", "bar").list();

  • Delete PrometheusRule:
client.monitoring().prometheusRules().inNamespace("default").withName("foo").delete();

ServiceMonitor

ServiceMonitor is available for usage in OpenShift Client via client.monitoring().serviceMonitors(). Here are some common examples of it's usage:

  • Load ServiceMonitor from YAML:
ServiceMonitor serviceMonitor = client.monitoring().serviceMonitors()
  .load(new FileInputStream("/test-servicemonitor.yml").get();

  • Create ServiceMonitor:
ServiceMonitor serviceMonitor = new ServiceMonitorBuilder()
    .withNewMetadata()
    .withName("foo")
    .addToLabels("prometheus", "frontend")
    .endMetadata()
    .withNewSpec()
    .withNewNamespaceSelector().withAny(true).endNamespaceSelector()
    .withNewSelector()
    .addToMatchLabels("prometheus", "frontend")
    .endSelector()
    .addNewEndpoint()
    .withPort("http-metric")
    .withInterval("15s")
    .endEndpoint()
    .endSpec()
    .build();

client.monitoring().serviceMonitors().inNamespace("rokumar").createOrReplace(serviceMonitor)

  • List ServiceMonitor in some namespace:
ServiceMonitorList serviceMonitorList = client.monitoring().serviceMonitors().inNamespace("ns1").list();

  • List ServiceMonitor in any namespace:
ServiceMonitorList serviceMonitorList = client.monitoring().serviceMonitors().inAnyNamespace().list();

  • List ServiceMonitor in some namespace with some labels:
ServiceMonitorList serviceMonitorList = client.monitoring().catalogSources().inNamespace("default").withLabel("foo", "bar").list();

  • Delete ServiceMonitor:
client.operatorHub().monitoring().inNamespace("default").withName("foo").delete();

ClusterResourceQuota

  • Create ClusterResourceQuota:
try (OpenShiftClient client = new DefaultOpenShiftClient()) {
    Map<String, Quantity> hard = new HashMap<>();
    hard.put("pods", new Quantity("10"));
    hard.put("secrets", new Quantity("20"));
    ClusterResourceQuota acrq = new ClusterResourceQuotaBuilder()
            .withNewMetadata().withName("foo").endMetadata()
            .withNewSpec()
            .withNewSelector()
            .addToAnnotations("openshift.io/requester", "foo-user")
            .endSelector()
            .withQuota(new ResourceQuotaSpecBuilder()
                    .withHard(hard)
                    .build())
            .endSpec()
            .build();

    client.quotas().clusterResourceQuotas().createOrReplace(acrq);
}

  • List ClusterResourceQuota from server:
ClusterResourceQuotaList clusterResourceQuotaList = client.quotas().clusterResourceQuotas().list();

  • Delete ClusterResourceQuota:
client.quotas().clusterResourceQuotas().withName("foo").delete();

ClusterVersion

  • Fetch Cluster Version:
try (OpenShiftClient client = new DefaultOpenShiftClient()) {
    ClusterVersion clusterVersion = client.config().clusterVersions().withName("version").get();
    System.out.println("Cluster Version: " + clusterVersion.getStatus().getDesired().getVersion());
}

EgressNetworkPolicy

EgressNetworkPolicy is available for usage in OpenShift Client via client..egressNetworkPolicys(). Here are some common examples of it's usage:

  • Load EgressNetworkPolicy from YAML:
EgressNetworkPolicy egressNetworkPolicy = client.egressNetworkPolicies()
  .load(new FileInputStream("/test-enp.yml").get();

  • Create EgressNetworkPolicy:
try (OpenShiftClient client = new DefaultOpenShiftClient()) {
    EgressNetworkPolicy enp = new EgressNetworkPolicyBuilder()
            .withNewMetadata()
            .withName("foo")
            .withNamespace("default")
            .endMetadata()
            .withNewSpec()
            .addNewEgress()
            .withType("Allow")
            .withNewTo()
            .withCidrSelector("1.2.3.0/24")
            .endTo()
            .endEgress()
            .addNewEgress()
            .withType("Allow")
            .withNewTo()
            .withDnsName("www.foo.com")
            .endTo()
            .endEgress()
            .endSpec()
            .build();
    client.egressNetworkPolicies().inNamespace("default").createOrReplace(enp);
}

  • List EgressNetworkPolicy in some namespace:
EgressNetworkPolicyList egressNetworkPolicyList = client.egressNetworkPolicies().inNamespace("default").list();

  • List EgressNetworkPolicy in any namespace:
EgressNetworkPolicyList egressNetworkPolicyList = client.egressNetworkPolicies().inAnyNamespace().list();

  • List EgressNetworkPolicy in some namespace with some labels:
EgressNetworkPolicyList egressNetworkPolicyList = client.egressNetworkPolicies().inNamespace("default").withLabel("foo", "bar").list();

  • Delete EgressNetworkPolicy:
client.egressNetworkPolicies().inNamespace("default").withName("foo").delete();

Tekton Client

Fabric8 Kubernetes Client also has an extension for Tekton. It is pretty much the same as Kubernetes Client but has support for some additional Tekton resources.

Initializing Tekton Client

Initializing Tekton client is the same as Kubernetes Client. You

try (final TektonClient client = new DefaultTektonClient()) {
  // Do stuff with client
}

This would pick up default settings, reading your kubeconfig file from ~/.kube/config directory or whatever is defined inside KUBECONFIG environment variable. But if you want to customize creation of client, you can also pass a Config object inside DefaultTektonClient. You can also create TektonClient from an existing instance of KubernetesClient. There is a method called adapt(..) for this. Here is an example:

KubernetesClient client = new DefaultKubernetesClient();
TektonClient tektonClient = client.adapt(TektonClient.class);

Tekton Client DSL Usage

The Tekton client supports CRD API version tekton.dev/v1alpha1 as well as tekton.dev/v1beta1. tekton.dev/v1alpha1 includes the CRDs Pipeline, PipelineRun, PipelineResource, Task, TaskRun, Condition and ClusterTask. All tekton.dev/v1alpha1 resources are available using the DSL tektonClient.v1alpha1(). tekton.dev/v1beta1 includes the CRDs Pipeline, PipelineRun, Task, TaskRun and ClusterTask. All tekton.dev/v1beta1 resources are available using the DSL tektonClient.v1beta1(). In addition to the Tekton Pipelines CRDs, the client also supports Tekton Triggers. TriggerTemplate, TriggerBinding, EventListener and ClusterTriggerBinding are available using the DSL tektonClient.v1alpha1().

The usage of the resources follows the same pattern as for K8s resources like Pods or Deployments. Here are some common examples:

  • Listing all PipelineRun objects in some specific namespace:
PipelineRunList list = tektonClient.v1beta1().pipelineRuns().inNamespace("default").list();

  • Create a PipelineRun:
PipelineRun pipelineRun = new PipelineRunBuilder()
        .withNewMetadata().withName("demo-run-1").endMetadata()
        .withNewSpec()
        .withNewPipelineRef().withName("demo-pipeline").endPipelineRef()
        .addNewParam().withName("greeting").withNewValue("Hello World!").endParam()
        .endSpec()
        .build();

tektonClient.v1beta1().pipelineRuns().inNamespace("default").create(pipelineRun);

Knative Client

Fabric8 Kubernetes Client also has an extension for Knative. It is pretty much the same as Kubernetes Client but has support for some additional Knative resources.

Initializing Knative Client

Initializing Knative client is the same as Kubernetes Client.

try (final KnativeClient client = new DefaultKnativeClient()) {
  // Do stuff with client
}

This would pick up default settings, reading your kubeconfig file from ~/.kube/config directory or whatever is defined inside KUBECONFIG environment variable. But if you want to customize creation of client, you can also pass a Config object inside DefaultKnativeClient. You can also create KnativeClient from an existing instance of KubernetesClient. There is a method called adapt(..) for this. Here is an example:

KubernetesClient client = new DefaultKubernetesClient();
KnativeClient knativeClient = client.adapt(KnativeClient.class);

Knative Client DSL Usage

The usage of the resources follows the same pattern as for K8s resources like Pods or Deployments. Here are some common examples:

  • Listing all Service objects in some specific namespace:
ServiceList list = knativeClient.services().inNamespace("default").list();

  • Create a Service:
try (KnativeClient kn = new DefaultKnativeClient()) {
    // Create Service object
    Service service = new ServiceBuilder()
            .withNewMetadata().withName("helloworld-go").endMetadata()
            .withNewSpec()
            .withNewTemplate()
            .withNewSpec()
            .addToContainers(new ContainerBuilder()
                    .withImage("gcr.io/knative-samples/helloworld-go")
                    .addNewEnv().withName("TARGET").withValue("Go Sample V1").endEnv()
                    .build())
            .endSpec()
            .endTemplate()
            .endSpec()
            .build();

    // Apply it onto Kubernetes Server
    kn.services().inNamespace("default").createOrReplace(service);
}

</article>

<details class="details-reset details-overlay details-overlay-dark" id="jumpto-line-details-dialog" style="box-sizing: border-box; display: block;"><summary data-hotkey="l" aria-label="Jump to line" role="button" style="box-sizing: border-box; display: list-item; cursor: pointer; list-style: none;"></summary></details>

</main>

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,658评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,482评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,213评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,395评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,487评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,523评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,525评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,300评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,753评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,048评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,223评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,905评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,541评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,168评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,417评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,094评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,088评论 2 352

推荐阅读更多精彩内容