Skip to content

Latest commit

 

History

History
286 lines (223 loc) · 11.3 KB

MIGRATION-v5.md

File metadata and controls

286 lines (223 loc) · 11.3 KB

Migration from 4.x to 5.x

Note

If you encounter any problems with the following "Migration from 4.x to 5.x" instructions, please let us know by creating an issue in our GitHub repository.

We value your feedback and will work to address your issue promptly. Your contribution is essential to improving our documentation, making our migration process smoother for everyone!

Simplified DSL

Elimination of Doneables

To reduce the number of classes generated by the client and the overall size of packages, Doneable interface, implementations, and implementation generator tasks have been removed.

Provided Doneable implementations (especially for CustomResources) are no longer needed and can be safely removed.

Createable & CreateOrReplaceable

As a result of the Doneable interface removal, createNew() and createOrReplaceWithNew() methods are no longer available. Usages of these methods should be refactored to use the create(Resource... item) or createOrReplace(Resource... item) methods instead.

// Deprecated
client.configMaps().inNamespace("default").createNew()
  .withNewMetadata().withName("config-map-name").endMetadata()
  .addToData("key", "value")
  .done();
// Alternative
client.configMaps().inNamespace("default").create(
  new ConfigMapBuilder()
    .withNewMetadata().withName("config-map-name").endMetadata()
    .addToData("key", "value")
    .done();
);

// Deprecated
client.configMaps().inNamespace("default").createOrReplaceWithNew()
  .withNewMetadata().withName("config-map-name").endMetadata()
  .addToData("key", "value")
  .done();
// Alternative
client.configMaps().inNamespace("default").createOrReplaceWithNew(
  new ConfigMapBuilder()
    .withNewMetadata().withName("config-map-name").endMetadata()
    .addToData("key", "value")
    .done();
);

Editable

As a result of the Doneable interface removal, edit() method is no longer available. The lambda "friendly" T edit(UnaryOperator<T> function) or the visitable approach T edit(Class<V> visitorType, Visitor<V> visitor) methods should be used instead.

// Deprecated
client.configMaps().inNamespace("default").withName("config-map-name").edit()
  .addToData("key-2", "value-2")
  done();
// Alternative
client.configMaps().inNamespace("default").withName("config-map-name").edit(
  c -> new ConfigMapBuilder(c).addToData("key-2", "value-2").build()
);
// Alternative with visitable approach
client.configMaps().inNamespace("default").withName("config-map-name").edit(
  ObjectMetaBuilder.class,
  omb -> omb.addToAnnotations("key", "value")
);

Refactored Watch

Watcher interface

Watcher#onClose(KubernetesClientException cause) method has been replaced by Watcher#onClose(WatcherException cause) and a new default Watcher#onClose() method has been added.

The argument-less onClose method is always invoked upon Watcher completion, regardless if there is an exception or not. The onClose with exception argument is only invoked in case an exception occurs during the Watcher life-cycle (once the watch connection is open and established).

For migration purposes, any onClose implementations resembling the following:

void onClose(KubernetesClientException cause) {
  if (cause != null) {
    // Do in case of exception
  }
  // Clean-up operations
}

Should be refactored to:

void onClose(WatcherException cause) {
  // Do in case of exception
}
void onClose() {
  // Clean-up operations
}

Improved Custom Resource User Experience

This release should be a drop-in replacement for v4 in terms of breaking changes. However, the new release includes many improvements that simplifies the usage of Custom Resources and Custom Resource Definitions in the client.

Custom Resource POJO annotations

@Version

Allows to specify which version of the API the annotated class is defined under.

Together with @Group, this allows to determine the apiVersion field associated with the annotated resource.

See https://kubernetes.io/docs/reference/using-api/#api-versioning for more details.

@Group

Allows to specify which API group the annotated class is defined under.

Together with @Version, this allows to determine the apiVersion field associated with the annotated resource.

See https://kubernetes.io/docs/reference/using-api/#api-groups for more details.

@Kind

Allows to specify which Kind value should be used to refer to instance of the annotated class.

If not provided, a default value is computed based on the annotated class name.

See HasMetadata#getKind for more details.

@Singular

Allows to specify the singular name of the resource.

@Plural

Allows to specify the plural name of the resource to serve.

The custom resources are served under /apis/<group>/<version>/.../<plural>

Custom Resource Type Parameters

The CustomResource abstract class provides a default implementation for the convention fields spec and status. The class is now parameterized and the Types for these fields can be specified through the new Type parameters in the class.

