From 5a6f8399d6188042a92748c10bb985180b9a4d0a Mon Sep 17 00:00:00 2001 From: Steve Hawkins Date: Wed, 27 Apr 2022 15:39:33 -0400 Subject: [PATCH] fix #3923: minimizing the need for a mapping provider by using jandex --- .../CamelKV1ResourceMappingProvider.java | 17 -- ...CamelKV1alpha1ResourceMappingProvider.java | 13 - .../ChaosMeshResourceMappingProvider.java | 24 -- .../model/KnativeResourceMappingProvider.java | 38 --- ...ServiceCatalogResourceMappingProvider.java | 20 -- ...TektonTriggersResourceMappingProvider.java | 18 -- ...TektonV1alpha1ResourceMappingProvider.java | 19 -- .../TektonV1beta1ResourceMappingProvider.java | 18 +- ...VolumeSnapshotResourceMappingProvider.java | 15 - .../kubernetes-model-core/pom.xml | 4 + .../KubernetesResourceMappingProvider.java | 15 +- .../kubernetes/api/model/KubernetesList.java | 11 +- .../InternalResourceMappingProvider.java | 38 --- .../internal/KubernetesDeserializer.java | 259 ++++++++---------- ...etes.api.KubernetesResourceMappingProvider | 1 - .../internal/KubernetesDeserializerTest.java | 25 +- .../features/src/main/resources/feature.xml | 1 + pom.xml | 5 + 18 files changed, 159 insertions(+), 382 deletions(-) delete mode 100644 kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/internal/InternalResourceMappingProvider.java delete mode 100644 kubernetes-model-generator/kubernetes-model-core/src/main/resources/META-INF/services/io.fabric8.kubernetes.api.KubernetesResourceMappingProvider diff --git a/extensions/camel-k/model-v1/src/main/java/io/fabric8/camelk/CamelKV1ResourceMappingProvider.java b/extensions/camel-k/model-v1/src/main/java/io/fabric8/camelk/CamelKV1ResourceMappingProvider.java index af639f4c7ff..81e8d18e9af 100644 --- a/extensions/camel-k/model-v1/src/main/java/io/fabric8/camelk/CamelKV1ResourceMappingProvider.java +++ b/extensions/camel-k/model-v1/src/main/java/io/fabric8/camelk/CamelKV1ResourceMappingProvider.java @@ -16,24 +16,7 @@ package io.fabric8.camelk; import io.fabric8.kubernetes.api.KubernetesResourceMappingProvider; -import io.fabric8.kubernetes.api.model.KubernetesResource; - -import java.util.HashMap; -import java.util.Map; public class CamelKV1ResourceMappingProvider implements KubernetesResourceMappingProvider { - public final Map> mappings = new HashMap<>(); - - public CamelKV1ResourceMappingProvider() { - mappings.put("camel.apahce.org/v1#Build", io.fabric8.camelk.v1.Build.class); - mappings.put("camel.apahce.org/v1#CamelCatalog", io.fabric8.camelk.v1.CamelCatalog.class); - mappings.put("camel.apahce.org/v1#Integration", io.fabric8.camelk.v1.Integration.class); - mappings.put("camel.apahce.org/v1#IntegrationKit", io.fabric8.camelk.v1.IntegrationKit.class); - mappings.put("camel.apahce.org/v1#IntegrationPlatform", io.fabric8.camelk.v1.IntegrationPlatform.class); - } - - public Map> getMappings() { - return mappings; - } } diff --git a/extensions/camel-k/model-v1alpha1/src/main/java/io/fabric8/camelk/CamelKV1alpha1ResourceMappingProvider.java b/extensions/camel-k/model-v1alpha1/src/main/java/io/fabric8/camelk/CamelKV1alpha1ResourceMappingProvider.java index 20aede72305..36ddfc1da8c 100644 --- a/extensions/camel-k/model-v1alpha1/src/main/java/io/fabric8/camelk/CamelKV1alpha1ResourceMappingProvider.java +++ b/extensions/camel-k/model-v1alpha1/src/main/java/io/fabric8/camelk/CamelKV1alpha1ResourceMappingProvider.java @@ -16,20 +16,7 @@ package io.fabric8.camelk; import io.fabric8.kubernetes.api.KubernetesResourceMappingProvider; -import io.fabric8.kubernetes.api.model.KubernetesResource; - -import java.util.HashMap; -import java.util.Map; public class CamelKV1alpha1ResourceMappingProvider implements KubernetesResourceMappingProvider { - public final Map> mappings = new HashMap<>(); - - public CamelKV1alpha1ResourceMappingProvider() { - mappings.put("camel.apache.org/v1alpha1#Kamelet", io.fabric8.camelk.v1alpha1.Kamelet.class); - } - - public Map> getMappings() { - return mappings; - } } diff --git a/extensions/chaosmesh/model/src/main/java/io/fabric8/chaosmesh/api/model/ChaosMeshResourceMappingProvider.java b/extensions/chaosmesh/model/src/main/java/io/fabric8/chaosmesh/api/model/ChaosMeshResourceMappingProvider.java index 833169b5fde..7015413b85b 100644 --- a/extensions/chaosmesh/model/src/main/java/io/fabric8/chaosmesh/api/model/ChaosMeshResourceMappingProvider.java +++ b/extensions/chaosmesh/model/src/main/java/io/fabric8/chaosmesh/api/model/ChaosMeshResourceMappingProvider.java @@ -16,31 +16,7 @@ package io.fabric8.chaosmesh.api.model; import io.fabric8.kubernetes.api.KubernetesResourceMappingProvider; -import io.fabric8.kubernetes.api.model.KubernetesResource; - -import java.util.HashMap; -import java.util.Map; public class ChaosMeshResourceMappingProvider implements KubernetesResourceMappingProvider { - public final Map> mappings = new HashMap<>(); - - public ChaosMeshResourceMappingProvider() { - mappings.put("chaos-mesh.org/v1alpha1#IoChaos", io.fabric8.chaosmesh.v1alpha1.IoChaos.class); - mappings.put("chaos-mesh.org/v1alpha1#KernelChaos", io.fabric8.chaosmesh.v1alpha1.KernelChaos.class); - mappings.put("chaos-mesh.org/v1alpha1#NetworkChaos", io.fabric8.chaosmesh.v1alpha1.NetworkChaos.class); - mappings.put("chaos-mesh.org/v1alpha1#PodChaos", io.fabric8.chaosmesh.v1alpha1.PodChaos.class); - mappings.put("chaos-mesh.org/v1alpha1#PodIoChaos", io.fabric8.chaosmesh.v1alpha1.PodIoChaos.class); - mappings.put("chaos-mesh.org/v1alpha1#PodNetworkChaos", io.fabric8.chaosmesh.v1alpha1.PodNetworkChaos.class); - mappings.put("chaos-mesh.org/v1alpha1#StressChaos", io.fabric8.chaosmesh.v1alpha1.StressChaos.class); - mappings.put("chaos-mesh.org/v1alpha1#TimeChaos", io.fabric8.chaosmesh.v1alpha1.TimeChaos.class); - mappings.put("chaos-mesh.org/v1alpha1#JVMChaos", io.fabric8.chaosmesh.v1alpha1.JVMChaos.class); - mappings.put("chaos-mesh.org/v1alpha1#HTTPChaos", io.fabric8.chaosmesh.v1alpha1.HTTPChaos.class); - mappings.put("chaos-mesh.org/v1alpha1#DNSChaos", io.fabric8.chaosmesh.v1alpha1.DNSChaos.class); - mappings.put("chaos-mesh.org/v1alpha1#AwsChaos", io.fabric8.chaosmesh.v1alpha1.AwsChaos.class); - } - - public Map> getMappings() { - return mappings; - } } diff --git a/extensions/knative/model/src/main/java/io/fabric8/knative/api/model/KnativeResourceMappingProvider.java b/extensions/knative/model/src/main/java/io/fabric8/knative/api/model/KnativeResourceMappingProvider.java index 11dc6302df8..3950bb31fe5 100644 --- a/extensions/knative/model/src/main/java/io/fabric8/knative/api/model/KnativeResourceMappingProvider.java +++ b/extensions/knative/model/src/main/java/io/fabric8/knative/api/model/KnativeResourceMappingProvider.java @@ -16,45 +16,7 @@ package io.fabric8.knative.api.model; import io.fabric8.kubernetes.api.KubernetesResourceMappingProvider; -import io.fabric8.kubernetes.api.model.KubernetesResource; -import java.util.HashMap; -import java.util.Map; public class KnativeResourceMappingProvider implements KubernetesResourceMappingProvider { - public final Map> mappings = new HashMap<>(); - - public KnativeResourceMappingProvider() { - mappings.put("serving.knative.dev/v1#Configuration", io.fabric8.knative.serving.v1.Configuration.class); - mappings.put("serving.knative.dev/v1#Revision", io.fabric8.knative.serving.v1.Revision.class); - mappings.put("serving.knative.dev/v1#Service", io.fabric8.knative.serving.v1.Service.class); - mappings.put("serving.knative.dev/v1#Route", io.fabric8.knative.serving.v1.Route.class); - - mappings.put("eventing.knative.dev/v1#Broker", io.fabric8.knative.eventing.v1.Broker.class); - mappings.put("eventing.knative.dev/v1#Channel", io.fabric8.knative.messaging.v1.Channel.class); - mappings.put("eventing.knative.dev/v1beta1#EventType", io.fabric8.knative.eventing.v1beta1.EventType.class); - mappings.put("eventing.knative.dev/v1#Trigger", io.fabric8.knative.eventing.v1.Trigger.class); - mappings.put("eventing.knative.dev/v1#Subscription", io.fabric8.knative.messaging.v1.Subscription.class); - - mappings.put("messaging.knative.dev/v1#InMemoryChannel", io.fabric8.knative.messaging.v1.InMemoryChannel.class); - mappings.put("messaging.knative.dev/v1#Sequence", io.fabric8.knative.flows.v1.Sequence.class); - mappings.put("sources.knative.dev/v1#PingSource", io.fabric8.knative.sources.v1.PingSource.class); - mappings.put("sources.knative.dev/v1#ContainerSource", io.fabric8.knative.sources.v1.ContainerSource.class); - mappings.put("sources.knative.dev/v1#ApiServerSource", io.fabric8.knative.sources.v1.ApiServerSource.class); - mappings.put("sources.knative.dev/v1#SinkBinding", io.fabric8.knative.sources.v1.SinkBinding.class); - mappings.put("sources.knative.dev/v1alpha1#AwsSqsSource", io.fabric8.knative.eventing.contrib.awssqs.v1alpha1.AwsSqsSource.class); - mappings.put("sources.knative.dev/v1alpha1#CouchDbSource", io.fabric8.knative.eventing.contrib.couchdb.v1alpha1.CouchDbSource.class); - mappings.put("sources.knative.dev/v1alpha1#GitHubSource", io.fabric8.knative.eventing.contrib.github.v1alpha1.GitHubSource.class); - mappings.put("bindings.knative.dev/v1alpha1#GitHubBinding", io.fabric8.knative.eventing.contrib.github.v1alpha1.GitHubBinding.class); - mappings.put("sources.knative.dev/v1alpha1#GitLabSource", io.fabric8.knative.eventing.contrib.gitlab.v1alpha1.GitLabSource.class); - mappings.put("bindings.knative.dev/v1alpha1#GitLabBinding", io.fabric8.knative.eventing.contrib.gitlab.v1alpha1.GitLabBinding.class); - mappings.put("sources.knative.dev/v1alpha1#PrometheusSource", io.fabric8.knative.eventing.contrib.prometheus.v1alpha1.PrometheusSource.class); - mappings.put("sources.knative.dev/v1beta1#KafkaSource", io.fabric8.knative.eventing.contrib.kafka.v1beta1.KafkaSource.class); - mappings.put("messaging.knative.dev/v1beta1#KafkaChannel", io.fabric8.knative.eventing.contrib.kafka.v1beta1.KafkaChannel.class); - mappings.put("bindings.knative.dev/v1beta11#KafkaBinding", io.fabric8.knative.eventing.contrib.kafka.v1beta1.KafkaBinding.class); - } - - public Map> getMappings() { - return mappings; - } } diff --git a/extensions/service-catalog/model/src/main/java/io/fabric8/servicecatalog/api/model/ServiceCatalogResourceMappingProvider.java b/extensions/service-catalog/model/src/main/java/io/fabric8/servicecatalog/api/model/ServiceCatalogResourceMappingProvider.java index c331cb50961..634aefb3cf3 100644 --- a/extensions/service-catalog/model/src/main/java/io/fabric8/servicecatalog/api/model/ServiceCatalogResourceMappingProvider.java +++ b/extensions/service-catalog/model/src/main/java/io/fabric8/servicecatalog/api/model/ServiceCatalogResourceMappingProvider.java @@ -16,27 +16,7 @@ package io.fabric8.servicecatalog.api.model; import io.fabric8.kubernetes.api.KubernetesResourceMappingProvider; -import io.fabric8.kubernetes.api.model.KubernetesResource; - -import java.util.HashMap; -import java.util.Map; public class ServiceCatalogResourceMappingProvider implements KubernetesResourceMappingProvider { - public final Map> mappings = new HashMap<>(); - - public ServiceCatalogResourceMappingProvider() { - mappings.put("servicecatalog.k8s.io/v1beta1#ClusterServiceBroker", ClusterServiceBroker.class); - mappings.put("servicecatalog.k8s.io/v1beta1#ClusterServiceClass", ClusterServiceClass.class); - mappings.put("servicecatalog.k8s.io/v1beta1#ClusterServicePlan", ClusterServicePlan.class); - mappings.put("servicecatalog.k8s.io/v1beta1#ServiceBroker", ServiceBroker.class); - mappings.put("servicecatalog.k8s.io/v1beta1#ServiceBinding", ServiceBinding.class); - mappings.put("servicecatalog.k8s.io/v1beta1#ServiceInstance", ServiceInstance.class); - mappings.put("servicecatalog.k8s.io/v1beta1#ServiceClass", ServiceClass.class); - mappings.put("servicecatalog.k8s.io/v1beta1#ServicePlan", ServicePlan.class); - } - - public Map> getMappings() { - return mappings; - } } diff --git a/extensions/tekton/model-triggers/src/main/java/io/fabric8/tekton/TektonTriggersResourceMappingProvider.java b/extensions/tekton/model-triggers/src/main/java/io/fabric8/tekton/TektonTriggersResourceMappingProvider.java index a9cafda2d73..b02d4d54986 100644 --- a/extensions/tekton/model-triggers/src/main/java/io/fabric8/tekton/TektonTriggersResourceMappingProvider.java +++ b/extensions/tekton/model-triggers/src/main/java/io/fabric8/tekton/TektonTriggersResourceMappingProvider.java @@ -16,25 +16,7 @@ package io.fabric8.tekton; import io.fabric8.kubernetes.api.KubernetesResourceMappingProvider; -import io.fabric8.kubernetes.api.model.KubernetesResource; - -import java.util.HashMap; -import java.util.Map; public class TektonTriggersResourceMappingProvider implements KubernetesResourceMappingProvider { - public final Map> mappings = new HashMap<>(); - - public TektonTriggersResourceMappingProvider() { - mappings.put("triggers.tekton.dev/v1alpha1#TriggerTemplate", io.fabric8.tekton.triggers.v1alpha1.TriggerTemplate.class); - mappings.put("triggers.tekton.dev/v1alpha1#TriggerBinding", io.fabric8.tekton.triggers.v1alpha1.TriggerBinding.class); - mappings.put("triggers.tekton.dev/v1alpha1#EventListener", io.fabric8.tekton.triggers.v1alpha1.EventListener.class); - mappings.put("triggers.tekton.dev/v1alpha1#ClusterTriggerBinding", io.fabric8.tekton.triggers.v1alpha1.ClusterTriggerBinding.class); - mappings.put("triggers.tekton.dev/v1alpha1#Trigger", io.fabric8.tekton.triggers.v1alpha1.Trigger.class); - mappings.put("triggers.tekton.dev/v1alpha1#ClusterInterceptor", io.fabric8.tekton.triggers.v1alpha1.ClusterInterceptor.class); - } - - public Map> getMappings() { - return mappings; - } } diff --git a/extensions/tekton/model-v1alpha1/src/main/java/io/fabric8/tekton/TektonV1alpha1ResourceMappingProvider.java b/extensions/tekton/model-v1alpha1/src/main/java/io/fabric8/tekton/TektonV1alpha1ResourceMappingProvider.java index 4686f64d580..5f6a4353633 100644 --- a/extensions/tekton/model-v1alpha1/src/main/java/io/fabric8/tekton/TektonV1alpha1ResourceMappingProvider.java +++ b/extensions/tekton/model-v1alpha1/src/main/java/io/fabric8/tekton/TektonV1alpha1ResourceMappingProvider.java @@ -16,26 +16,7 @@ package io.fabric8.tekton; import io.fabric8.kubernetes.api.KubernetesResourceMappingProvider; -import io.fabric8.kubernetes.api.model.KubernetesResource; - -import java.util.HashMap; -import java.util.Map; public class TektonV1alpha1ResourceMappingProvider implements KubernetesResourceMappingProvider { - public final Map> mappings = new HashMap<>(); - - public TektonV1alpha1ResourceMappingProvider() { - mappings.put("tekton.dev/v1alpha1#Condition", io.fabric8.tekton.pipeline.v1alpha1.Condition.class); - mappings.put("tekton.dev/v1alpha1#Pipeline", io.fabric8.tekton.pipeline.v1alpha1.Pipeline.class); - mappings.put("tekton.dev/v1alpha1#PipelineRun", io.fabric8.tekton.pipeline.v1alpha1.PipelineRun.class); - mappings.put("tekton.dev/v1alpha1#Task", io.fabric8.tekton.pipeline.v1alpha1.Task.class); - mappings.put("tekton.dev/v1alpha1#TaskRun", io.fabric8.tekton.pipeline.v1alpha1.TaskRun.class); - mappings.put("tekton.dev/v1alpha1#ClusterTask", io.fabric8.tekton.pipeline.v1alpha1.ClusterTask.class); - mappings.put("tekton.dev/v1alpha1#PipelineResource", io.fabric8.tekton.resource.v1alpha1.PipelineResource.class); - } - - public Map> getMappings() { - return mappings; - } } diff --git a/extensions/tekton/model-v1beta1/src/main/java/io/fabric8/tekton/TektonV1beta1ResourceMappingProvider.java b/extensions/tekton/model-v1beta1/src/main/java/io/fabric8/tekton/TektonV1beta1ResourceMappingProvider.java index 708ed9c4bba..680871525a6 100644 --- a/extensions/tekton/model-v1beta1/src/main/java/io/fabric8/tekton/TektonV1beta1ResourceMappingProvider.java +++ b/extensions/tekton/model-v1beta1/src/main/java/io/fabric8/tekton/TektonV1beta1ResourceMappingProvider.java @@ -16,23 +16,7 @@ package io.fabric8.tekton; import io.fabric8.kubernetes.api.KubernetesResourceMappingProvider; -import io.fabric8.kubernetes.api.model.KubernetesResource; - -import java.util.HashMap; -import java.util.Map; public class TektonV1beta1ResourceMappingProvider implements KubernetesResourceMappingProvider { - public final Map> mappings = new HashMap<>(); - - public TektonV1beta1ResourceMappingProvider() { - mappings.put("tekton.dev/v1beta1#Pipeline", io.fabric8.tekton.pipeline.v1beta1.Pipeline.class); - mappings.put("tekton.dev/v1beta1#PipelineRun", io.fabric8.tekton.pipeline.v1beta1.PipelineRun.class); - mappings.put("tekton.dev/v1beta1#Task", io.fabric8.tekton.pipeline.v1beta1.Task.class); - mappings.put("tekton.dev/v1beta1#TaskRun", io.fabric8.tekton.pipeline.v1beta1.TaskRun.class); - mappings.put("tekton.dev/v1beta1#ClusterTask", io.fabric8.tekton.pipeline.v1beta1.ClusterTask.class); - } - - public Map> getMappings() { - return mappings; - }} +} \ No newline at end of file diff --git a/extensions/volumesnapshot/model/src/main/java/io/fabric8/volumesnapshot/api/model/VolumeSnapshotResourceMappingProvider.java b/extensions/volumesnapshot/model/src/main/java/io/fabric8/volumesnapshot/api/model/VolumeSnapshotResourceMappingProvider.java index 6d17878f2c8..92c4ef0588f 100644 --- a/extensions/volumesnapshot/model/src/main/java/io/fabric8/volumesnapshot/api/model/VolumeSnapshotResourceMappingProvider.java +++ b/extensions/volumesnapshot/model/src/main/java/io/fabric8/volumesnapshot/api/model/VolumeSnapshotResourceMappingProvider.java @@ -16,22 +16,7 @@ package io.fabric8.volumesnapshot.api.model; import io.fabric8.kubernetes.api.KubernetesResourceMappingProvider; -import io.fabric8.kubernetes.api.model.KubernetesResource; - -import java.util.HashMap; -import java.util.Map; public class VolumeSnapshotResourceMappingProvider implements KubernetesResourceMappingProvider { - public final Map> mappings = new HashMap<>(); - - public VolumeSnapshotResourceMappingProvider() { - mappings.put("snapshot.storage.k8s.io/v1#VolumeSnapshot", VolumeSnapshot.class); - mappings.put("snapshot.storage.k8s.io/v1#VolumeSnapshotClass", VolumeSnapshotClass.class); - mappings.put("snapshot.storage.k8s.io/v1#VolumeSnapshotContent", VolumeSnapshotContent.class); - } - - public Map> getMappings() { - return mappings; - } } diff --git a/kubernetes-model-generator/kubernetes-model-core/pom.xml b/kubernetes-model-generator/kubernetes-model-core/pom.xml index 70867f65fed..22cebccf67e 100644 --- a/kubernetes-model-generator/kubernetes-model-core/pom.xml +++ b/kubernetes-model-generator/kubernetes-model-core/pom.xml @@ -116,6 +116,10 @@ io.fabric8 kubernetes-model-common + + org.jboss + jandex + org.mockito mockito-core diff --git a/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/KubernetesResourceMappingProvider.java b/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/KubernetesResourceMappingProvider.java index 3c49354e90a..0b04c725a35 100644 --- a/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/KubernetesResourceMappingProvider.java +++ b/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/KubernetesResourceMappingProvider.java @@ -17,9 +17,20 @@ import io.fabric8.kubernetes.api.model.KubernetesResource; -import java.util.Map; +import java.util.function.Consumer; +/** + * Only required when running in a runtime, such as OSGI, that does + * not provide resource access outside of a module's own classloader. + */ public interface KubernetesResourceMappingProvider { - Map> getMappings(); + /** + * Implement this method if you are not providng a jandex index. + * + * @param classConsumer + */ + default void provideClasses(Consumer> classConsumer) { + + } } diff --git a/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/KubernetesList.java b/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/KubernetesList.java index e5429024308..d76e05fb32d 100644 --- a/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/KubernetesList.java +++ b/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/KubernetesList.java @@ -19,12 +19,12 @@ import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import io.sundr.builder.annotations.Buildable; - import io.fabric8.kubernetes.model.annotation.Generated; +import io.fabric8.kubernetes.model.annotation.Group; +import io.fabric8.kubernetes.model.annotation.Kind; +import io.fabric8.kubernetes.model.annotation.Version; +import io.sundr.builder.annotations.Buildable; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; @@ -40,6 +40,9 @@ "metadata", "items", }) +@Version("v1") +@Group("") +@Kind("List") @JsonDeserialize(using = JsonDeserializer.None.class) @Buildable(editableEnabled = false, validationEnabled = false, generateBuilderPackage=true, builderPackage = "io.fabric8.kubernetes.api.builder") public class KubernetesList extends BaseKubernetesList implements KubernetesResource { diff --git a/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/internal/InternalResourceMappingProvider.java b/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/internal/InternalResourceMappingProvider.java deleted file mode 100644 index af105e5e8f4..00000000000 --- a/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/internal/InternalResourceMappingProvider.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * 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.internal; - -import io.fabric8.kubernetes.api.KubernetesResourceMappingProvider; -import io.fabric8.kubernetes.api.model.KubernetesList; -import io.fabric8.kubernetes.api.model.KubernetesResource; - -import java.util.HashMap; -import java.util.Map; - -public class InternalResourceMappingProvider implements KubernetesResourceMappingProvider { - - private final Map> mappings = new HashMap<>(); - - public InternalResourceMappingProvider() { - mappings.put("List", KubernetesList.class); - mappings.put("v1#List", KubernetesList.class); - } - - @Override - public Map> getMappings() { - return mappings; - } -} diff --git a/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/internal/KubernetesDeserializer.java b/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/internal/KubernetesDeserializer.java index 9034cbc9187..30ba7ac88d0 100644 --- a/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/internal/KubernetesDeserializer.java +++ b/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/internal/KubernetesDeserializer.java @@ -27,9 +27,17 @@ import io.fabric8.kubernetes.model.annotation.Group; import io.fabric8.kubernetes.model.annotation.Version; import io.fabric8.kubernetes.model.util.Helper; +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.DotName; +import org.jboss.jandex.Index; +import org.jboss.jandex.IndexReader; import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.net.URLConnection; import java.util.ArrayList; +import java.util.Enumeration; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -37,6 +45,7 @@ import java.util.ServiceLoader; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentSkipListSet; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Stream; @@ -173,120 +182,77 @@ public static void registerProvider(KubernetesResourceMappingProvider provider) static class Mapping { - private static final String KEY_SEPARATOR = "#"; - - // n.b. Packages sorted in order of precedence, deserialization of resources with no - // specific version will default to first available Class in one of these packages: - private static final String[] PACKAGES = { - "io.fabric8.kubernetes.api.model.", - "io.fabric8.kubernetes.api.model.admission.v1.", - "io.fabric8.kubernetes.api.model.admission.v1beta1.", - "io.fabric8.kubernetes.api.model.admissionregistration.v1.", - "io.fabric8.kubernetes.api.model.admissionregistration.v1beta1.", - "io.fabric8.kubernetes.api.model.authentication.", - "io.fabric8.kubernetes.api.model.authorization.v1.", - "io.fabric8.kubernetes.api.model.authorization.v1beta1.", - "io.fabric8.kubernetes.api.model.apiextensions.v1.", - "io.fabric8.kubernetes.api.model.apiextensions.v1beta1.", - "io.fabric8.kubernetes.api.model.apps.", - "io.fabric8.kubernetes.api.model.autoscaling.v1.", - "io.fabric8.kubernetes.api.model.autoscaling.", - "io.fabric8.kubernetes.api.model.autoscaling.v2beta1.", - "io.fabric8.kubernetes.api.model.autoscaling.v2beta2.", - "io.fabric8.kubernetes.api.model.batch.v1.", - "io.fabric8.kubernetes.api.model.batch.v1beta1.", - "io.fabric8.kubernetes.api.model.certificates.v1.", - "io.fabric8.kubernetes.api.model.certificates.v1beta1.", - "io.fabric8.kubernetes.api.model.coordination.v1.", - "io.fabric8.kubernetes.api.model.coordination.", - "io.fabric8.kubernetes.api.model.discovery.v1.", - "io.fabric8.kubernetes.api.model.events.v1.", - "io.fabric8.kubernetes.api.model.events.v1beta1.", - "io.fabric8.kubernetes.api.model.flowcontrol.v1beta1.", - "io.fabric8.kubernetes.api.model.discovery.v1beta1.", - "io.fabric8.kubernetes.api.model.metrics.v1beta1.", - "io.fabric8.kubernetes.api.model.networking.v1.", - "io.fabric8.kubernetes.api.model.networking.v1beta1.", - "io.fabric8.kubernetes.api.model.policy.v1.", - "io.fabric8.kubernetes.api.model.policy.v1beta1.", - "io.fabric8.kubernetes.api.model.rbac.", - "io.fabric8.kubernetes.api.model.storage.", - "io.fabric8.kubernetes.api.model.scheduling.v1.", - "io.fabric8.kubernetes.api.model.scheduling.v1beta1.", - "io.fabric8.kubernetes.api.model.storage.", - "io.fabric8.kubernetes.api.model.storage.v1beta1.", - "io.fabric8.kubernetes.api.model.node.v1alpha1.", - "io.fabric8.kubernetes.api.model.node.v1beta1.", - "io.fabric8.openshift.api.model.", - "io.fabric8.openshift.api.model.clusterautoscaling.v1.", - "io.fabric8.openshift.api.model.clusterautoscaling.v1beta1.", - "io.fabric8.openshift.api.model.runtime.", - "io.fabric8.openshift.api.model.console.v1.", - "io.fabric8.openshift.api.model.console.v1alpha1.", - "io.fabric8.openshift.api.model.hive.v1.", - "io.fabric8.openshift.api.model.installer.v1.", - "io.fabric8.openshift.api.model.monitoring.v1.", - "io.fabric8.openshift.api.model.machine.v1beta1.", - "io.fabric8.openshift.api.model.operator.", - "io.fabric8.openshift.api.model.operator.v1.", - "io.fabric8.openshift.api.model.operator.v1alpha1.", - "io.fabric8.openshift.api.model.imageregistry.v1.", - "io.fabric8.openshift.api.model.operatorhub.manifests.", - "io.fabric8.openshift.api.model.operatorhub.v1.", - "io.fabric8.openshift.api.model.operatorhub.v1alpha1.", - "io.fabric8.openshift.api.model.operatorhub.lifecyclemanager.v1.", - "io.fabric8.openshift.api.model.machineconfig.v1.", - "io.fabric8.openshift.api.model.tuned.v1.", - "io.fabric8.openshift.api.model.whereabouts.v1alpha1.", - "io.fabric8.openshift.api.model.storageversionmigrator.v1alpha1.", - "io.fabric8.openshift.api.model.miscellaneous.cloudcredential.v1.", - "io.fabric8.openshift.api.model.miscellaneous.cncf.cni.v1.", - "io.fabric8.openshift.api.model.miscellaneous.metal3.v1alpha1.", - "io.fabric8.openshift.api.model.miscellaneous.network.operator.v1.", - "io.fabric8.openshift.api.model.miscellaneous.imageregistry.operator.v1.", - "io.fabric8.kubernetes.api.model.extensions." + // n.b. classes from each of the internal packages that lack a mapping provider + // needed for osgi resource loading: + private static final String[] CLASSES = { + "io.fabric8.kubernetes.api.model.admission.v1.AdmissionRequest", + "io.fabric8.kubernetes.api.model.apiextensions.v1.ConversionRequest", + "io.fabric8.kubernetes.api.model.apps.Deployment", + "io.fabric8.kubernetes.api.model.autoscaling.v1.HorizontalPodAutoscaler", + "io.fabric8.kubernetes.api.model.batch.v1.CronJob", + "io.fabric8.kubernetes.api.model.certificates.v1.CertificateSigningRequest", + "io.fabric8.kubernetes.api.model.coordination.v1.Lease", + "io.fabric8.kubernetes.api.model.discovery.v1.Endpoint", + "io.fabric8.kubernetes.api.model.events.v1.Event", + "io.fabric8.kubernetes.api.model.extensions.DaemonSet", + "io.fabric8.kubernetes.api.model.flowcontrol.v1beta1.FlowSchema", + "io.fabric8.kubernetes.api.model.metrics.v1beta1.ContainerMetrics", + "io.fabric8.kubernetes.api.model.networking.v1.HTTPIngressPath", + "io.fabric8.kubernetes.api.model.policy.v1.Eviction", + "io.fabric8.kubernetes.api.model.rbac.ClusterRole", + "io.fabric8.kubernetes.api.model.scheduling.v1.PriorityClass", + "io.fabric8.kubernetes.api.model.storage.CSIDriver", + "io.fabric8.kubernetes.api.model.node.v1beta1.Overhead", + "io.fabric8.openshift.api.model.APIServer", + "io.fabric8.openshift.api.model.clusterautoscaling.v1.ClusterAutoscaler", + "io.fabric8.openshift.api.model.console.v1.ConsoleCLIDownload", + "io.fabric8.openshift.api.model.hive.v1.AWSAssociatedVPC", + "io.fabric8.openshift.api.model.installer.v1.BootstrapInPlace", + "io.fabric8.openshift.api.model.monitoring.v1.Alertmanager", + "io.fabric8.openshift.api.model.machine.v1beta1.Condition", + "io.fabric8.openshift.api.model.machineconfig.v1.ContainerRuntimeConfig", + "io.fabric8.openshift.api.model.miscellaneous.cloudcredential.v1.CredentialsRequest", + "io.fabric8.openshift.api.model.operator.v1.AccessLogging", + "io.fabric8.openshift.api.model.operatorhub.v1.Operator", + "io.fabric8.openshift.api.model.storageversionmigrator.v1alpha1.GroupResource", + "io.fabric8.openshift.api.model.tuned.v1.OperandConfig", + "io.fabric8.openshift.api.model.whereabouts.v1alpha1.IPAllocation", }; private Map> mappings = new ConcurrentHashMap<>(); - private Map> internalMappings = new ConcurrentHashMap<>(); + private Set urlsLoaded = new ConcurrentSkipListSet<>(); Mapping() { registerAllProviders(); + loadFromJandex(Mapping.class.getClassLoader()); + loadFromJandex(Thread.currentThread().getContextClassLoader()); + // when in osgi, the jandex won't be visible from the current classloader, so we + // need the specific classloaders + Stream.of(CLASSES).map(this::getClassloader).filter(Objects::nonNull).forEach(this::loadFromJandex); } - public Class getForKey(TypeKey key) { - if (key == null) { + private ClassLoader getClassloader(String className) { + try { + Class clazz = KubernetesDeserializer.class.getClassLoader().loadClass(className); + return clazz.getClassLoader(); + } catch (Exception t) { return null; } - // check for an exact match - Class clazz = mappings.get(key); - if (clazz != null) { - return clazz; - } - // check if it's a lazily-loaded internal type - List defaults = internalMappings.get(key.kind); - if (defaults == null) { - defaults = loadInternalTypes(key.kind); - clazz = mappings.get(key); // check again after load for an exact match - if (clazz != null) { - return clazz; - } - } + } - // version is required - if (key.version == null) { - return null; + void loadFromJandex(ClassLoader classLoader) { + try { + internalLoadFromJandex(classLoader); + } catch (IOException e) { + System.err.println(String.format("Could not process jandex files for classloader %s", classLoader)); } + } - // if there are internal types matching kind, look for matching groups and versions - for (TypeKey typeKey : defaults) { - if ((key.apiGroup == null || key.apiGroup.equals(typeKey.apiGroup)) - && key.version.equals(typeKey.version) - && (typeKey.apiGroup == null || typeKey.apiGroup.endsWith(".openshift.io"))) { - return mappings.get(typeKey); - } + public Class getForKey(TypeKey key) { + if (key == null) { + return null; } - return null; + return mappings.get(key); } public void registerKind(String apiVersion, String kind, Class clazz) { @@ -297,11 +263,8 @@ public void registerProvider(KubernetesResourceMappingProvider provider) { if (provider == null) { return; } - provider.getMappings().entrySet().stream() - //If the model is shaded (which is as part of kubernetes-client uberjar) this is going to cause conflicts. - //This is why we NEED TO filter out incompatible resources. - .filter(entry -> KubernetesResource.class.isAssignableFrom(entry.getValue())) - .forEach(e -> mappings.put(createKey(e.getKey()), e.getValue())); + provider.provideClasses(this::addMapping); + loadFromJandex(provider.getClass().getClassLoader()); } /** @@ -321,15 +284,6 @@ TypeKey createKey(String apiVersion, String kind) { } } - TypeKey createKey(String key) { - // null is not allowed - if (key.contains(KEY_SEPARATOR)) { - String[] parts = key.split(KEY_SEPARATOR, 2); - return createKey(parts[0], parts[1]); - } - return createKey(null, key); - } - private void registerAllProviders() { getAllMappingProviders().forEach(this::registerProvider); } @@ -348,43 +302,16 @@ Stream getAllMappingProviders() { .filter(distinctByClassName(KubernetesResourceMappingProvider::getClass)); } - private List loadInternalTypes(String kind) { - List ordering = new ArrayList<>(); - for (int i = 0; i < PACKAGES.length; i++) { - Class result = loadClassIfExists(PACKAGES[i] + kind); - if (result == null) { - continue; - } - TypeKey defaultKeyFromClass = getKeyFromClass(result); - mappings.put(defaultKeyFromClass, result); - ordering.add(defaultKeyFromClass); - } - - internalMappings.put(kind, ordering); - return ordering; - } - TypeKey getKeyFromClass(Class clazz) { String apiGroup = Helper.getAnnotationValue(clazz, Group.class); String apiVersion = Helper.getAnnotationValue(clazz, Version.class); + String kind = HasMetadata.getKind(clazz); if (apiGroup != null && !apiGroup.isEmpty() && apiVersion != null && !apiVersion.isEmpty()) { - return new TypeKey(clazz.getSimpleName(), apiGroup, apiVersion); + return new TypeKey(kind, apiGroup, apiVersion); } else if (apiVersion != null && !apiVersion.isEmpty()) { - return createKey(apiVersion, clazz.getSimpleName()); - } - return new TypeKey(clazz.getSimpleName(), null, null); - } - - private Class loadClassIfExists(String className) { - try { - Class clazz = KubernetesDeserializer.class.getClassLoader().loadClass(className); - if (!KubernetesResource.class.isAssignableFrom(clazz)) { - return null; - } - return (Class) clazz; - } catch (Exception t) { - return null; + return createKey(apiVersion, kind); } + return new TypeKey(kind, null, null); } private Predicate distinctByClassName( @@ -393,5 +320,47 @@ private Predicate distinctByClassName( return provider -> existing.add(mapperProvider.apply(provider).getName()); } + private void internalLoadFromJandex(ClassLoader classLoader) throws IOException { + Enumeration indecies = classLoader.getResources("META-INF/jandex.idx"); + while (indecies.hasMoreElements()) { + URL u = indecies.nextElement(); + if (!urlsLoaded.add(u.toString())) { + continue; + } + URLConnection uc = u.openConnection(); + uc.setUseCaches(false); + try (InputStream input = uc.getInputStream()) { + IndexReader reader = new IndexReader(input); + Index index = reader.read(); + List annotations = index.getAnnotations(DotName.createSimple(Version.class.getName())); + for (AnnotationInstance a : annotations) { + DotName name = a.target().asClass().name(); + Class clazz; + try { + clazz = classLoader.loadClass(name.toString()); + } catch (ClassNotFoundException e) { + continue; + } + addMapping(clazz); + } + } + } + } + + private void addMapping(Class clazz) { + if (!KubernetesResource.class.isAssignableFrom(clazz)) { + //If the model is shaded (which is as part of kubernetes-client uberjar) this is going to cause conflicts. + //This is why we NEED TO filter out incompatible resources. + return; + } + Class krClazz = (Class) clazz; + TypeKey keyFromClass = getKeyFromClass(krClazz); + mappings.put(keyFromClass, krClazz); + + // oc behavior - allow resolving against just the version + if (keyFromClass.apiGroup != null && keyFromClass.apiGroup.endsWith(".openshift.io")) { + mappings.putIfAbsent(new TypeKey(keyFromClass.kind, null, keyFromClass.version), krClazz); + } + } } } diff --git a/kubernetes-model-generator/kubernetes-model-core/src/main/resources/META-INF/services/io.fabric8.kubernetes.api.KubernetesResourceMappingProvider b/kubernetes-model-generator/kubernetes-model-core/src/main/resources/META-INF/services/io.fabric8.kubernetes.api.KubernetesResourceMappingProvider deleted file mode 100644 index ee2125c6841..00000000000 --- a/kubernetes-model-generator/kubernetes-model-core/src/main/resources/META-INF/services/io.fabric8.kubernetes.api.KubernetesResourceMappingProvider +++ /dev/null @@ -1 +0,0 @@ -io.fabric8.kubernetes.internal.InternalResourceMappingProvider \ No newline at end of file diff --git a/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/internal/KubernetesDeserializerTest.java b/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/internal/KubernetesDeserializerTest.java index 0aa3fef8215..f55a0875888 100644 --- a/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/internal/KubernetesDeserializerTest.java +++ b/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/internal/KubernetesDeserializerTest.java @@ -20,11 +20,13 @@ import io.fabric8.kubernetes.api.model.Pod; import io.fabric8.kubernetes.api.model.Quantity; import io.fabric8.kubernetes.internal.KubernetesDeserializer.TypeKey; -import org.apache.commons.lang3.tuple.Pair; +import io.fabric8.kubernetes.model.annotation.Group; +import io.fabric8.kubernetes.model.annotation.Kind; +import io.fabric8.kubernetes.model.annotation.Version; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.util.stream.Collectors; +import java.util.function.Consumer; import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; @@ -36,7 +38,7 @@ class KubernetesDeserializerTest { @BeforeEach public void beforeEach() { - this.mapping = new TestableMapping(createProvider()); + this.mapping = new TestableMapping(new KubernetesResourceMappingProvider() {}); } @Test @@ -81,10 +83,13 @@ void shouldRegisterProvider() { // given TypeKey key = mapping.createKey("42", "Hitchhiker"); assertThat(mapping.getForKey(key)).isNull(); - KubernetesResourceMappingProvider provider = createProvider( - Pair.of("42#Hitchhiker", SmurfResource.class)); // when - mapping.registerProvider(provider); + mapping.registerProvider(new KubernetesResourceMappingProvider() { + @Override + public void provideClasses(Consumer> classConsumer) { + classConsumer.accept(SmurfResource.class); + } + }); // then Class clazz = mapping.getForKey(key); assertThat(clazz).isEqualTo(SmurfResource.class); @@ -153,11 +158,6 @@ void shouldNotLoadClassIfKeyOnlyHasKind() { assertThat(clazz).isNull(); } - private KubernetesResourceMappingProvider createProvider(Pair>... mappings) { - return () -> Stream.of(mappings) - .collect(Collectors.toMap(Pair::getKey, Pair::getValue)); - } - public static final class TestableMapping extends KubernetesDeserializer.Mapping { private final KubernetesResourceMappingProvider provider; @@ -173,6 +173,9 @@ protected Stream getAllMappingProviders() { } + @Group("") + @Kind("Hitchhiker") + @Version("42") private static final class SmurfResource implements KubernetesResource { } } diff --git a/platforms/karaf/features/src/main/resources/feature.xml b/platforms/karaf/features/src/main/resources/feature.xml index 288c70413dd..05948f8e001 100644 --- a/platforms/karaf/features/src/main/resources/feature.xml +++ b/platforms/karaf/features/src/main/resources/feature.xml @@ -36,6 +36,7 @@ mvn:org.ow2.asm/asm-commons/${asm.bundle.version} mvn:org.ow2.asm/asm-tree/${asm.bundle.version} mvn:org.ow2.asm/asm-util/${asm.bundle.version} + mvn:org.jboss/jandex/${jandex.version} mvn:io.fabric8/kubernetes-model-common/${project.version} mvn:io.fabric8/zjsonpatch/${zjsonpatch.version} diff --git a/pom.xml b/pom.xml index 854521dbbca..d222bacec2d 100644 --- a/pom.xml +++ b/pom.xml @@ -695,6 +695,11 @@ + + org.jboss + jandex + ${jandex.version} + io.sundr builder-annotations