-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Description
Client Version
14.0.0
Kubernetes Version
1.22.4
Java Version
Java 11
I am trying to create a SharedIndexInformer for a Kubevirt Virtual Machine Instance (custom resource - http://kubevirt.io/api-reference/main/index.html) and carry out a set of actions on add for the Custom Resource. I have used the Official Kubernetes Java client for the creation of the SharedIndexInformer (not fabric8)
I have gone ahead and created the libraries/models for the custom resource java client from the instructions given here - https://github.com/kubernetes-client/java/blob/master/docs/generate-model-from-third-party-resources.md
What I seem to be stuck at is when I am creating the sharedIndexInformer for the VMI Resource, the call to io.kubernetes.client.informer.cache.ReflectorRunnable.run() function seems to be stuck at Start listing and watching (code line - https://github.com/kubernetes-client/java/blob/master/util/src/main/java/io/kubernetes/client/informer/cache/ReflectorRunnable.java#L87)
Output Snippet
Kubeconfig Path - C:\GitFolder/config
16:31:55.867 [informer-controller-V1Pod] INFO io.kubernetes.client.informer.cache.Controller - informer#Controller: ready to run resync & reflector runnable
16:31:55.867 [informer-controller-V1alpha3VirtualMachineInstance] INFO io.kubernetes.client.informer.cache.Controller - informer#Controller: ready to run resync & reflector runnable
16:31:55.870 [informer-controller-V1Pod] INFO io.kubernetes.client.informer.cache.Controller - informer#Controller: resync skipped due to 0 full resync period
16:31:55.873 [controller-reflector-io.kubernetes.client.openapi.models.V1Pod-1] INFO io.kubernetes.client.informer.cache.ReflectorRunnable - class io.kubernetes.client.openapi.models.V1Pod#Start listing and watching...
16:31:55.873 [controller-reflector-io.kubernetes.client.kubevirt.models.V1alpha3VirtualMachineInstance-1] INFO io.kubernetes.client.informer.cache.ReflectorRunnable - class io.kubernetes.client.kubevirt.models.V1alpha3VirtualMachineInstance#Start listing and watching...
16:31:58.524 [controller-reflector-io.kubernetes.client.openapi.models.V1Pod-1] DEBUG io.kubernetes.client.informer.cache.ReflectorRunnable - class io.kubernetes.client.openapi.models.V1Pod#Extract resourceVersion 110011207 list meta
16:31:58.524 [controller-reflector-io.kubernetes.client.openapi.models.V1Pod-1] DEBUG io.kubernetes.client.informer.cache.ReflectorRunnable - class io.kubernetes.client.openapi.models.V1Pod#Start watching with 110011207...
16:31:58.524 [controller-reflector-io.kubernetes.client.openapi.models.V1Pod-1] DEBUG io.kubernetes.client.informer.cache.ReflectorRunnable - class io.kubernetes.client.openapi.models.V1Pod#Start watch with resource version 110011207
16:31:59.461 [controller-reflector-io.kubernetes.client.kubevirt.models.V1alpha3VirtualMachineInstance-1] INFO io.kubernetes.client.informer.cache.ReflectorRunnable - class io.kubernetes.client.kubevirt.models.V1alpha3VirtualMachineInstance#Start listing and watching...
16:32:00.726 [controller-reflector-io.kubernetes.client.kubevirt.models.V1alpha3VirtualMachineInstance-1] INFO io.kubernetes.client.informer.cache.ReflectorRunnable - class io.kubernetes.client.kubevirt.models.V1alpha3VirtualMachineInstance#Start listing and watching...
16:32:01.994 [controller-reflector-io.kubernetes.client.kubevirt.models.V1alpha3VirtualMachineInstance-1] INFO io.kubernetes.client.informer.cache.ReflectorRunnable - class io.kubernetes.client.kubevirt.models.V1alpha3VirtualMachineInstance#Start listing and watching...
16:32:03.267 [controller-reflector-io.kubernetes.client.kubevirt.models.V1alpha3VirtualMachineInstance-1] INFO io.kubernetes.client.informer.cache.ReflectorRunnable - class io.kubernetes.client.kubevirt.models.V1alpha3VirtualMachineInstance#Start listing and watching...
16:32:04.533 [controller-reflector-io.kubernetes.client.kubevirt.models.V1alpha3VirtualMachineInstance-1] INFO io.kubernetes.client.informer.cache.ReflectorRunnable - class io.kubernetes.client.kubevirt.models.V1alpha3VirtualMachineInstance#Start listing and watching...
16:32:05.810 [controller-reflector-io.kubernetes.client.kubevirt.models.V1alpha3VirtualMachineInstance-1] INFO io.kubernetes.client.informer.cache.ReflectorRunnable - class io.kubernetes.client.kubevirt.models.V1alpha3VirtualMachineInstance#Start listing and watching...
If you look at this output, an informer which I created from V1Pod resource seems to work correctly however that is not the case with V1alpha3VirtualMachineInstances.
Code Snippet for my Informer -
private static Call listNamespacedVmiCall(ApiClient client, String namespace, String pretty, Boolean allowWatchBookmarks, String _continue, String fieldSelector, String labelSelector, Integer limit, String resourceVersion, String resourceVersionMatch, Integer timeoutSeconds, Boolean watch, ApiCallback _callback) throws ApiException {
Object localVarPostBody = null;
String localVarPath = "/api/v1/namespaces/{namespace}/vmi".replaceAll("\\{namespace\\}", client.escapeString(namespace.toString()));
List<Pair> localVarQueryParams = new ArrayList();
List<Pair> localVarCollectionQueryParams = new ArrayList();
if (pretty != null) {
localVarQueryParams.addAll(client.parameterToPair("pretty", pretty));
}
if (allowWatchBookmarks != null) {
localVarQueryParams.addAll(client.parameterToPair("allowWatchBookmarks", allowWatchBookmarks));
}
if (_continue != null) {
localVarQueryParams.addAll(client.parameterToPair("continue", _continue));
}
if (fieldSelector != null) {
localVarQueryParams.addAll(client.parameterToPair("fieldSelector", fieldSelector));
}
if (labelSelector != null) {
localVarQueryParams.addAll(client.parameterToPair("labelSelector", labelSelector));
}
if (limit != null) {
localVarQueryParams.addAll(client.parameterToPair("limit", limit));
}
if (resourceVersion != null) {
localVarQueryParams.addAll(client.parameterToPair("resourceVersion", resourceVersion));
}
if (resourceVersionMatch != null) {
localVarQueryParams.addAll(client.parameterToPair("resourceVersionMatch", resourceVersionMatch));
}
if (timeoutSeconds != null) {
localVarQueryParams.addAll(client.parameterToPair("timeoutSeconds", timeoutSeconds));
}
if (watch != null) {
localVarQueryParams.addAll(client.parameterToPair("watch", watch));
}
Map<String, String> localVarHeaderParams = new HashMap<String, String>();
Map<String, String> localVarCookieParams = new HashMap<String, String>();
Map<String, Object> localVarFormParams = new HashMap<String, Object>();
String[] localVarAccepts = new String[]{"application/json", "application/yaml", "application/vnd.kubernetes.protobuf", "application/json;stream=watch", "application/vnd.kubernetes.protobuf;stream=watch"};
String localVarAccept = client.selectHeaderAccept(localVarAccepts);
if (localVarAccept != null) {
localVarHeaderParams.put("Accept", localVarAccept);
}
String[] localVarContentTypes = new String[0];
String localVarContentType = client.selectHeaderContentType(localVarContentTypes);
localVarHeaderParams.put("Content-Type", localVarContentType);
String[] localVarAuthNames = new String[]{"BearerToken"};
return client.buildCall(
localVarPath,
"GET",
localVarQueryParams,
localVarCollectionQueryParams,
localVarPostBody,
localVarHeaderParams,
localVarCookieParams,
localVarFormParams,
localVarAuthNames,
_callback);
}
public static SharedIndexInformer<V1alpha3VirtualMachineInstance> createVmiInformer(String namespace, SharedInformerFactory factory, CoreV1Api coreV1Api) {
ApiClient apiClient = coreV1Api.getApiClient();
SharedIndexInformer<V1alpha3VirtualMachineInstance> vmiInformer =
factory.sharedIndexInformerFor(
(CallGeneratorParams params) -> {
return listNamespacedVmiCall(
apiClient,
namespace,
null,
null,
null,
null,
null,
null,
params.resourceVersion,
null,
params.timeoutSeconds,
params.watch,
null);
},
V1alpha3VirtualMachineInstance.class,
V1alpha3VirtualMachineInstanceList.class);
vmiInformer.addEventHandler(
new ResourceEventHandler<V1alpha3VirtualMachineInstance>() {
@Override
public void onAdd(V1alpha3VirtualMachineInstance vmi) {
System.out.printf("%s VMI added! Timestamp %s\n", vmi.getMetadata().getName(),
vmi.getMetadata().getCreationTimestamp());
}
@Override
public void onUpdate(V1alpha3VirtualMachineInstance oldVmi, V1alpha3VirtualMachineInstance newVmi) {
System.out.printf(
"%s => %s VMI updated!\n",
oldVmi.getMetadata().getName(), newVmi.getMetadata().getName());
System.out.printf("Data Updated - \nDifferences between the 2 strings - %s\n",
StringUtils.difference(oldVmi.getMetadata().toString(), newVmi.getMetadata().toString()));
}
@Override
public void onDelete(V1alpha3VirtualMachineInstance vmi, boolean deletedFinalStateUnknown) {
System.out.printf("%s VMI deleted!\n", vmi.getMetadata().getName());
}
});
return vmiInformer;
}
Here listNamespacedVmiCall is the function that lists and watches for the virtual machine instance on a particular namespace. This is a static function which has been written by me.
The Virtual Machine Class has been autogenerated using the instructions from the link given above (https://github.com/kubernetes-client/java/blob/master/docs/generate-model-from-third-party-resources.md) and looks extremely similar to the V1Pod Class -
public class V1alpha3VirtualMachineInstance implements io.kubernetes.client.common.KubernetesObject {
public static final String SERIALIZED_NAME_API_VERSION = "apiVersion";
@SerializedName(SERIALIZED_NAME_API_VERSION)
private String apiVersion;
public static final String SERIALIZED_NAME_KIND = "kind";
@SerializedName(SERIALIZED_NAME_KIND)
private String kind;
public static final String SERIALIZED_NAME_METADATA = "metadata";
@SerializedName(SERIALIZED_NAME_METADATA)
private V1ObjectMeta metadata = null;
public static final String SERIALIZED_NAME_SPEC = "spec";
@SerializedName(SERIALIZED_NAME_SPEC)
private V1alpha3VirtualMachineInstanceSpec spec;
public static final String SERIALIZED_NAME_STATUS = "status";
@SerializedName(SERIALIZED_NAME_STATUS)
private V1alpha3VirtualMachineInstanceStatus status;
public V1alpha3VirtualMachineInstance apiVersion(String apiVersion) {
this.apiVersion = apiVersion;
return this;
}
/**
* APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
* @return apiVersion
**/
@javax.annotation.Nullable
@ApiModelProperty(value = "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources")
public String getApiVersion() {
return apiVersion;
}
public void setApiVersion(String apiVersion) {
this.apiVersion = apiVersion;
}
public V1alpha3VirtualMachineInstance kind(String kind) {
this.kind = kind;
return this;
}
/**
* Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
* @return kind
**/
@javax.annotation.Nullable
@ApiModelProperty(value = "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds")
public String getKind() {
return kind;
}
public void setKind(String kind) {
this.kind = kind;
}
public V1alpha3VirtualMachineInstance metadata(V1ObjectMeta metadata) {
this.metadata = metadata;
return this;
}
/**
* Get metadata
* @return metadata
**/
@javax.annotation.Nullable
@ApiModelProperty(value = "")
public V1ObjectMeta getMetadata() {
return metadata;
}
public void setMetadata(V1ObjectMeta metadata) {
this.metadata = metadata;
}
public V1alpha3VirtualMachineInstance spec(V1alpha3VirtualMachineInstanceSpec spec) {
this.spec = spec;
return this;
}
/**
* Get spec
* @return spec
**/
@ApiModelProperty(required = true, value = "")
public V1alpha3VirtualMachineInstanceSpec getSpec() {
return spec;
}
public void setSpec(V1alpha3VirtualMachineInstanceSpec spec) {
this.spec = spec;
}
public V1alpha3VirtualMachineInstance status(V1alpha3VirtualMachineInstanceStatus status) {
this.status = status;
return this;
}
/**
* Get status
* @return status
**/
@javax.annotation.Nullable
@ApiModelProperty(value = "")
public V1alpha3VirtualMachineInstanceStatus getStatus() {
return status;
}
public void setStatus(V1alpha3VirtualMachineInstanceStatus status) {
this.status = status;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
V1alpha3VirtualMachineInstance v1alpha3VirtualMachineInstance = (V1alpha3VirtualMachineInstance) o;
return Objects.equals(this.apiVersion, v1alpha3VirtualMachineInstance.apiVersion) &&
Objects.equals(this.kind, v1alpha3VirtualMachineInstance.kind) &&
Objects.equals(this.metadata, v1alpha3VirtualMachineInstance.metadata) &&
Objects.equals(this.spec, v1alpha3VirtualMachineInstance.spec) &&
Objects.equals(this.status, v1alpha3VirtualMachineInstance.status);
}
@Override
public int hashCode() {
return Objects.hash(apiVersion, kind, metadata, spec, status);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("class V1alpha3VirtualMachineInstance {\n");
sb.append(" apiVersion: ").append(toIndentedString(apiVersion)).append("\n");
sb.append(" kind: ").append(toIndentedString(kind)).append("\n");
sb.append(" metadata: ").append(toIndentedString(metadata)).append("\n");
sb.append(" spec: ").append(toIndentedString(spec)).append("\n");
sb.append(" status: ").append(toIndentedString(status)).append("\n");
sb.append("}");
return sb.toString();
}
/**
* Convert the given object to string with each line indented by 4 spaces
* (except the first line).
*/
private String toIndentedString(Object o) {
if (o == null) {
return "null";
}
return o.toString().replace("\n", "\n ");
}
}
The same can be said for V1alpha3VirtualMachineInstanceList.java (which is on the lines of V1PodList.java)
public class V1alpha3VirtualMachineInstanceList implements io.kubernetes.client.common.KubernetesListObject {
public static final String SERIALIZED_NAME_API_VERSION = "apiVersion";
@SerializedName(SERIALIZED_NAME_API_VERSION)
private String apiVersion;
public static final String SERIALIZED_NAME_ITEMS = "items";
@SerializedName(SERIALIZED_NAME_ITEMS)
private List<V1alpha3VirtualMachineInstance> items = new ArrayList<>();
public static final String SERIALIZED_NAME_KIND = "kind";
@SerializedName(SERIALIZED_NAME_KIND)
private String kind;
public static final String SERIALIZED_NAME_METADATA = "metadata";
@SerializedName(SERIALIZED_NAME_METADATA)
private V1ListMeta metadata = null;
public V1alpha3VirtualMachineInstanceList apiVersion(String apiVersion) {
this.apiVersion = apiVersion;
return this;
}
/**
* APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
* @return apiVersion
**/
@javax.annotation.Nullable
@ApiModelProperty(value = "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources")
public String getApiVersion() {
return apiVersion;
}
public void setApiVersion(String apiVersion) {
this.apiVersion = apiVersion;
}
public V1alpha3VirtualMachineInstanceList items(List<V1alpha3VirtualMachineInstance> items) {
this.items = items;
return this;
}
public V1alpha3VirtualMachineInstanceList addItemsItem(V1alpha3VirtualMachineInstance itemsItem) {
this.items.add(itemsItem);
return this;
}
/**
* List of virtualmachineinstances. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md
* @return items
**/
@ApiModelProperty(required = true, value = "List of virtualmachineinstances. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md")
public List<V1alpha3VirtualMachineInstance> getItems() {
return items;
}
public void setItems(List<V1alpha3VirtualMachineInstance> items) {
this.items = items;
}
public V1alpha3VirtualMachineInstanceList kind(String kind) {
this.kind = kind;
return this;
}
/**
* Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
* @return kind
**/
@javax.annotation.Nullable
@ApiModelProperty(value = "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds")
public String getKind() {
return kind;
}
public void setKind(String kind) {
this.kind = kind;
}
public V1alpha3VirtualMachineInstanceList metadata(V1ListMeta metadata) {
this.metadata = metadata;
return this;
}
/**
* Get metadata
* @return metadata
**/
@javax.annotation.Nullable
@ApiModelProperty(value = "")
public V1ListMeta getMetadata() {
return metadata;
}
public void setMetadata(V1ListMeta metadata) {
this.metadata = metadata;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
V1alpha3VirtualMachineInstanceList v1alpha3VirtualMachineInstanceList = (V1alpha3VirtualMachineInstanceList) o;
return Objects.equals(this.apiVersion, v1alpha3VirtualMachineInstanceList.apiVersion) &&
Objects.equals(this.items, v1alpha3VirtualMachineInstanceList.items) &&
Objects.equals(this.kind, v1alpha3VirtualMachineInstanceList.kind) &&
Objects.equals(this.metadata, v1alpha3VirtualMachineInstanceList.metadata);
}
@Override
public int hashCode() {
return Objects.hash(apiVersion, items, kind, metadata);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("class V1alpha3VirtualMachineInstanceList {\n");
sb.append(" apiVersion: ").append(toIndentedString(apiVersion)).append("\n");
sb.append(" items: ").append(toIndentedString(items)).append("\n");
sb.append(" kind: ").append(toIndentedString(kind)).append("\n");
sb.append(" metadata: ").append(toIndentedString(metadata)).append("\n");
sb.append("}");
return sb.toString();
}
/**
* Convert the given object to string with each line indented by 4 spaces
* (except the first line).
*/
private String toIndentedString(Object o) {
if (o == null) {
return "null";
}
return o.toString().replace("\n", "\n ");
}
}
I am really not sure where I am going wrong here since both classes implement io.kubernetes.client.common.KubernetesListObject and can work exactly like the V1Pod and V1PodList classes. Can someone tell me what I am doing wrong here ?
The way I am creating my informer is as follows -
String kubeConfigPath = System.getenv("HOME") + "/config";
System.out.println("Kubeconfig Path - " + kubeConfigPath);
// loading the out-of-cluster config, a kubeconfig from file-system
ApiClient client =
ClientBuilder.kubeconfig(KubeConfig.loadKubeConfig(new FileReader(kubeConfigPath))).build();
// set the global default api-client to the in-cluster one from above
Configuration.setDefaultApiClient(client);
CoreV1Api coreV1Api = new CoreV1Api();
ApiClient apiClient = coreV1Api.getApiClient();
OkHttpClient httpClient =
apiClient.getHttpClient().newBuilder().readTimeout(0, TimeUnit.SECONDS).build();
apiClient.setHttpClient(httpClient);
SharedInformerFactory factory = new SharedInformerFactory();
SharedIndexInformer<V1alpha3VirtualMachineInstance> vmiInformer = createVmiInformer(<namespace>, factory, coreV1Api);
factory.startAllRegisteredInformers();
Any ideas would help me proceed here would be welcome.