From 9cf59383d632d297b212453afc834f5dd228756b Mon Sep 17 00:00:00 2001 From: shawkins Date: Sat, 14 Aug 2021 07:35:06 -0400 Subject: [PATCH] fix #3294 #3303 exposing apigroups and apiresource also trying to consolidate existing logic about openshift adapting --- CHANGELOG.md | 2 + .../fabric8/kubernetes/client/BaseClient.java | 23 +- .../io/fabric8/kubernetes/client/Client.java | 16 ++ .../io/fabric8/kubernetes/client/Config.java | 5 + .../client/dsl/base/BaseOperation.java | 12 +- .../kubernetes/ApiGroupResourceListsIT.java | 54 +++++ .../java/io/fabric8/kubernetes/EventsIT.java | 3 - .../cmd/generate/generate.go | 2 + .../kubernetes/api/model/APIResource.java | 210 ++++++++++++++++++ .../kubernetes/api/model/APIResourceList.java | 147 ++++++++++++ .../kubernetes/api/model/KubeSchema.java | 32 ++- .../main/resources/schema/kube-schema.json | 89 ++++++++ .../resources/schema/validation-schema.json | 160 +++++++++++++ .../client/DefaultOpenShiftClient.java | 39 +--- .../NamespacedOpenShiftExtensionAdapter.java | 9 - .../openshift/client/OpenShiftConfig.java | 19 ++ .../client/OpenShiftExtensionAdapter.java | 10 - .../client/OpenshiftAdapterSupport.java | 85 +------ 18 files changed, 782 insertions(+), 135 deletions(-) create mode 100644 kubernetes-itests/src/test/java/io/fabric8/kubernetes/ApiGroupResourceListsIT.java create mode 100644 kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/APIResource.java create mode 100644 kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/APIResourceList.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 05d2a0d9da4..5d8ab9975c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ #### Dependency Upgrade #### New Features +* Fix #3294: Support fetching APIGroupList +* Fix #3303: Support fetching APIResourceList #### _**Note**_: Breaking changes in the API diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/BaseClient.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/BaseClient.java index ff01d469dde..f36119e478e 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/BaseClient.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/BaseClient.java @@ -21,6 +21,8 @@ import okhttp3.ConnectionPool; import okhttp3.Dispatcher; import okhttp3.OkHttpClient; +import io.fabric8.kubernetes.api.model.APIGroupList; +import io.fabric8.kubernetes.api.model.APIResourceList; import io.fabric8.kubernetes.api.model.RootPaths; import io.fabric8.kubernetes.client.dsl.base.BaseOperation; import io.fabric8.kubernetes.client.utils.HttpClientUtils; @@ -32,6 +34,8 @@ public abstract class BaseClient implements Client, HttpClientAware { + + public static final String APIS = "/apis"; protected OkHttpClient httpClient; private URL masterUrl; @@ -53,7 +57,7 @@ public BaseClient(final Config config) { public BaseClient(final OkHttpClient httpClient, Config config) { try { - this.httpClient = httpClient; + this.httpClient = config.adaptClient(httpClient); this.namespace = config.getNamespace(); this.configuration = config; this.apiVersion = config.getApiVersion(); @@ -134,8 +138,11 @@ public C adapt(Class type) { @Override public RootPaths rootPaths() { - return new BaseOperation(new OperationContext().withOkhttpClient(httpClient).withConfig(configuration)) { - }.getRootPaths(); + return newBaseOperation(httpClient, configuration).getRootPaths(); + } + + static BaseOperation newBaseOperation(OkHttpClient httpClient, Config configuration) { + return new BaseOperation(new OperationContext().withOkhttpClient(httpClient).withConfig(configuration)) {}; } @Override @@ -153,4 +160,14 @@ public boolean supportsApiPath(String apiPath) { } return false; } + + @Override + public APIGroupList getApiGroups() { + return newBaseOperation(httpClient, configuration).restCall(APIGroupList.class, APIS); + } + + @Override + public APIResourceList getApiResources(String groupVersion) { + return newBaseOperation(httpClient, configuration).restCall(APIResourceList.class, APIS, groupVersion); + } } diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/Client.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/Client.java index 562cb9a016e..660a6345962 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/Client.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/Client.java @@ -16,6 +16,8 @@ package io.fabric8.kubernetes.client; +import io.fabric8.kubernetes.api.model.APIGroupList; +import io.fabric8.kubernetes.api.model.APIResourceList; import io.fabric8.kubernetes.api.model.RootPaths; import java.io.Closeable; @@ -48,5 +50,19 @@ public interface Client extends ConfigAware, Closeable { */ boolean supportsApiPath(String path); + @Override void close(); + + /** + * Returns the api groups + * @return the {@link APIGroupList} metadata + */ + APIGroupList getApiGroups(); + + /** + * Return the api resource metadata for the given groupVersion + * @param the groupVersion - group/version + * @return the {@link APIResourceList} for the groupVersion + */ + APIResourceList getApiResources(String groupVersion); } diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/Config.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/Config.java index 1d137157d14..6c0f6e69235 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/Config.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/Config.java @@ -55,6 +55,7 @@ import io.fabric8.kubernetes.client.utils.Serialization; import io.fabric8.kubernetes.client.utils.Utils; import io.sundr.builder.annotations.Buildable; +import okhttp3.OkHttpClient; import okhttp3.TlsVersion; @JsonInclude(JsonInclude.Include.NON_NULL) @@ -1341,4 +1342,8 @@ public Readiness getReadiness() { return Readiness.getInstance(); } + public OkHttpClient adaptClient(OkHttpClient httpClient) { + return httpClient; + } + } diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/base/BaseOperation.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/base/BaseOperation.java index 15402a04878..eb86ddd7c0c 100755 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/base/BaseOperation.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/base/BaseOperation.java @@ -195,10 +195,18 @@ public T getMandatory() { } public RootPaths getRootPaths() { + return restCall(RootPaths.class); + } + + public Res restCall(Class result, String... path) { try { URL requestUrl = new URL(config.getMasterUrl()); - Request.Builder req = new Request.Builder().get().url(requestUrl); - return handleResponse(req, RootPaths.class); + String url = requestUrl.toString(); + if (path != null && path.length > 0) { + url = URLUtils.join(url, URLUtils.pathJoin(path)); + } + Request.Builder req = new Request.Builder().get().url(url); + return handleResponse(req, result); } catch (KubernetesClientException e) { if (e.getCode() != HttpURLConnection.HTTP_NOT_FOUND) { throw e; diff --git a/kubernetes-itests/src/test/java/io/fabric8/kubernetes/ApiGroupResourceListsIT.java b/kubernetes-itests/src/test/java/io/fabric8/kubernetes/ApiGroupResourceListsIT.java new file mode 100644 index 00000000000..2e551584781 --- /dev/null +++ b/kubernetes-itests/src/test/java/io/fabric8/kubernetes/ApiGroupResourceListsIT.java @@ -0,0 +1,54 @@ +/** + * 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; + +import io.fabric8.kubernetes.api.model.APIGroupList; +import io.fabric8.kubernetes.api.model.APIResourceList; +import io.fabric8.kubernetes.client.KubernetesClient; +import org.arquillian.cube.kubernetes.api.Session; +import org.arquillian.cube.kubernetes.impl.requirement.RequiresKubernetes; +import org.arquillian.cube.requirement.ArquillianConditionalRunner; +import org.jboss.arquillian.test.api.ArquillianResource; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.assertTrue; + +@RunWith(ArquillianConditionalRunner.class) +@RequiresKubernetes +public class ApiGroupResourceListsIT { + + @ArquillianResource + KubernetesClient client; + + @ArquillianResource + Session session; + + @Test + public void testApiGroups() throws InterruptedException { + APIGroupList list = client.getApiGroups(); + + assertTrue(list.getGroups().stream().anyMatch(g -> "apps".equals(g.getName()))); + } + + @Test + public void testApiResources() throws InterruptedException { + APIResourceList list = client.getApiResources("apps/v1"); + + assertTrue(list.getResources().stream().anyMatch(r -> "deployments".equals(r.getName()))); + } +} diff --git a/kubernetes-itests/src/test/java/io/fabric8/kubernetes/EventsIT.java b/kubernetes-itests/src/test/java/io/fabric8/kubernetes/EventsIT.java index 6bc5062ebd8..10c07a407a7 100644 --- a/kubernetes-itests/src/test/java/io/fabric8/kubernetes/EventsIT.java +++ b/kubernetes-itests/src/test/java/io/fabric8/kubernetes/EventsIT.java @@ -28,9 +28,6 @@ import org.junit.Test; import org.junit.runner.RunWith; -import java.time.OffsetDateTime; -import java.time.format.DateTimeFormatter; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; diff --git a/kubernetes-model-generator/kubernetes-model-core/cmd/generate/generate.go b/kubernetes-model-generator/kubernetes-model-core/cmd/generate/generate.go index 4b3ed3b7b31..705a87e7639 100644 --- a/kubernetes-model-generator/kubernetes-model-core/cmd/generate/generate.go +++ b/kubernetes-model-generator/kubernetes-model-core/cmd/generate/generate.go @@ -39,6 +39,8 @@ type Schema struct { Info apimachineryversion.Info APIGroup metav1.APIGroup APIGroupList metav1.APIGroupList + APIResource metav1.APIResource + APIResourceList metav1.APIResourceList BaseKubernetesList metav1.List ObjectMeta metav1.ObjectMeta TypeMeta metav1.TypeMeta diff --git a/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/APIResource.java b/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/APIResource.java new file mode 100644 index 00000000000..beb388773a1 --- /dev/null +++ b/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/APIResource.java @@ -0,0 +1,210 @@ + +package io.fabric8.kubernetes.api.model; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import io.sundr.builder.annotations.Buildable; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@JsonDeserialize(using = com.fasterxml.jackson.databind.JsonDeserializer.None.class) +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "apiVersion", + "kind", + "metadata", + "categories", + "group", + "name", + "namespaced", + "shortNames", + "singularName", + "storageVersionHash", + "verbs", + "version" +}) +@ToString +@EqualsAndHashCode +@Buildable(editableEnabled = false, validationEnabled = false, generateBuilderPackage = true, lazyCollectionInitEnabled = false, builderPackage = "io.fabric8.kubernetes.api.builder") +public class APIResource implements KubernetesResource +{ + + @JsonProperty("categories") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private List categories = new ArrayList(); + @JsonProperty("group") + private String group; + @JsonProperty("kind") + private String kind; + @JsonProperty("name") + private String name; + @JsonProperty("namespaced") + private Boolean namespaced; + @JsonProperty("shortNames") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private List shortNames = new ArrayList(); + @JsonProperty("singularName") + private String singularName; + @JsonProperty("storageVersionHash") + private String storageVersionHash; + @JsonProperty("verbs") + private List verbs = new ArrayList(); + @JsonProperty("version") + private String version; + @JsonIgnore + private Map additionalProperties = new HashMap(); + + /** + * No args constructor for use in serialization + * + */ + public APIResource() { + } + + /** + * + * @param shortNames + * @param kind + * @param name + * @param storageVersionHash + * @param verbs + * @param categories + * @param version + * @param namespaced + * @param group + * @param singularName + */ + public APIResource(List categories, String group, String kind, String name, Boolean namespaced, List shortNames, String singularName, String storageVersionHash, List verbs, String version) { + super(); + this.categories = categories; + this.group = group; + this.kind = kind; + this.name = name; + this.namespaced = namespaced; + this.shortNames = shortNames; + this.singularName = singularName; + this.storageVersionHash = storageVersionHash; + this.verbs = verbs; + this.version = version; + } + + @JsonProperty("categories") + public List getCategories() { + return categories; + } + + @JsonProperty("categories") + public void setCategories(List categories) { + this.categories = categories; + } + + @JsonProperty("group") + public String getGroup() { + return group; + } + + @JsonProperty("group") + public void setGroup(String group) { + this.group = group; + } + + @JsonProperty("kind") + public String getKind() { + return kind; + } + + @JsonProperty("kind") + public void setKind(String kind) { + this.kind = kind; + } + + @JsonProperty("name") + public String getName() { + return name; + } + + @JsonProperty("name") + public void setName(String name) { + this.name = name; + } + + @JsonProperty("namespaced") + public Boolean getNamespaced() { + return namespaced; + } + + @JsonProperty("namespaced") + public void setNamespaced(Boolean namespaced) { + this.namespaced = namespaced; + } + + @JsonProperty("shortNames") + public List getShortNames() { + return shortNames; + } + + @JsonProperty("shortNames") + public void setShortNames(List shortNames) { + this.shortNames = shortNames; + } + + @JsonProperty("singularName") + public String getSingularName() { + return singularName; + } + + @JsonProperty("singularName") + public void setSingularName(String singularName) { + this.singularName = singularName; + } + + @JsonProperty("storageVersionHash") + public String getStorageVersionHash() { + return storageVersionHash; + } + + @JsonProperty("storageVersionHash") + public void setStorageVersionHash(String storageVersionHash) { + this.storageVersionHash = storageVersionHash; + } + + @JsonProperty("verbs") + public List getVerbs() { + return verbs; + } + + @JsonProperty("verbs") + public void setVerbs(List verbs) { + this.verbs = verbs; + } + + @JsonProperty("version") + public String getVersion() { + return version; + } + + @JsonProperty("version") + public void setVersion(String version) { + this.version = version; + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + +} diff --git a/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/APIResourceList.java b/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/APIResourceList.java new file mode 100644 index 00000000000..4874bfee038 --- /dev/null +++ b/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/APIResourceList.java @@ -0,0 +1,147 @@ + +package io.fabric8.kubernetes.api.model; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import io.sundr.builder.annotations.Buildable; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@JsonDeserialize(using = com.fasterxml.jackson.databind.JsonDeserializer.None.class) +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "apiVersion", + "kind", + "metadata", + "groupVersion", + "resources" +}) +@ToString +@EqualsAndHashCode +@Buildable(editableEnabled = false, validationEnabled = false, generateBuilderPackage = true, lazyCollectionInitEnabled = false, builderPackage = "io.fabric8.kubernetes.api.builder") +public class APIResourceList implements KubernetesResource +{ + + /** + * + * (Required) + * + */ + @JsonProperty("apiVersion") + private String apiVersion = "v1"; + @JsonProperty("groupVersion") + private String groupVersion; + /** + * + * (Required) + * + */ + @JsonProperty("kind") + private String kind = "APIResourceList"; + @JsonProperty("resources") + private List resources = new ArrayList(); + @JsonIgnore + private Map additionalProperties = new HashMap(); + + /** + * No args constructor for use in serialization + * + */ + public APIResourceList() { + } + + /** + * + * @param apiVersion + * @param kind + * @param groupVersion + * @param resources + */ + public APIResourceList(String apiVersion, String groupVersion, String kind, List resources) { + super(); + this.apiVersion = apiVersion; + this.groupVersion = groupVersion; + this.kind = kind; + this.resources = resources; + } + + /** + * + * (Required) + * + */ + @JsonProperty("apiVersion") + public String getApiVersion() { + return apiVersion; + } + + /** + * + * (Required) + * + */ + @JsonProperty("apiVersion") + public void setApiVersion(String apiVersion) { + this.apiVersion = apiVersion; + } + + @JsonProperty("groupVersion") + public String getGroupVersion() { + return groupVersion; + } + + @JsonProperty("groupVersion") + public void setGroupVersion(String groupVersion) { + this.groupVersion = groupVersion; + } + + /** + * + * (Required) + * + */ + @JsonProperty("kind") + public String getKind() { + return kind; + } + + /** + * + * (Required) + * + */ + @JsonProperty("kind") + public void setKind(String kind) { + this.kind = kind; + } + + @JsonProperty("resources") + public List getResources() { + return resources; + } + + @JsonProperty("resources") + public void setResources(List resources) { + this.resources = resources; + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + +} diff --git a/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/KubeSchema.java b/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/KubeSchema.java index 0488ad7ff01..ece309118bb 100644 --- a/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/KubeSchema.java +++ b/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/KubeSchema.java @@ -23,6 +23,8 @@ "metadata", "APIGroup", "APIGroupList", + "APIResource", + "APIResourceList", "APIService", "APIServiceList", "BaseKubernetesList", @@ -92,6 +94,10 @@ public class KubeSchema { private APIGroup aPIGroup; @JsonProperty("APIGroupList") private APIGroupList aPIGroupList; + @JsonProperty("APIResource") + private APIResource aPIResource; + @JsonProperty("APIResourceList") + private APIResourceList aPIResourceList; @JsonProperty("APIService") private APIService aPIService; @JsonProperty("APIServiceList") @@ -239,6 +245,7 @@ public KubeSchema() { * @param groupVersionResource * @param limitRangeList * @param toleration + * @param aPIResourceList * @param nodeList * @param groupVersionKind * @param node @@ -269,6 +276,7 @@ public KubeSchema() { * @param microTime * @param podExecOptions * @param serviceAccount + * @param aPIResource * @param resourceQuotaList * @param topologySelectorTerm * @param createOptions @@ -284,10 +292,12 @@ public KubeSchema() { * @param endpointPort * @param config */ - public KubeSchema(APIGroup aPIGroup, APIGroupList aPIGroupList, APIService aPIService, APIServiceList aPIServiceList, BaseKubernetesList baseKubernetesList, Binding binding, ComponentStatus componentStatus, ComponentStatusList componentStatusList, Condition condition, Config config, ConfigMap configMap, ConfigMapList configMapList, ContainerStatus containerStatus, CreateOptions createOptions, DeleteOptions deleteOptions, EndpointPort endpointPort, Endpoints endpoints, EndpointsList endpointsList, EnvVar envVar, Event event, EventList eventList, EventSeries eventSeries, EventSource eventSource, GetOptions getOptions, GroupVersionKind groupVersionKind, GroupVersionResource groupVersionResource, Info info, LimitRangeList limitRangeList, ListOptions listOptions, MicroTime microTime, Namespace namespace, NamespaceList namespaceList, Node node, NodeList nodeList, ObjectMeta objectMeta, Patch patch, PatchOptions patchOptions, PersistentVolume persistentVolume, PersistentVolumeClaim persistentVolumeClaim, PersistentVolumeClaimList persistentVolumeClaimList, PersistentVolumeList persistentVolumeList, PodExecOptions podExecOptions, PodList podList, PodTemplateList podTemplateList, Quantity quantity, ReplicationControllerList replicationControllerList, ResourceQuota resourceQuota, ResourceQuotaList resourceQuotaList, RootPaths rootPaths, Secret secret, SecretList secretList, ServiceAccount serviceAccount, ServiceAccountList serviceAccountList, ServiceList serviceList, Status status, String time, Toleration toleration, TopologySelectorTerm topologySelectorTerm, TypeMeta typeMeta, UpdateOptions updateOptions, WatchEvent watchEvent) { + public KubeSchema(APIGroup aPIGroup, APIGroupList aPIGroupList, APIResource aPIResource, APIResourceList aPIResourceList, APIService aPIService, APIServiceList aPIServiceList, BaseKubernetesList baseKubernetesList, Binding binding, ComponentStatus componentStatus, ComponentStatusList componentStatusList, Condition condition, Config config, ConfigMap configMap, ConfigMapList configMapList, ContainerStatus containerStatus, CreateOptions createOptions, DeleteOptions deleteOptions, EndpointPort endpointPort, Endpoints endpoints, EndpointsList endpointsList, EnvVar envVar, Event event, EventList eventList, EventSeries eventSeries, EventSource eventSource, GetOptions getOptions, GroupVersionKind groupVersionKind, GroupVersionResource groupVersionResource, Info info, LimitRangeList limitRangeList, ListOptions listOptions, MicroTime microTime, Namespace namespace, NamespaceList namespaceList, Node node, NodeList nodeList, ObjectMeta objectMeta, Patch patch, PatchOptions patchOptions, PersistentVolume persistentVolume, PersistentVolumeClaim persistentVolumeClaim, PersistentVolumeClaimList persistentVolumeClaimList, PersistentVolumeList persistentVolumeList, PodExecOptions podExecOptions, PodList podList, PodTemplateList podTemplateList, Quantity quantity, ReplicationControllerList replicationControllerList, ResourceQuota resourceQuota, ResourceQuotaList resourceQuotaList, RootPaths rootPaths, Secret secret, SecretList secretList, ServiceAccount serviceAccount, ServiceAccountList serviceAccountList, ServiceList serviceList, Status status, String time, Toleration toleration, TopologySelectorTerm topologySelectorTerm, TypeMeta typeMeta, UpdateOptions updateOptions, WatchEvent watchEvent) { super(); this.aPIGroup = aPIGroup; this.aPIGroupList = aPIGroupList; + this.aPIResource = aPIResource; + this.aPIResourceList = aPIResourceList; this.aPIService = aPIService; this.aPIServiceList = aPIServiceList; this.baseKubernetesList = baseKubernetesList; @@ -369,6 +379,26 @@ public void setAPIGroupList(APIGroupList aPIGroupList) { this.aPIGroupList = aPIGroupList; } + @JsonProperty("APIResource") + public APIResource getAPIResource() { + return aPIResource; + } + + @JsonProperty("APIResource") + public void setAPIResource(APIResource aPIResource) { + this.aPIResource = aPIResource; + } + + @JsonProperty("APIResourceList") + public APIResourceList getAPIResourceList() { + return aPIResourceList; + } + + @JsonProperty("APIResourceList") + public void setAPIResourceList(APIResourceList aPIResourceList) { + this.aPIResourceList = aPIResourceList; + } + @JsonProperty("APIService") public APIService getAPIService() { return aPIService; diff --git a/kubernetes-model-generator/kubernetes-model-core/src/main/resources/schema/kube-schema.json b/kubernetes-model-generator/kubernetes-model-core/src/main/resources/schema/kube-schema.json index cc78702c8a4..285a4478fe9 100644 --- a/kubernetes-model-generator/kubernetes-model-core/src/main/resources/schema/kube-schema.json +++ b/kubernetes-model-generator/kubernetes-model-core/src/main/resources/schema/kube-schema.json @@ -231,6 +231,87 @@ "io.fabric8.kubernetes.api.model.KubernetesResource" ] }, + "kubernetes_apimachinery_pkg_apis_APIResource": { + "type": "object", + "properties": { + "categories": { + "type": "array", + "javaOmitEmpty": true, + "items": { + "type": "string" + } + }, + "group": { + "type": "string" + }, + "kind": { + "type": "string" + }, + "name": { + "type": "string" + }, + "namespaced": { + "type": "boolean" + }, + "shortNames": { + "type": "array", + "javaOmitEmpty": true, + "items": { + "type": "string" + } + }, + "singularName": { + "type": "string" + }, + "storageVersionHash": { + "type": "string" + }, + "verbs": { + "type": "array", + "items": { + "type": "string" + } + }, + "version": { + "type": "string" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.APIResource", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource" + ] + }, + "kubernetes_apimachinery_pkg_apis_APIResourceList": { + "type": "object", + "properties": { + "apiVersion": { + "type": "string", + "default": "v1", + "required": true + }, + "groupVersion": { + "type": "string" + }, + "kind": { + "type": "string", + "default": "APIResourceList", + "required": true + }, + "resources": { + "type": "array", + "items": { + "$ref": "#/definitions/kubernetes_apimachinery_pkg_apis_APIResource", + "existingJavaType": "io.fabric8.kubernetes.api.model.APIResource" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.APIResourceList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource" + ] + }, "kubernetes_apimachinery_pkg_apis_Condition": { "type": "object", "properties": { @@ -7392,6 +7473,14 @@ "$ref": "#/definitions/kubernetes_apimachinery_pkg_apis_APIGroupList", "existingJavaType": "io.fabric8.kubernetes.api.model.APIGroupList" }, + "APIResource": { + "$ref": "#/definitions/kubernetes_apimachinery_pkg_apis_APIResource", + "existingJavaType": "io.fabric8.kubernetes.api.model.APIResource" + }, + "APIResourceList": { + "$ref": "#/definitions/kubernetes_apimachinery_pkg_apis_APIResourceList", + "existingJavaType": "io.fabric8.kubernetes.api.model.APIResourceList" + }, "APIService": { "$ref": "#/definitions/kubernetes_aggregator_APIService", "existingJavaType": "io.fabric8.kubernetes.api.model.APIService" diff --git a/kubernetes-model-generator/kubernetes-model-core/src/main/resources/schema/validation-schema.json b/kubernetes-model-generator/kubernetes-model-core/src/main/resources/schema/validation-schema.json index 51a77f20c9b..c3a2a7fdbe8 100644 --- a/kubernetes-model-generator/kubernetes-model-core/src/main/resources/schema/validation-schema.json +++ b/kubernetes-model-generator/kubernetes-model-core/src/main/resources/schema/validation-schema.json @@ -231,6 +231,87 @@ "io.fabric8.kubernetes.api.model.KubernetesResource" ] }, + "kubernetes_apimachinery_pkg_apis_APIResource": { + "type": "object", + "properties": { + "categories": { + "type": "array", + "javaOmitEmpty": true, + "items": { + "type": "string" + } + }, + "group": { + "type": "string" + }, + "kind": { + "type": "string" + }, + "name": { + "type": "string" + }, + "namespaced": { + "type": "boolean" + }, + "shortNames": { + "type": "array", + "javaOmitEmpty": true, + "items": { + "type": "string" + } + }, + "singularName": { + "type": "string" + }, + "storageVersionHash": { + "type": "string" + }, + "verbs": { + "type": "array", + "items": { + "type": "string" + } + }, + "version": { + "type": "string" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.APIResource", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource" + ] + }, + "kubernetes_apimachinery_pkg_apis_APIResourceList": { + "type": "object", + "properties": { + "apiVersion": { + "type": "string", + "default": "v1", + "required": true + }, + "groupVersion": { + "type": "string" + }, + "kind": { + "type": "string", + "default": "APIResourceList", + "required": true + }, + "resources": { + "type": "array", + "items": { + "$ref": "#/definitions/kubernetes_apimachinery_pkg_apis_APIResource", + "existingJavaType": "io.fabric8.kubernetes.api.model.APIResource" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.APIResourceList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource" + ] + }, "kubernetes_apimachinery_pkg_apis_Condition": { "type": "object", "properties": { @@ -7392,6 +7473,14 @@ "$ref": "#/definitions/kubernetes_apimachinery_pkg_apis_APIGroupList", "existingJavaType": "io.fabric8.kubernetes.api.model.APIGroupList" }, + "APIResource": { + "$ref": "#/definitions/kubernetes_apimachinery_pkg_apis_APIResource", + "existingJavaType": "io.fabric8.kubernetes.api.model.APIResource" + }, + "APIResourceList": { + "$ref": "#/definitions/kubernetes_apimachinery_pkg_apis_APIResourceList", + "existingJavaType": "io.fabric8.kubernetes.api.model.APIResourceList" + }, "APIService": { "$ref": "#/definitions/kubernetes_aggregator_APIService", "existingJavaType": "io.fabric8.kubernetes.api.model.APIService" @@ -7707,6 +7796,77 @@ }, "additionalProperties": true }, + "apiresource": { + "properties": { + "categories": { + "type": "array", + "javaOmitEmpty": true, + "items": { + "type": "string" + } + }, + "group": { + "type": "string" + }, + "kind": { + "type": "string" + }, + "name": { + "type": "string" + }, + "namespaced": { + "type": "boolean" + }, + "shortNames": { + "type": "array", + "javaOmitEmpty": true, + "items": { + "type": "string" + } + }, + "singularName": { + "type": "string" + }, + "storageVersionHash": { + "type": "string" + }, + "verbs": { + "type": "array", + "items": { + "type": "string" + } + }, + "version": { + "type": "string" + } + }, + "additionalProperties": true + }, + "apiresourcelist": { + "properties": { + "apiVersion": { + "type": "string", + "default": "v1", + "required": true + }, + "groupVersion": { + "type": "string" + }, + "kind": { + "type": "string", + "default": "APIResourceList", + "required": true + }, + "resources": { + "type": "array", + "items": { + "$ref": "#/definitions/kubernetes_apimachinery_pkg_apis_APIResource", + "existingJavaType": "io.fabric8.kubernetes.api.model.APIResource" + } + } + }, + "additionalProperties": true + }, "apiservice": { "properties": { "apiVersion": { diff --git a/openshift-client/src/main/java/io/fabric8/openshift/client/DefaultOpenShiftClient.java b/openshift-client/src/main/java/io/fabric8/openshift/client/DefaultOpenShiftClient.java index 82359ac0a65..e728b60c15d 100644 --- a/openshift-client/src/main/java/io/fabric8/openshift/client/DefaultOpenShiftClient.java +++ b/openshift-client/src/main/java/io/fabric8/openshift/client/DefaultOpenShiftClient.java @@ -37,7 +37,6 @@ import io.fabric8.kubernetes.client.dsl.MixedOperation; import io.fabric8.kubernetes.client.dsl.Nameable; import io.fabric8.kubernetes.client.dsl.NamespaceListVisitFromServerGetDeleteRecreateWaitApplicable; -import io.fabric8.kubernetes.client.dsl.NamespaceVisitFromServerGetWatchDeleteRecreateWaitApplicable; import io.fabric8.kubernetes.client.dsl.Namespaceable; import io.fabric8.kubernetes.client.dsl.NamespacedInOutCreateable; import io.fabric8.kubernetes.client.dsl.NonNamespaceOperation; @@ -47,8 +46,7 @@ import io.fabric8.kubernetes.client.dsl.base.HasMetadataOperation; import io.fabric8.kubernetes.client.dsl.internal.core.v1.ComponentStatusOperationsImpl; import io.fabric8.kubernetes.client.extended.leaderelection.LeaderElectorBuilder; -import io.fabric8.kubernetes.client.utils.BackwardsCompatibilityInterceptor; -import io.fabric8.kubernetes.client.utils.ImpersonatorInterceptor; +import io.fabric8.kubernetes.client.utils.HttpClientUtils; import io.fabric8.kubernetes.client.utils.Serialization; import io.fabric8.openshift.api.model.BrokerTemplateInstance; import io.fabric8.openshift.api.model.BrokerTemplateInstanceList; @@ -174,17 +172,15 @@ import io.fabric8.openshift.client.dsl.internal.user.UserOperationsImpl; import io.fabric8.openshift.client.internal.OpenShiftClusterOperationsImpl; import io.fabric8.openshift.client.internal.OpenShiftNamespaceVisitFromServerGetWatchDeleteRecreateWaitApplicableListImpl; -import io.fabric8.openshift.client.internal.OpenShiftOAuthInterceptor; -import okhttp3.Authenticator; import okhttp3.OkHttpClient; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; /** * Class for Default Openshift Client implementing KubernetesClient interface. @@ -192,7 +188,7 @@ */ public class DefaultOpenShiftClient extends BaseKubernetesClient implements NamespacedOpenShiftClient { - private static final Map API_GROUPS_ENABLED_PER_URL = new HashMap<>(); + private static final Map API_GROUPS_ENABLED_PER_URL = new ConcurrentHashMap<>(); public static final String AUTHORIZATION_OPENSHIFT_IO = "authorization.openshift.io"; public static final String V1_APIVERSION = "v1"; @@ -211,19 +207,12 @@ public DefaultOpenShiftClient(final Config config) { } public DefaultOpenShiftClient(final OpenShiftConfig config) { - super(configWithApiGroupsEnabled(clientWithOpenShiftOAuthInterceptor(config), config)); - try { - this.httpClient = clientWithOpenShiftOAuthInterceptor(this.httpClient, config); - this.openShiftUrl = new URL(config.getOpenShiftUrl()); - } catch (MalformedURLException e) { - throw new KubernetesClientException("Could not create client", e); - } + this(HttpClientUtils.createHttpClient(config), config); } public DefaultOpenShiftClient(OkHttpClient httpClient, OpenShiftConfig config) { super(httpClient, configWithApiGroupsEnabled(httpClient, config)); try { - this.httpClient = clientWithOpenShiftOAuthInterceptor(httpClient, getConfiguration()); this.openShiftUrl = new URL(config.getOpenShiftUrl()); } catch (MalformedURLException e) { throw new KubernetesClientException("Could not create client", e); @@ -241,9 +230,9 @@ private static OpenShiftConfig configWithApiGroupsEnabled(OkHttpClient httpClien return config.withOpenshiftApiGroupsEnabled(false); } - Boolean enabled = OpenshiftAdapterSupport.isOpenShiftAPIGroups(httpClient, url); + boolean enabled = OpenshiftAdapterSupport.isOpenShift(httpClient, config); API_GROUPS_ENABLED_PER_URL.put(url, enabled); - return config.withOpenshiftApiGroupsEnabled(enabled); + return config.withOpenshiftApiGroupsEnabled(enabled); } public static DefaultOpenShiftClient fromConfig(String config) { @@ -254,22 +243,6 @@ public static DefaultOpenShiftClient fromConfig(InputStream is) { return new DefaultOpenShiftClient(Serialization.unmarshal(is, OpenShiftConfig.class)); } - private static OkHttpClient clientWithOpenShiftOAuthInterceptor(Config config) { - return clientWithOpenShiftOAuthInterceptor(null, config); - } - - static OkHttpClient clientWithOpenShiftOAuthInterceptor(OkHttpClient httpClient, Config config) { - OkHttpClient.Builder builder = httpClient != null ? - httpClient.newBuilder().authenticator(Authenticator.NONE) : - new OkHttpClient.Builder().authenticator(Authenticator.NONE); - - builder.interceptors().clear(); - return builder.addInterceptor(new OpenShiftOAuthInterceptor(httpClient, OpenShiftConfig.wrap(config))) - .addInterceptor(new ImpersonatorInterceptor(config)) - .addInterceptor(new BackwardsCompatibilityInterceptor()) - .build(); - } - @Override public URL getOpenshiftUrl() { return openShiftUrl; diff --git a/openshift-client/src/main/java/io/fabric8/openshift/client/NamespacedOpenShiftExtensionAdapter.java b/openshift-client/src/main/java/io/fabric8/openshift/client/NamespacedOpenShiftExtensionAdapter.java index d402d6a4691..857105ee377 100644 --- a/openshift-client/src/main/java/io/fabric8/openshift/client/NamespacedOpenShiftExtensionAdapter.java +++ b/openshift-client/src/main/java/io/fabric8/openshift/client/NamespacedOpenShiftExtensionAdapter.java @@ -16,8 +16,6 @@ package io.fabric8.openshift.client; -import okhttp3.OkHttpClient; -import io.fabric8.kubernetes.client.Client; import io.fabric8.kubernetes.client.ExtensionAdapter; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Service; @@ -32,11 +30,4 @@ public Class getExtensionType() { return NamespacedOpenShiftClient.class; } - @Override - public NamespacedOpenShiftClient adapt(Client client) { - if (!isAdaptable(client)) { - throw new OpenShiftNotAvailableException("OpenShift is not available. Root paths at: " + client.getMasterUrl() + " do not include /oapi or the new /apis/*.openshift.io APIs."); - } - return new DefaultOpenShiftClient(client.adapt(OkHttpClient.class), OpenShiftConfig.wrap(client.getConfiguration())); - } } diff --git a/openshift-client/src/main/java/io/fabric8/openshift/client/OpenShiftConfig.java b/openshift-client/src/main/java/io/fabric8/openshift/client/OpenShiftConfig.java index cd6d4d5aacb..37633433c84 100644 --- a/openshift-client/src/main/java/io/fabric8/openshift/client/OpenShiftConfig.java +++ b/openshift-client/src/main/java/io/fabric8/openshift/client/OpenShiftConfig.java @@ -26,11 +26,16 @@ import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.OAuthTokenProvider; import io.fabric8.kubernetes.client.internal.readiness.Readiness; +import io.fabric8.kubernetes.client.utils.BackwardsCompatibilityInterceptor; +import io.fabric8.kubernetes.client.utils.ImpersonatorInterceptor; import io.fabric8.kubernetes.client.utils.URLUtils; import io.fabric8.kubernetes.client.utils.Utils; +import io.fabric8.openshift.client.internal.OpenShiftOAuthInterceptor; import io.fabric8.openshift.client.internal.readiness.OpenShiftReadiness; import io.sundr.builder.annotations.Buildable; import io.sundr.builder.annotations.BuildableReference; +import okhttp3.Authenticator; +import okhttp3.OkHttpClient; import okhttp3.TlsVersion; @JsonInclude(JsonInclude.Include.NON_NULL) @@ -196,4 +201,18 @@ public void setOpenshiftApiGroupsEnabled(boolean openshiftApiGroupsEnabled) { public Readiness getReadiness() { return OpenShiftReadiness.getInstance(); } + + @Override + public OkHttpClient adaptClient(OkHttpClient httpClient) { + OkHttpClient.Builder builder = httpClient != null ? + httpClient.newBuilder().authenticator(Authenticator.NONE) : + new OkHttpClient.Builder().authenticator(Authenticator.NONE); + + builder.interceptors().clear(); + return builder.addInterceptor(new OpenShiftOAuthInterceptor(httpClient, this)) + .addInterceptor(new ImpersonatorInterceptor(this)) + .addInterceptor(new BackwardsCompatibilityInterceptor()) + .build(); + } + } diff --git a/openshift-client/src/main/java/io/fabric8/openshift/client/OpenShiftExtensionAdapter.java b/openshift-client/src/main/java/io/fabric8/openshift/client/OpenShiftExtensionAdapter.java index cde67221767..d0eb25a6313 100644 --- a/openshift-client/src/main/java/io/fabric8/openshift/client/OpenShiftExtensionAdapter.java +++ b/openshift-client/src/main/java/io/fabric8/openshift/client/OpenShiftExtensionAdapter.java @@ -16,7 +16,6 @@ package io.fabric8.openshift.client; -import io.fabric8.kubernetes.client.Client; import io.fabric8.kubernetes.client.ExtensionAdapter; import io.fabric8.openshift.api.model.Build; import io.fabric8.openshift.api.model.BuildConfig; @@ -50,7 +49,6 @@ import io.fabric8.openshift.client.dsl.internal.security.SecurityContextConstraintsOperationsImpl; import io.fabric8.openshift.client.dsl.internal.user.GroupOperationsImpl; import io.fabric8.openshift.client.dsl.internal.user.UserOperationsImpl; -import okhttp3.OkHttpClient; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Service; @@ -83,12 +81,4 @@ public Class getExtensionType() { return OpenShiftClient.class; } - - @Override - public OpenShiftClient adapt(Client client) { - if (!isAdaptable(client)) { - throw new OpenShiftNotAvailableException("OpenShift is not available. Root paths at: " + client.getMasterUrl() + " do not include oapi."); - } - return new DefaultOpenShiftClient(client.adapt(OkHttpClient.class), OpenShiftConfig.wrap(client.getConfiguration())); - } } diff --git a/openshift-client/src/main/java/io/fabric8/openshift/client/OpenshiftAdapterSupport.java b/openshift-client/src/main/java/io/fabric8/openshift/client/OpenshiftAdapterSupport.java index f8627b8e227..ae31a0ad312 100644 --- a/openshift-client/src/main/java/io/fabric8/openshift/client/OpenshiftAdapterSupport.java +++ b/openshift-client/src/main/java/io/fabric8/openshift/client/OpenshiftAdapterSupport.java @@ -16,36 +16,25 @@ package io.fabric8.openshift.client; -import io.fabric8.kubernetes.api.model.APIGroup; -import io.fabric8.kubernetes.api.model.APIGroupList; import io.fabric8.kubernetes.client.BaseClient; import io.fabric8.kubernetes.client.Client; import io.fabric8.kubernetes.client.KubernetesClientException; -import io.fabric8.kubernetes.client.utils.Serialization; -import io.fabric8.kubernetes.client.utils.URLUtils; import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; import java.net.URI; -import java.net.URL; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import static io.fabric8.openshift.client.DefaultOpenShiftClient.clientWithOpenShiftOAuthInterceptor; public class OpenshiftAdapterSupport { - static final ConcurrentMap IS_OPENSHIFT = new ConcurrentHashMap<>(); - static final ConcurrentMap USES_OPENSHIFT_APIGROUPS = new ConcurrentHashMap<>(); - public static final String APIS = "/apis"; - public Boolean isAdaptable(Client client) { - OpenShiftConfig config = new OpenShiftConfig(client.getConfiguration()); - if (!hasCustomOpenShiftUrl(config) && !isOpenShift(client, config)) { - return false; + OpenShiftConfig config = OpenShiftConfig.wrap(client.getConfiguration()); + return hasCustomOpenShiftUrl(config) || isOpenShift(client.adapt(OkHttpClient.class), config); + } + + public DefaultOpenShiftClient adapt(Client client) { + if (!isAdaptable(client)) { + throw new OpenShiftNotAvailableException("OpenShift is not available. Root paths at: " + client.getMasterUrl() + " do not include oapi."); } - return true; + return new DefaultOpenShiftClient(client.adapt(OkHttpClient.class), OpenShiftConfig.wrap(client.getConfiguration())); } /** @@ -54,63 +43,11 @@ public Boolean isAdaptable(Client client) { * @param config {@link OpenShiftConfig} OpenShift Configuration * @return True if oapi is found in the root paths. */ - static boolean isOpenShift(Client client, OpenShiftConfig config) { - return isOpenShiftAPIGroups(client, config); + public static boolean isOpenShift(OkHttpClient client, OpenShiftConfig config) { + return new BaseClient(client, config) {}.getApiGroups() + .getGroups().stream().anyMatch(g -> g.getName().endsWith("openshift.io")); } - /** - * Check if OpenShift API Groups are available - * @param client The client. - * @param config {@link OpenShiftConfig} OpenShift config - * @return True if the new /apis/*.openshift.io/ APIs are found in the root paths. - */ - static boolean isOpenShiftAPIGroups(Client client, OpenShiftConfig config) { - URL masterUrl = client.getMasterUrl(); - - OkHttpClient httpClient = clientWithOpenShiftOAuthInterceptor(((BaseClient)client).getHttpClient(), config); - try { - Request.Builder requestBuilder = new Request.Builder() - .get() - .url(URLUtils.join(masterUrl.toString(), APIS)); - Response response = httpClient.newCall(requestBuilder.build()).execute(); - APIGroupList apiGroupList = Serialization.unmarshal(response.body().string(), APIGroupList.class); - - for (APIGroup apiGroup : apiGroupList.getGroups()) { - if (apiGroup.getName().endsWith("openshift.io")) { - return true; - } - } - } catch(Exception e) { - KubernetesClientException.launderThrowable(e); - } - return false; - } - - /** - * Check if OpenShift API Groups are available - * @param httpClient The httpClient. - * @param masterUrl The master url. - * @return True if the new /apis/*.openshift.io/ APIs are found in the root paths. - */ - static boolean isOpenShiftAPIGroups(OkHttpClient httpClient, String masterUrl) { - try { - Request.Builder requestBuilder = new Request.Builder() - .get() - .url(URLUtils.join(masterUrl, APIS)); - Response response = httpClient.newCall(requestBuilder.build()).execute(); - APIGroupList apiGroupList = Serialization.unmarshal(response.body().string(), APIGroupList.class); - - for (APIGroup apiGroup : apiGroupList.getGroups()) { - if (apiGroup.getName().endsWith("openshift.io")) { - return true; - } - } - } catch(Exception e) { - KubernetesClientException.launderThrowable(e); - } - return false; - } - /** * Checks if a custom URL for OpenShift has been used. * @param config The openshift configuration.