Helper & Utility methods

CustomResourceDefinitionContext - v1CRDFromCustomResourceType and v1beta1CRDFromCustomResourceType

New v1CRDFromCustomResourceType and v1beta1CRDFromCustomResourceType methods have been introduced on CustomResourceDefinitionContext to initialize a CustomResourceDefinitionBuilder with the information provided by a specific CustomResource implementation.

These methods simplify the creation of CustomResourceDefinitions by inferring the boiler-plate spec values from the annotations and other information already provided in the CustomResource implementation.

SharedIndexInformer API improvements

We have added some minor improvements in shared informer APIs. Changes are as follows:

  • No List type required in SharedInformerFactory.sharedIndexInformerFor and SharedInformerFactory.sharedIndexInformerForCustomResource methods. Now you don't need to provide any List type for creatinga new SharedIndexInformer. Now the method only accepts Type and resyncPeriod as parameter. Here is an example of 4.x and 5.x versions to give you a clear idea:

    4.x:

      SharedIndexInformer<Pod> podInformer = sharedInformerFactory.sharedIndexInformerFor(Pod.class, PodList.class, resyncPeriod);

    5.x:

    SharedIndexInformer<Pod> podInformer = factory.sharedIndexInformerFor(Pod.class, resyncPeriod);
  • SharedInformerFactory.sharedIndexInformerForCustomResource uses CustomResource as base type rather than HasMetadata. Although we're already enforcing this in our CustomResource API for your CustomResource POJOs to extend CustomResource; we've made this change more explicit in SharedInformer API.

  • Utility methods for creating Namespaced Informers. Now you don't have to provide an explicit OperationContext for creating a Namespaced Informer. You can simply use inNamespace() method for configuring namespace in SharedInformerFactory. Here is an example:

    4.x:

    SharedIndexInformer<Pod> podInformer = sharedInformerFactory.sharedIndexInformerFor(
            Pod.class,
            PodList.class,
            new OperationContext().withNamespace("default"),
            RESYNC_PERIOD);

    5.x:

    SharedIndexInformer<Pod> podInformer = factory.inNamespace("default").sharedIndexInformerFor(Pod.class, RESYNC_PERIOD);
  • No need to provide CustomResourceDefinitionContext in SharedInformerFactory.sharedIndexInformerForCustomResource. CustomResourceDefinition related information is now discovered automatically from CustomResource annotations or opinionated defaults. Here is an example of 4.x and 5.x versions for a CustomResource called Dummy, we're trying to create SharedIndexInformers.

    4.x

    Dummy.java

    import io.fabric8.kubernetes.api.model.Namespaced;
    import io.fabric8.kubernetes.api.model.ObjectMeta;
    import io.fabric8.kubernetes.client.CustomResource;
    
    public class Dummy extends CustomResource implements Namespaced {
        private DummySpec spec;
    
    
        @Override
        public String toString() {
          return "Dummy{" +
              "apiVersion='" + getApiVersion() + '\'' +
              ", metadata=" + getMetadata() +
              ", spec=" + spec +
              '}';
        }
    
        public DummySpec getSpec() {
          return spec;
        }
    
        public void setSpec(DummySpec spec) {
          this.spec = spec;
        }
    
        @Override
        public ObjectMeta getMetadata() { return super.getMetadata(); }
    }

    Create SharedIndexInformer for Dummy:

    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, 60 * 1000L);

    5.x:

    Dummy.java

    import io.fabric8.kubernetes.api.model.KubernetesResource;
    import io.fabric8.kubernetes.api.model.Namespaced;
    import io.fabric8.kubernetes.client.CustomResource;
    import io.fabric8.kubernetes.model.annotation.Group;
    import io.fabric8.kubernetes.model.annotation.Version;
    
    @Version(Dummy.VERSION)
    @Group(Dummy.GROUP)
    public class Dummy extends CustomResource<DummySpec, KubernetesResource> implements Namespaced {
      public static final String GROUP = "demo.fabric8.io";
      public static final String VERSION = "v1";
    }

    Create SharedIndexInformer for Dummy:

    SharedIndexInformer<Dummy> dummyInformer = sharedInformerFactory.sharedIndexInformerForCustomResource(Dummy.class, 60 * 1000L);

kube-validation-schema.json files renamed to validation-schema.json

kube-validation-schema.json files are no longer included in our model packaged. The equivalent file is now named validation-schema.json.

The schema URL has been updated to the latest compatible version (http://json-schema.org/draft-05/schema#)