Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extension development using only api and resource/resourceList implementations #3858

Merged
merged 15 commits into from
Mar 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 92 additions & 3 deletions doc/MIGRATION-v6.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,55 @@
# Migration from 5.x to 6.x

## Contents:
- [Namespace Changes](#namespace-changes)
- [API/Impl split](#api-impl-split)
- [Deprecation Removals](#deprecation-removals)
- [IntOrString changes](#intorstring-changes)
- [Resource Changes](#resource-changes)
- [lists Removal](#lists-removal)
- [GenericKubernetesClient Removal](#generickubernetesclient-removal)
- [IntOrString Changes](#intorstring-changes)
- [ServiceCatalog Changes](#service-catalog-changes)
- [Adapt Changes](#adapt-changes)
- [Deprecations](#deprecations)
- [Object sorting](#object-sorting)

## Namespace Changes

To match the behavior of kubectl the client will now consider any call to inNamespace as the namespace to use regardless of what is on a passed in item.
Only if the client is left at the default namespace or a call has been made to inAnyNamespace will the item namespace be used.
This applies to all calls to inNamespace - at the Client, Operation, or Resource level, and for all operations (load, create, delete, withItem, etc.)

The end result is that exceptions refering to mismatched namespaces will no longer be thrown.

Consider the following examples:

// inNamespace called at the client level with load
// Prior behavior - exception if item has a namespace that is not monitoring.
// New behavior - the item namespace is monitoring
this.kubernetesClient.inNamespace("monitoring").configMaps().load(item)...

// inNamespace called at an operation level with load
// Prior behavior - exception if item has a namespace that is not monitoring.
// New behavior - the item namespace is monitoring
this.kubernetesClient.configMaps().inNamespace("monitoring").load(item)...

// inNamespace called at the client level with resource
// Prior behavior - context namespace is changed to match the item.
// New behavior - the item namespace is monitoring
this.kubernetesClient.inNamespace("monitoring").resource(item)...

// default namespace call to create
// Prior behavior - exception if item has a namespace that does not match the context.
// New behavior - item will be created with its namespace, or the default if missing
this.kubernetesClient.configMaps().create(item);

// default namespace call to load
// Prior behavior - exception if item has a namespace that does not match the context.
// New behavior - item will be loaded with its namespace, or the default if missing
this.kubernetesClient.configMaps().load(item)...

To track the namespace handling at the client level the Config has an additional boolean field defaultNamespace, you may set that to false to have the Client treat subsequent calls as if inNamespace had been called explicitly.

## API/Impl split

This release introduces kubernetes-client-api and openshift-client-api modules. You may use them as compile dependencies in your application with the respective kubernetes-client and openshift-client as runtime dependencies. This will keep you compile classpath cleaner of classes and libraries that are not intentionally exposed by the fabric8 client.
Expand Down Expand Up @@ -37,6 +81,39 @@ To use it, exclude the kubernetes-httpclient-okhttp dependency and add the kuber
- Removed methods on SharedInformerFactory dealing with the OperationContext
- Removed DefaultKubernetesClient and DefaultOpenShiftClient constructors directly referencing OkHttp - use OkHttpClientImpl to wrap the OkHttpClient, or the OkHttpClientFactory instead.

### Extension Development

Extension development may now be done using only the kubernetes-client-api dependency. Please see the [extensions](../extensions).

## Resource Changes

KubernetesClient.resource no longer returns NamespaceVisitFromServerGetWatchDeleteRecreateWaitApplicable, use NamespaceableResource instead.

This may require you to implement previously deprecated methods on your own. For example, instead of:

client.resource(deployment).inNamespace(session.getNamespace()).deletingExisting().createOrReplace();

Use:

var resource = client.resource(deployment).inNamespace(session.getNamespace());
resource.delete();
resource.waitUntilCondition(Objects::isNull, 30, TimeUnit.SECONDS);
resource.create();

## lists Removal

KuberentesClient.lists was removed. This entry point is effectively the same as KubernetesClient.resourceList or load. Please use one of those methods instead.

For example:

Instead of KubernetesClient.lists().load, use KubernetesClient.resourceList or load
Instead of KubernetesClient.lists().create(list), use KubernetesClient.resourceList(list.getItems()).create()
Instead of KubernetesClient.lists().delete(list), use KubernetesClient.resourceList(list.getItems()).delete()

## GenericKubernetesClient Removal

GenericKubernetesClient has been removed. Instead the relevant methods are on NamespacedKubernetesClient and NamespacedOpenShiftClient directly.

## IntOrString changes

We've removed setter methods `setIntVal`, `setKind`, `setStrVal` from the class. You'd need to rely on constructors or builders for creating `IntOrString` object. Here are some examples:
Expand Down Expand Up @@ -65,7 +142,19 @@ We've removed setter methods `setIntVal`, `setKind`, `setStrVal` from the class.
IntOrString i2 = new IntOrString("3000");
String strValue = i2.getStrVal();
```


## Service Catalog Changes

io.fabric8.servicecatalog.client.internal.XXXResource interfaces moved to io.fabric8.servicecatalog.client.dsl.XXXResource to no longer be in an internal package.

## Adapt Changes

Client.isAdaptable and Client.adapt will check first if the existing instance is compatible with the desired type.

## Deprecations

- ApiVersionUtil classes in each extension have been deprecated, you should use io.fabric8.kubernetes.client.utils.ApiVersionUtil instead.

## Object Sorting

KubernetesList and Template will no longer automatically sort their objects by default. You may use the HasMetadataComparator to sort the items as needed.
KubernetesList and Template will no longer automatically sort their objects by default. You may use the HasMetadataComparator to sort the items as needed.
5 changes: 5 additions & 0 deletions extensions/camel-k/client/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,14 @@
<groupId>io.fabric8</groupId>
<artifactId>camel-k-model-v1</artifactId>
</dependency>
<dependency>
<groupId>io.fabric8</groupId>
<artifactId>kubernetes-client-api</artifactId>
</dependency>
<dependency>
<groupId>io.fabric8</groupId>
<artifactId>kubernetes-client</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,14 @@

import io.fabric8.camelk.client.dsl.V1APIGroupDSL;
import io.fabric8.camelk.client.dsl.V1alpha1APIGroupDSL;
import io.fabric8.kubernetes.client.BaseClient;
import io.fabric8.kubernetes.client.ClientContext;
import io.fabric8.kubernetes.client.Client;
import io.fabric8.kubernetes.client.Config;
import io.fabric8.kubernetes.client.ConfigBuilder;
import io.fabric8.kubernetes.client.RequestConfig;
import io.fabric8.kubernetes.client.WithRequestCallable;
import io.fabric8.kubernetes.client.dsl.FunctionCallable;
import io.fabric8.kubernetes.client.extension.ClientAdapter;

public class DefaultCamelKClient extends BaseClient implements NamespacedCamelKClient {
public class DefaultCamelKClient extends ClientAdapter<DefaultCamelKClient> implements NamespacedCamelKClient {

public DefaultCamelKClient() {
super();
Expand All @@ -35,25 +34,16 @@ public DefaultCamelKClient(Config configuration) {
super(configuration);
}

public DefaultCamelKClient(ClientContext clientContext) {
super(clientContext);
public DefaultCamelKClient(Client client) {
super(client);
}

@Override
public NamespacedCamelKClient inAnyNamespace() {
return inNamespace(null);
protected DefaultCamelKClient newInstance(Client client) {
return new DefaultCamelKClient(client);
}

@Override
public NamespacedCamelKClient inNamespace(String namespace) {
Config updated = new ConfigBuilder(getConfiguration())
.withNamespace(namespace)
.build();

return new DefaultCamelKClient(newState(updated));
}

@Override
public FunctionCallable<NamespacedCamelKClient> withRequestConfig(RequestConfig requestConfig) {
return new WithRequestCallable<>(this, requestConfig);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,44 +26,49 @@
import io.fabric8.camelk.v1.IntegrationList;
import io.fabric8.camelk.v1.IntegrationPlatform;
import io.fabric8.camelk.v1.IntegrationPlatformList;
import io.fabric8.kubernetes.client.BaseClient;
import io.fabric8.kubernetes.client.ClientContext;
import io.fabric8.kubernetes.client.Handlers;
import io.fabric8.kubernetes.client.Client;
import io.fabric8.kubernetes.client.dsl.MixedOperation;
import io.fabric8.kubernetes.client.dsl.Resource;
import io.fabric8.kubernetes.client.extension.ClientAdapter;

public class V1APIGroupClient extends BaseClient implements V1APIGroupDSL {
public V1APIGroupClient() {
super();
}
public class V1APIGroupClient extends ClientAdapter<V1APIGroupClient> implements V1APIGroupDSL {

public V1APIGroupClient(ClientContext clientContext) {
super(clientContext);
}
public V1APIGroupClient() {
super();
}

@Override
public MixedOperation<Build, BuildList, Resource<Build>> builds() {
return Handlers.getOperation(Build.class, BuildList.class, this);
}
public V1APIGroupClient(Client client) {
super(client);
}

@Override
public MixedOperation<CamelCatalog, CamelCatalogList, Resource<CamelCatalog>> camelCatalogs() {
return Handlers.getOperation(CamelCatalog.class, CamelCatalogList.class, this);
}
@Override
protected V1APIGroupClient newInstance(Client client) {
return new V1APIGroupClient(client);
}

@Override
public MixedOperation<Integration, IntegrationList, Resource<Integration>> integrations() {
return Handlers.getOperation(Integration.class, IntegrationList.class, this);
}
@Override
public MixedOperation<Build, BuildList, Resource<Build>> builds() {
return resources(Build.class, BuildList.class);
}

@Override
public MixedOperation<IntegrationKit, IntegrationKitList, Resource<IntegrationKit>> integrationKits() {
return Handlers.getOperation(IntegrationKit.class, IntegrationKitList.class, this);
}
@Override
public MixedOperation<CamelCatalog, CamelCatalogList, Resource<CamelCatalog>> camelCatalogs() {
return resources(CamelCatalog.class, CamelCatalogList.class);
}

@Override
public MixedOperation<IntegrationPlatform, IntegrationPlatformList, Resource<IntegrationPlatform>> integrationPlatforms() {
return Handlers.getOperation(IntegrationPlatform.class, IntegrationPlatformList.class, this);
}
@Override
public MixedOperation<Integration, IntegrationList, Resource<Integration>> integrations() {
return resources(Integration.class, IntegrationList.class);
}

@Override
public MixedOperation<IntegrationKit, IntegrationKitList, Resource<IntegrationKit>> integrationKits() {
return resources(IntegrationKit.class, IntegrationKitList.class);
}

@Override
public MixedOperation<IntegrationPlatform, IntegrationPlatformList, Resource<IntegrationPlatform>> integrationPlatforms() {
return resources(IntegrationPlatform.class, IntegrationPlatformList.class);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,28 @@
import io.fabric8.camelk.client.dsl.V1alpha1APIGroupDSL;
import io.fabric8.camelk.v1alpha1.Kamelet;
import io.fabric8.camelk.v1alpha1.KameletList;
import io.fabric8.kubernetes.client.BaseClient;
import io.fabric8.kubernetes.client.ClientContext;
import io.fabric8.kubernetes.client.Handlers;
import io.fabric8.kubernetes.client.Client;
import io.fabric8.kubernetes.client.dsl.MixedOperation;
import io.fabric8.kubernetes.client.dsl.Resource;
import io.fabric8.kubernetes.client.extension.ClientAdapter;

public class V1alpha1APIGroupClient extends BaseClient implements V1alpha1APIGroupDSL {
public class V1alpha1APIGroupClient extends ClientAdapter<V1alpha1APIGroupClient> implements V1alpha1APIGroupDSL {

public V1alpha1APIGroupClient() {
super();
}

public V1alpha1APIGroupClient(ClientContext clientContext) {
super(clientContext);
public V1alpha1APIGroupClient(Client client) {
super(client);
}

@Override
protected V1alpha1APIGroupClient newInstance(Client client) {
return new V1alpha1APIGroupClient(client);
}

@Override
public MixedOperation<Kamelet, KameletList, Resource<Kamelet>> kamelets() {
return Handlers.getOperation(Kamelet.class, KameletList.class, this);
return resources(Kamelet.class, KameletList.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,19 @@
*/
package io.fabric8.camelk.client.dsl;

import io.fabric8.kubernetes.client.Client;
import io.fabric8.kubernetes.client.dsl.MixedOperation;
import io.fabric8.kubernetes.client.dsl.NonNamespaceOperation;
import io.fabric8.kubernetes.client.dsl.Resource;
import io.fabric8.camelk.v1.Build;
import io.fabric8.camelk.v1.BuildList;
import io.fabric8.camelk.v1.CamelCatalog;
import io.fabric8.camelk.v1.CamelCatalogList;
import io.fabric8.camelk.v1.Integration;
import io.fabric8.camelk.v1.IntegrationList;
import io.fabric8.camelk.v1.IntegrationKit;
import io.fabric8.camelk.v1.IntegrationKitList;
import io.fabric8.camelk.v1.IntegrationList;
import io.fabric8.camelk.v1.IntegrationPlatform;
import io.fabric8.camelk.v1.IntegrationPlatformList;
import io.fabric8.kubernetes.client.Client;
import io.fabric8.kubernetes.client.dsl.MixedOperation;
import io.fabric8.kubernetes.client.dsl.Resource;

public interface V1APIGroupDSL extends Client {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,17 @@
import io.fabric8.kubernetes.api.model.HasMetadata;
import io.fabric8.kubernetes.client.utils.Utils;

/** Borrowed from the client. */
/**
* @deprecated
* @see io.fabric8.kubernetes.client.utils.ApiVersionUtil
*/
@Deprecated
public class ApiVersionUtil {

private ApiVersionUtil() {
throw new IllegalStateException("Utility class");
}

/**
* Extracts apiGroupName from apiGroupVersion when in resource for apiGroupName/acpiGroupVersion
* combination
Expand All @@ -34,7 +38,7 @@ private ApiVersionUtil() {
* @param apiGroup apiGroupName present if any
* @return Just the apiGroupName part without apiGroupVersion
*/

public static <T> String apiGroup(T item, String apiGroup) {
if (item instanceof HasMetadata
&& Utils.isNotNullOrEmpty(((HasMetadata) item).getApiVersion())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,23 @@
import io.fabric8.kubernetes.client.utils.Utils;

/**
* Borrowed from the client.
* @deprecated
* @see io.fabric8.kubernetes.client.utils.ApiVersionUtil
*/
@Deprecated
public class ApiVersionUtil {

private ApiVersionUtil() {
throw new IllegalStateException("Utility class");
}

/**
* Extracts apiGroupName from apiGroupVersion when in resource for apiGroupName/apiGroupVersion combination
* @param item resource which is being used
* @param apiGroup apiGroupName present if any
* @return Just the apiGroupName part without apiGroupVersion
*/

public static <T> String apiGroup(T item, String apiGroup) {
if (item instanceof HasMetadata && Utils.isNotNullOrEmpty(((HasMetadata) item).getApiVersion())) {
return trimGroupOrNull(((HasMetadata) item).getApiVersion());
Expand Down
Loading