This is the Java client for the Enonic XP Kubernetes Operator. This client includes the latest CRD model and bindings for the fabric8io/kubernetes-client.
- Installation
- K8s CRD deserialization
- K8s clients creation
- CRUD
- Watching with websockets (short lived watching)
- Watching with informers (long lived watching)
For XP Application:
dependencies {
include "com.enonic.kubernetes:client:${k8s-client-version}"
}
For non-XP Application:
dependencies {
implementation "com.enonic.kubernetes:client:${k8s-client-version}"
}
<dependency>
<groupId>com.enonic.kubernetes</groupId>
<artifactId>client</artifactId>
<version>${k8s-client-version}</version>
</dependency>
If you are using a custom jackson object mapper you can add the deserializer to it like so:
ObjectMapper objectMapper = new ObjectMapper();
CrdMappingProvider.registerDeserializer(objectMapper);
// Create config
Config config = new ConfigBuilder().
withMasterUrl( "https://<CLUSTER>" ).
withNewClientCertData( "<CA_CERT>" ).
withOauthToken( "<TOKEN>" ).
build();
// Create client
EnonicKubernetesClient client = new DefaultEnonicKubernetesClient( new DefaultKubernetesClient( config ).inAnyNamespace() );
NOTE: See more details at the fabric8io/kubernetes-client repository.
// Create
ConfigMap configMap = client.k8s().configMaps().
inNamespace( "my-namespace" ).
withName( "my-config-map" ).
create( new ConfigMapBuilder().
withData( Map.of("my", "data") ).
build() );
// Create or Replace
configMap = client.k8s().configMaps().
inNamespace( "my-namespace" ).
withName( "my-config-map" ).
createOrReplace( new ConfigMapBuilder().
withData( Map.of("my", "new-data-with-create-or-replace") ).
build() );
// Patch
configMap = client.k8s().configMaps().
inNamespace( "my-namespace" ).
withName( "my-config-map" ).
patch( new ConfigMapBuilder().
withData( Map.of("my", "new-data-with-patch") ).
build() );
// Replace
configMap = client.k8s().configMaps().
inNamespace( "my-namespace" ).
withName( "my-config-map" ).
replace( new ConfigMapBuilder().
withData( Map.of("my", "new-data-with-replace") ).
build() );
// Edit
configMap = client.k8s().configMaps().
inNamespace( "my-namespace" ).
withName( "my-config-map" ).
edit( c -> {
c.setData( Map.of( "my", "new-data-with-edit" ) );
return c;
} );
// Get
configMap = client.k8s().configMaps().
inNamespace("my-namespace").
withName( "my-config-map" ).
get();
// Delete
client.k8s().configMaps().
inNamespace("my-namespace").
withName( "my-config-map" ).
delete();
NOTE: See more details in the tests.
// Get CRD client
MixedOperation<Xp7App, Xp7App.Xp7AppList, Resource<Xp7App>> xp7AppClient = client.enonic().v1().crds().xp7apps();
// Create
Xp7App xp7App = xp7AppClient.
inNamespace( "my-namespace" ).
withName( "my-app" ).
create( new Xp7App().
withSpec( new Xp7AppSpec().
withUrl( "app-url" ) ) );
// Create or Replace
xp7App = xp7AppClient.
inNamespace( "my-namespace" ).
withName( "my-app" ).
createOrReplace( new Xp7App().
withSpec( new Xp7AppSpec().
withUrl( "app-url-with-create-or-replace" ) ) );
// Patch
xp7App = xp7AppClient.
inNamespace( "my-namespace" ).
withName( "my-app" ).
patch( new Xp7App().
withSpec( new Xp7AppSpec().
withUrl( "app-url-with-patch" ) ) );
// Replace
xp7App = xp7AppClient.
inNamespace( "my-namespace" ).
withName( "my-app" ).
replace( new Xp7App().
withSpec( new Xp7AppSpec().
withUrl( "app-url-with-replace" ) ) );
// Edit
xp7App = xp7AppClient.
inNamespace( "my-namespace" ).
withName( "my-app" ).
edit( c -> c.withSpec( new Xp7AppSpec().
withUrl( "app-url-with-edit" ) ));
// Get
xp7App = xp7AppClient.
inNamespace( "my-namespace" ).
withName( "my-app" ).
get();
// Delete
xp7AppClient.
inNamespace( "my-namespace" ).
withName( "my-app" ).
delete();
// Watch
client.k8s().configMaps().
inAnyNamespace().
watch( new Watcher<>()
{
@Override
public void eventReceived( final Action action, final ConfigMap configMap )
{
// On Update
}
@Override
public void onClose()
{
// On websocket close
}
@Override
public void onClose( final WatcherException e )
{
// On websocket exception
}
} );
You can listen to events like so:
// Watch
xp7AppClient.
inAnyNamespace().
watch( new Watcher<>()
{
@Override
public void eventReceived( final Action action, final Xp7App xp7App )
{
// On Update
}
@Override
public void onClose()
{
// On websocket close
}
@Override
public void onClose( final WatcherException e )
{
// On websocket exception
}
} );
// Get informer factory
SharedInformerFactory sharedInformerFactory = client.k8s().informers();
// Create informer
SharedIndexInformer<ConfigMap> configMapInformer = sharedInformerFactory.
sharedIndexInformerFor( ConfigMap.class, 30 * 1000L );
// Add event handler
configMapInformer.addEventHandler( new ResourceEventHandler<ConfigMap>()
{
@Override
public void onAdd( final ConfigMap configMap )
{
// On add
}
@Override
public void onUpdate( final ConfigMap configMap, final ConfigMap t1 )
{
// On update
}
@Override
public void onDelete( final ConfigMap configMap, final boolean b )
{
// On delete
}
} );
// Start all informers
sharedInformerFactory.startAllRegisteredInformers();
...
// Stop all informers
sharedInformerFactory.stopAllRegisteredInformers();
// Get informer factory
SharedInformerFactory sharedInformerFactory = client.k8s().informers();
// Create informer
SharedIndexInformer<Xp7App> xp7AppInformer = sharedInformerFactory.
sharedIndexInformerFor( Xp7App.class, 30 * 1000L );
// Add event handler
xp7AppInformer.addEventHandler( new ResourceEventHandler<Xp7App>()
{
@Override
public void onAdd( final Xp7App xp7App )
{
// On add
}
@Override
public void onUpdate( final Xp7App xp7App, final Xp7App t1 )
{
// On update
}
@Override
public void onDelete( final Xp7App xp7App, final boolean b )
{
// On delete
}
} );
// Start all informers
sharedInformerFactory.startAllRegisteredInformers();
...
// Stop all informers
sharedInformerFactory.stopAllRegisteredInformers();