kubernetes-sigs / controller-runtime

Repo for the controller-runtime subproject of kubebuilder (sig-apimachinery)
Apache License 2.0
2.55k stars 1.15k forks source link

multiple group-version-kinds associated with type *v1.SecretList, refusing to guess at one #362

Closed ctron closed 1 year ago

ctron commented 5 years ago

Trying to list a secret with the following code

import corev1 "k8s.io/api/core/v1"
client.List(ctx, nil, &corev1.SecretList{})

Fails with the following error:

multiple group-version-kinds associated with type *v1.SecretList, refusing to guess at one
DirectXMan12 commented 5 years ago

Which version of Kubernetes and which version of controller-runtime? That seems bizzare, as it would imply that corev1.SecretList was associated with multiple groups.

DirectXMan12 commented 5 years ago

Can you post a minimal reproducer?

DirectXMan12 commented 5 years ago

FWIW, the following works fine for me:

package main

import (
    "context"

    ctrl "sigs.k8s.io/controller-runtime"
    "sigs.k8s.io/controller-runtime/pkg/log/zap"
    corev1 "k8s.io/api/core/v1"
    _ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
)

func main() {
    ctrl.SetLogger(zap.Logger(true))
    mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{})
    if err != nil {
        panic(err)
    }

    stopCh := ctrl.SetupSignalHandler()
    go func() {
        if err := mgr.Start(stopCh); err != nil {
            panic(err)
        }
    }()

    if started := mgr.GetCache().WaitForCacheSync(stopCh); !started {
        panic("not all started")
    }

    client := mgr.GetClient()
    var secrets corev1.SecretList
    if err := client.List(context.TODO(), &secrets); err != nil {
        panic(err)
    }

    ctrl.Log.Info("my cached secrets", "secrets", len(secrets.Items))

    directClient := mgr.GetAPIReader()
    if err := directClient.List(context.TODO(), &secrets); err != nil {
        panic(err)
    }

    ctrl.Log.Info("my direct secrets", "secrets", len(secrets.Items))
}

I'd suspect you've got something adding SecretList to a scheme somewhere it shouldn't be

ctron commented 5 years ago

So, I got a reproducer for you. Unfortunately your code did not compile, so I did need to adapt:

package main

import (
    "context"
    "os"

    "github.com/openshift/api"
    "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"

    "sigs.k8s.io/controller-runtime/pkg/runtime/signals"

    corev1 "k8s.io/api/core/v1"
    "k8s.io/client-go/kubernetes/scheme"
    _ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
    "sigs.k8s.io/controller-runtime/pkg/client/config"
    "sigs.k8s.io/controller-runtime/pkg/manager"
    logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
)

var log = logf.Log.WithName("cmd")

func main() {

    logf.SetLogger(logf.ZapLogger(true))

    cfg, err := config.GetConfig()
    if err != nil {
        log.Error(err, "Failed to get configuration")
        os.Exit(1)
    }

    mgr, err := manager.New(cfg, manager.Options{})
    if err != nil {
        log.Error(err, "Failed to create manager")
        os.Exit(1)
    }

    stopCh := signals.SetupSignalHandler()
    if started := mgr.GetCache().WaitForCacheSync(stopCh); !started {
        panic("not all started")
    }

    // add openshift API

    if err := api.Install(scheme.Scheme); err != nil {
        log.Error(err, "Failed to register OpenShift schema")
        os.Exit(1)
    }

    client := mgr.GetClient()

    // get unstructured

    usecrets := unstructured.UnstructuredList{}
    usecrets.SetKind("SecretList")
    usecrets.SetAPIVersion("v1")
    if err := client.List(context.TODO(), nil, &usecrets); err != nil {
        panic(err)
    }

    log.Info("my unstructured secrets", "secrets", len(usecrets.Items))

    // get typed

    var secrets corev1.SecretList
    if err := client.List(context.TODO(), nil, &secrets); err != nil {
        panic(err)
    }

    log.Info("my secrets", "secrets", len(secrets.Items))

}

Which results in:

2019-03-19T08:38:41.815+0100    INFO    cmd my unstructured secrets {"secrets": 487}
panic: multiple group-version-kinds associated with type *v1.SecretList, refusing to guess at one

goroutine 1 [running]:
main.main()
    /home/jreimann/gobase/enmasse/src/github.com/enmasseproject/enmasse/cmd/test/main.go:65 +0x5f5

I am using:

  - package: sigs.k8s.io/controller-runtime
    version: 0.1.9

Which resolved to:

- name: sigs.k8s.io/controller-runtime
  version: f6f0bc9611363b43664d08fb097ab13243ef621d

If you remove the registration of the OpenShift API, then it actually works. Digging a bit deeper into to code I think there is a fundamental flaw in the controller runtime, which assumes that the object kind is unique, which it isn't. Only the combination of Kind + ApiVersion is unique.

If that helps you, I can create a reproducer project on GitHub which shows the problem.

shawn-hurley commented 5 years ago

The issue is that the controller runtime when creating a default scheme, adds secrets and then when you add openshift it re-adds the type. Not the Kind but the Type.

Here: https://github.com/openshift/api/blob/master/install.go#L103

If you want to use api.Install then you need to use a scheme when the manager is created that only installs the type once I think.

ctron commented 5 years ago

I am sorry, but that cannot be the case. First of all, I am using release-3.11, which doesn't have this code: https://github.com/openshift/api/blob/release-3.11/install.go

Second, as you can see in the code you linked, that would be done by a call to InstallKube, not Install.

ctron commented 5 years ago

I created a reproducer repository for you: https://github.com/ctron/controller-runtime-362

As you can see in the output, the object is there only once, and the conflicting entry is caused by two different types, having the same "kind":

Dumping GVK ...
 - /v1, Kind=SecretList
 - image.openshift.io/v1, Kind=SecretList
Full log output ~~~ GOROOT=/home/jreimann/Downloads/go/current #gosetup GOPATH=/home/jreimann/gobase/controller-runtime-362 #gosetup /home/jreimann/Downloads/go/current/bin/go build -o /tmp/___go_build_main_go /home/jreimann/gobase/controller-runtime-362/src/github.com/ctron/controller-runtime-362/cmd/main.go #gosetup /tmp/___go_build_main_go #gosetup Dumping known types ... /__internal, Kind=WatchEvent -> v1.InternalEvent /v1, Kind=APIGroup -> v1.APIGroup /v1, Kind=APIGroupList -> v1.APIGroupList /v1, Kind=APIResourceList -> v1.APIResourceList /v1, Kind=APIVersions -> v1.APIVersions /v1, Kind=Binding -> v1.Binding /v1, Kind=ComponentStatus -> v1.ComponentStatus /v1, Kind=ComponentStatusList -> v1.ComponentStatusList /v1, Kind=ConfigMap -> v1.ConfigMap /v1, Kind=ConfigMapList -> v1.ConfigMapList /v1, Kind=CreateOptions -> v1.CreateOptions /v1, Kind=DeleteOptions -> v1.DeleteOptions /v1, Kind=Endpoints -> v1.Endpoints /v1, Kind=EndpointsList -> v1.EndpointsList /v1, Kind=Event -> v1.Event /v1, Kind=EventList -> v1.EventList /v1, Kind=ExportOptions -> v1.ExportOptions /v1, Kind=GetOptions -> v1.GetOptions /v1, Kind=LimitRange -> v1.LimitRange /v1, Kind=LimitRangeList -> v1.LimitRangeList /v1, Kind=List -> v1.List /v1, Kind=ListOptions -> v1.ListOptions /v1, Kind=Namespace -> v1.Namespace /v1, Kind=NamespaceList -> v1.NamespaceList /v1, Kind=Node -> v1.Node /v1, Kind=NodeList -> v1.NodeList /v1, Kind=NodeProxyOptions -> v1.NodeProxyOptions /v1, Kind=PersistentVolume -> v1.PersistentVolume /v1, Kind=PersistentVolumeClaim -> v1.PersistentVolumeClaim /v1, Kind=PersistentVolumeClaimList -> v1.PersistentVolumeClaimList /v1, Kind=PersistentVolumeList -> v1.PersistentVolumeList /v1, Kind=Pod -> v1.Pod /v1, Kind=PodAttachOptions -> v1.PodAttachOptions /v1, Kind=PodExecOptions -> v1.PodExecOptions /v1, Kind=PodList -> v1.PodList /v1, Kind=PodLogOptions -> v1.PodLogOptions /v1, Kind=PodPortForwardOptions -> v1.PodPortForwardOptions /v1, Kind=PodProxyOptions -> v1.PodProxyOptions /v1, Kind=PodStatusResult -> v1.PodStatusResult /v1, Kind=PodTemplate -> v1.PodTemplate /v1, Kind=PodTemplateList -> v1.PodTemplateList /v1, Kind=RangeAllocation -> v1.RangeAllocation /v1, Kind=ReplicationController -> v1.ReplicationController /v1, Kind=ReplicationControllerList -> v1.ReplicationControllerList /v1, Kind=ResourceQuota -> v1.ResourceQuota /v1, Kind=ResourceQuotaList -> v1.ResourceQuotaList /v1, Kind=Secret -> v1.Secret /v1, Kind=SecretList -> v1.SecretList /v1, Kind=SerializedReference -> v1.SerializedReference /v1, Kind=Service -> v1.Service /v1, Kind=ServiceAccount -> v1.ServiceAccount /v1, Kind=ServiceAccountList -> v1.ServiceAccountList /v1, Kind=ServiceList -> v1.ServiceList /v1, Kind=ServiceProxyOptions -> v1.ServiceProxyOptions /v1, Kind=Status -> v1.Status /v1, Kind=UpdateOptions -> v1.UpdateOptions /v1, Kind=WatchEvent -> v1.WatchEvent admissionregistration.k8s.io/__internal, Kind=WatchEvent -> v1.InternalEvent admissionregistration.k8s.io/v1alpha1, Kind=CreateOptions -> v1.CreateOptions admissionregistration.k8s.io/v1alpha1, Kind=DeleteOptions -> v1.DeleteOptions admissionregistration.k8s.io/v1alpha1, Kind=ExportOptions -> v1.ExportOptions admissionregistration.k8s.io/v1alpha1, Kind=GetOptions -> v1.GetOptions admissionregistration.k8s.io/v1alpha1, Kind=InitializerConfiguration -> v1alpha1.InitializerConfiguration admissionregistration.k8s.io/v1alpha1, Kind=InitializerConfigurationList -> v1alpha1.InitializerConfigurationList admissionregistration.k8s.io/v1alpha1, Kind=ListOptions -> v1.ListOptions admissionregistration.k8s.io/v1alpha1, Kind=UpdateOptions -> v1.UpdateOptions admissionregistration.k8s.io/v1alpha1, Kind=WatchEvent -> v1.WatchEvent admissionregistration.k8s.io/v1beta1, Kind=CreateOptions -> v1.CreateOptions admissionregistration.k8s.io/v1beta1, Kind=DeleteOptions -> v1.DeleteOptions admissionregistration.k8s.io/v1beta1, Kind=ExportOptions -> v1.ExportOptions admissionregistration.k8s.io/v1beta1, Kind=GetOptions -> v1.GetOptions admissionregistration.k8s.io/v1beta1, Kind=ListOptions -> v1.ListOptions admissionregistration.k8s.io/v1beta1, Kind=MutatingWebhookConfiguration -> v1beta1.MutatingWebhookConfiguration admissionregistration.k8s.io/v1beta1, Kind=MutatingWebhookConfigurationList -> v1beta1.MutatingWebhookConfigurationList admissionregistration.k8s.io/v1beta1, Kind=UpdateOptions -> v1.UpdateOptions admissionregistration.k8s.io/v1beta1, Kind=ValidatingWebhookConfiguration -> v1beta1.ValidatingWebhookConfiguration admissionregistration.k8s.io/v1beta1, Kind=ValidatingWebhookConfigurationList -> v1beta1.ValidatingWebhookConfigurationList admissionregistration.k8s.io/v1beta1, Kind=WatchEvent -> v1.WatchEvent apps/__internal, Kind=WatchEvent -> v1.InternalEvent apps/v1, Kind=ControllerRevision -> v1.ControllerRevision apps/v1, Kind=ControllerRevisionList -> v1.ControllerRevisionList apps/v1, Kind=CreateOptions -> v1.CreateOptions apps/v1, Kind=DaemonSet -> v1.DaemonSet apps/v1, Kind=DaemonSetList -> v1.DaemonSetList apps/v1, Kind=DeleteOptions -> v1.DeleteOptions apps/v1, Kind=Deployment -> v1.Deployment apps/v1, Kind=DeploymentList -> v1.DeploymentList apps/v1, Kind=ExportOptions -> v1.ExportOptions apps/v1, Kind=GetOptions -> v1.GetOptions apps/v1, Kind=ListOptions -> v1.ListOptions apps/v1, Kind=ReplicaSet -> v1.ReplicaSet apps/v1, Kind=ReplicaSetList -> v1.ReplicaSetList apps/v1, Kind=StatefulSet -> v1.StatefulSet apps/v1, Kind=StatefulSetList -> v1.StatefulSetList apps/v1, Kind=UpdateOptions -> v1.UpdateOptions apps/v1, Kind=WatchEvent -> v1.WatchEvent apps/v1beta1, Kind=ControllerRevision -> v1beta1.ControllerRevision apps/v1beta1, Kind=ControllerRevisionList -> v1beta1.ControllerRevisionList apps/v1beta1, Kind=CreateOptions -> v1.CreateOptions apps/v1beta1, Kind=DeleteOptions -> v1.DeleteOptions apps/v1beta1, Kind=Deployment -> v1beta1.Deployment apps/v1beta1, Kind=DeploymentList -> v1beta1.DeploymentList apps/v1beta1, Kind=DeploymentRollback -> v1beta1.DeploymentRollback apps/v1beta1, Kind=ExportOptions -> v1.ExportOptions apps/v1beta1, Kind=GetOptions -> v1.GetOptions apps/v1beta1, Kind=ListOptions -> v1.ListOptions apps/v1beta1, Kind=Scale -> v1beta1.Scale apps/v1beta1, Kind=StatefulSet -> v1beta1.StatefulSet apps/v1beta1, Kind=StatefulSetList -> v1beta1.StatefulSetList apps/v1beta1, Kind=UpdateOptions -> v1.UpdateOptions apps/v1beta1, Kind=WatchEvent -> v1.WatchEvent apps/v1beta2, Kind=ControllerRevision -> v1beta2.ControllerRevision apps/v1beta2, Kind=ControllerRevisionList -> v1beta2.ControllerRevisionList apps/v1beta2, Kind=CreateOptions -> v1.CreateOptions apps/v1beta2, Kind=DaemonSet -> v1beta2.DaemonSet apps/v1beta2, Kind=DaemonSetList -> v1beta2.DaemonSetList apps/v1beta2, Kind=DeleteOptions -> v1.DeleteOptions apps/v1beta2, Kind=Deployment -> v1beta2.Deployment apps/v1beta2, Kind=DeploymentList -> v1beta2.DeploymentList apps/v1beta2, Kind=ExportOptions -> v1.ExportOptions apps/v1beta2, Kind=GetOptions -> v1.GetOptions apps/v1beta2, Kind=ListOptions -> v1.ListOptions apps/v1beta2, Kind=ReplicaSet -> v1beta2.ReplicaSet apps/v1beta2, Kind=ReplicaSetList -> v1beta2.ReplicaSetList apps/v1beta2, Kind=Scale -> v1beta2.Scale apps/v1beta2, Kind=StatefulSet -> v1beta2.StatefulSet apps/v1beta2, Kind=StatefulSetList -> v1beta2.StatefulSetList apps/v1beta2, Kind=UpdateOptions -> v1.UpdateOptions apps/v1beta2, Kind=WatchEvent -> v1.WatchEvent apps.openshift.io/__internal, Kind=WatchEvent -> v1.InternalEvent apps.openshift.io/v1, Kind=CreateOptions -> v1.CreateOptions apps.openshift.io/v1, Kind=DeleteOptions -> v1.DeleteOptions apps.openshift.io/v1, Kind=DeploymentConfig -> v1.DeploymentConfig apps.openshift.io/v1, Kind=DeploymentConfigList -> v1.DeploymentConfigList apps.openshift.io/v1, Kind=DeploymentConfigRollback -> v1.DeploymentConfigRollback apps.openshift.io/v1, Kind=DeploymentLog -> v1.DeploymentLog apps.openshift.io/v1, Kind=DeploymentLogOptions -> v1.DeploymentLogOptions apps.openshift.io/v1, Kind=DeploymentRequest -> v1.DeploymentRequest apps.openshift.io/v1, Kind=ExportOptions -> v1.ExportOptions apps.openshift.io/v1, Kind=GetOptions -> v1.GetOptions apps.openshift.io/v1, Kind=ListOptions -> v1.ListOptions apps.openshift.io/v1, Kind=Scale -> v1beta1.Scale apps.openshift.io/v1, Kind=UpdateOptions -> v1.UpdateOptions apps.openshift.io/v1, Kind=WatchEvent -> v1.WatchEvent authentication.k8s.io/__internal, Kind=WatchEvent -> v1.InternalEvent authentication.k8s.io/v1, Kind=CreateOptions -> v1.CreateOptions authentication.k8s.io/v1, Kind=DeleteOptions -> v1.DeleteOptions authentication.k8s.io/v1, Kind=ExportOptions -> v1.ExportOptions authentication.k8s.io/v1, Kind=GetOptions -> v1.GetOptions authentication.k8s.io/v1, Kind=ListOptions -> v1.ListOptions authentication.k8s.io/v1, Kind=TokenRequest -> v1.TokenRequest authentication.k8s.io/v1, Kind=TokenReview -> v1.TokenReview authentication.k8s.io/v1, Kind=UpdateOptions -> v1.UpdateOptions authentication.k8s.io/v1, Kind=WatchEvent -> v1.WatchEvent authentication.k8s.io/v1beta1, Kind=CreateOptions -> v1.CreateOptions authentication.k8s.io/v1beta1, Kind=DeleteOptions -> v1.DeleteOptions authentication.k8s.io/v1beta1, Kind=ExportOptions -> v1.ExportOptions authentication.k8s.io/v1beta1, Kind=GetOptions -> v1.GetOptions authentication.k8s.io/v1beta1, Kind=ListOptions -> v1.ListOptions authentication.k8s.io/v1beta1, Kind=TokenReview -> v1beta1.TokenReview authentication.k8s.io/v1beta1, Kind=UpdateOptions -> v1.UpdateOptions authentication.k8s.io/v1beta1, Kind=WatchEvent -> v1.WatchEvent authorization.k8s.io/__internal, Kind=WatchEvent -> v1.InternalEvent authorization.k8s.io/v1, Kind=CreateOptions -> v1.CreateOptions authorization.k8s.io/v1, Kind=DeleteOptions -> v1.DeleteOptions authorization.k8s.io/v1, Kind=ExportOptions -> v1.ExportOptions authorization.k8s.io/v1, Kind=GetOptions -> v1.GetOptions authorization.k8s.io/v1, Kind=ListOptions -> v1.ListOptions authorization.k8s.io/v1, Kind=LocalSubjectAccessReview -> v1.LocalSubjectAccessReview authorization.k8s.io/v1, Kind=SelfSubjectAccessReview -> v1.SelfSubjectAccessReview authorization.k8s.io/v1, Kind=SelfSubjectRulesReview -> v1.SelfSubjectRulesReview authorization.k8s.io/v1, Kind=SubjectAccessReview -> v1.SubjectAccessReview authorization.k8s.io/v1, Kind=UpdateOptions -> v1.UpdateOptions authorization.k8s.io/v1, Kind=WatchEvent -> v1.WatchEvent authorization.k8s.io/v1beta1, Kind=CreateOptions -> v1.CreateOptions authorization.k8s.io/v1beta1, Kind=DeleteOptions -> v1.DeleteOptions authorization.k8s.io/v1beta1, Kind=ExportOptions -> v1.ExportOptions authorization.k8s.io/v1beta1, Kind=GetOptions -> v1.GetOptions authorization.k8s.io/v1beta1, Kind=ListOptions -> v1.ListOptions authorization.k8s.io/v1beta1, Kind=LocalSubjectAccessReview -> v1beta1.LocalSubjectAccessReview authorization.k8s.io/v1beta1, Kind=SelfSubjectAccessReview -> v1beta1.SelfSubjectAccessReview authorization.k8s.io/v1beta1, Kind=SelfSubjectRulesReview -> v1beta1.SelfSubjectRulesReview authorization.k8s.io/v1beta1, Kind=SubjectAccessReview -> v1beta1.SubjectAccessReview authorization.k8s.io/v1beta1, Kind=UpdateOptions -> v1.UpdateOptions authorization.k8s.io/v1beta1, Kind=WatchEvent -> v1.WatchEvent authorization.openshift.io/__internal, Kind=WatchEvent -> v1.InternalEvent authorization.openshift.io/v1, Kind=ClusterRole -> v1.ClusterRole authorization.openshift.io/v1, Kind=ClusterRoleBinding -> v1.ClusterRoleBinding authorization.openshift.io/v1, Kind=ClusterRoleBindingList -> v1.ClusterRoleBindingList authorization.openshift.io/v1, Kind=ClusterRoleList -> v1.ClusterRoleList authorization.openshift.io/v1, Kind=CreateOptions -> v1.CreateOptions authorization.openshift.io/v1, Kind=DeleteOptions -> v1.DeleteOptions authorization.openshift.io/v1, Kind=ExportOptions -> v1.ExportOptions authorization.openshift.io/v1, Kind=GetOptions -> v1.GetOptions authorization.openshift.io/v1, Kind=IsPersonalSubjectAccessReview -> v1.IsPersonalSubjectAccessReview authorization.openshift.io/v1, Kind=ListOptions -> v1.ListOptions authorization.openshift.io/v1, Kind=LocalResourceAccessReview -> v1.LocalResourceAccessReview authorization.openshift.io/v1, Kind=LocalSubjectAccessReview -> v1.LocalSubjectAccessReview authorization.openshift.io/v1, Kind=ResourceAccessReview -> v1.ResourceAccessReview authorization.openshift.io/v1, Kind=ResourceAccessReviewResponse -> v1.ResourceAccessReviewResponse authorization.openshift.io/v1, Kind=Role -> v1.Role authorization.openshift.io/v1, Kind=RoleBinding -> v1.RoleBinding authorization.openshift.io/v1, Kind=RoleBindingList -> v1.RoleBindingList authorization.openshift.io/v1, Kind=RoleBindingRestriction -> v1.RoleBindingRestriction authorization.openshift.io/v1, Kind=RoleBindingRestrictionList -> v1.RoleBindingRestrictionList authorization.openshift.io/v1, Kind=RoleList -> v1.RoleList authorization.openshift.io/v1, Kind=SelfSubjectRulesReview -> v1.SelfSubjectRulesReview authorization.openshift.io/v1, Kind=SubjectAccessReview -> v1.SubjectAccessReview authorization.openshift.io/v1, Kind=SubjectAccessReviewResponse -> v1.SubjectAccessReviewResponse authorization.openshift.io/v1, Kind=SubjectRulesReview -> v1.SubjectRulesReview authorization.openshift.io/v1, Kind=UpdateOptions -> v1.UpdateOptions authorization.openshift.io/v1, Kind=WatchEvent -> v1.WatchEvent autoscaling/__internal, Kind=WatchEvent -> v1.InternalEvent autoscaling/v1, Kind=CreateOptions -> v1.CreateOptions autoscaling/v1, Kind=DeleteOptions -> v1.DeleteOptions autoscaling/v1, Kind=ExportOptions -> v1.ExportOptions autoscaling/v1, Kind=GetOptions -> v1.GetOptions autoscaling/v1, Kind=HorizontalPodAutoscaler -> v1.HorizontalPodAutoscaler autoscaling/v1, Kind=HorizontalPodAutoscalerList -> v1.HorizontalPodAutoscalerList autoscaling/v1, Kind=ListOptions -> v1.ListOptions autoscaling/v1, Kind=Scale -> v1.Scale autoscaling/v1, Kind=UpdateOptions -> v1.UpdateOptions autoscaling/v1, Kind=WatchEvent -> v1.WatchEvent autoscaling/v2beta1, Kind=CreateOptions -> v1.CreateOptions autoscaling/v2beta1, Kind=DeleteOptions -> v1.DeleteOptions autoscaling/v2beta1, Kind=ExportOptions -> v1.ExportOptions autoscaling/v2beta1, Kind=GetOptions -> v1.GetOptions autoscaling/v2beta1, Kind=HorizontalPodAutoscaler -> v2beta1.HorizontalPodAutoscaler autoscaling/v2beta1, Kind=HorizontalPodAutoscalerList -> v2beta1.HorizontalPodAutoscalerList autoscaling/v2beta1, Kind=ListOptions -> v1.ListOptions autoscaling/v2beta1, Kind=UpdateOptions -> v1.UpdateOptions autoscaling/v2beta1, Kind=WatchEvent -> v1.WatchEvent autoscaling/v2beta2, Kind=CreateOptions -> v1.CreateOptions autoscaling/v2beta2, Kind=DeleteOptions -> v1.DeleteOptions autoscaling/v2beta2, Kind=ExportOptions -> v1.ExportOptions autoscaling/v2beta2, Kind=GetOptions -> v1.GetOptions autoscaling/v2beta2, Kind=HorizontalPodAutoscaler -> v2beta2.HorizontalPodAutoscaler autoscaling/v2beta2, Kind=HorizontalPodAutoscalerList -> v2beta2.HorizontalPodAutoscalerList autoscaling/v2beta2, Kind=ListOptions -> v1.ListOptions autoscaling/v2beta2, Kind=UpdateOptions -> v1.UpdateOptions autoscaling/v2beta2, Kind=WatchEvent -> v1.WatchEvent batch/__internal, Kind=WatchEvent -> v1.InternalEvent batch/v1, Kind=CreateOptions -> v1.CreateOptions batch/v1, Kind=DeleteOptions -> v1.DeleteOptions batch/v1, Kind=ExportOptions -> v1.ExportOptions batch/v1, Kind=GetOptions -> v1.GetOptions batch/v1, Kind=Job -> v1.Job batch/v1, Kind=JobList -> v1.JobList batch/v1, Kind=ListOptions -> v1.ListOptions batch/v1, Kind=UpdateOptions -> v1.UpdateOptions batch/v1, Kind=WatchEvent -> v1.WatchEvent batch/v1beta1, Kind=CreateOptions -> v1.CreateOptions batch/v1beta1, Kind=CronJob -> v1beta1.CronJob batch/v1beta1, Kind=CronJobList -> v1beta1.CronJobList batch/v1beta1, Kind=DeleteOptions -> v1.DeleteOptions batch/v1beta1, Kind=ExportOptions -> v1.ExportOptions batch/v1beta1, Kind=GetOptions -> v1.GetOptions batch/v1beta1, Kind=JobTemplate -> v1beta1.JobTemplate batch/v1beta1, Kind=ListOptions -> v1.ListOptions batch/v1beta1, Kind=UpdateOptions -> v1.UpdateOptions batch/v1beta1, Kind=WatchEvent -> v1.WatchEvent batch/v2alpha1, Kind=CreateOptions -> v1.CreateOptions batch/v2alpha1, Kind=CronJob -> v2alpha1.CronJob batch/v2alpha1, Kind=CronJobList -> v2alpha1.CronJobList batch/v2alpha1, Kind=DeleteOptions -> v1.DeleteOptions batch/v2alpha1, Kind=ExportOptions -> v1.ExportOptions batch/v2alpha1, Kind=GetOptions -> v1.GetOptions batch/v2alpha1, Kind=JobTemplate -> v2alpha1.JobTemplate batch/v2alpha1, Kind=ListOptions -> v1.ListOptions batch/v2alpha1, Kind=UpdateOptions -> v1.UpdateOptions batch/v2alpha1, Kind=WatchEvent -> v1.WatchEvent build.openshift.io/__internal, Kind=WatchEvent -> v1.InternalEvent build.openshift.io/v1, Kind=BinaryBuildRequestOptions -> v1.BinaryBuildRequestOptions build.openshift.io/v1, Kind=Build -> v1.Build build.openshift.io/v1, Kind=BuildConfig -> v1.BuildConfig build.openshift.io/v1, Kind=BuildConfigList -> v1.BuildConfigList build.openshift.io/v1, Kind=BuildList -> v1.BuildList build.openshift.io/v1, Kind=BuildLog -> v1.BuildLog build.openshift.io/v1, Kind=BuildLogOptions -> v1.BuildLogOptions build.openshift.io/v1, Kind=BuildRequest -> v1.BuildRequest build.openshift.io/v1, Kind=CreateOptions -> v1.CreateOptions build.openshift.io/v1, Kind=DeleteOptions -> v1.DeleteOptions build.openshift.io/v1, Kind=ExportOptions -> v1.ExportOptions build.openshift.io/v1, Kind=GetOptions -> v1.GetOptions build.openshift.io/v1, Kind=ListOptions -> v1.ListOptions build.openshift.io/v1, Kind=PodProxyOptions -> v1.PodProxyOptions build.openshift.io/v1, Kind=UpdateOptions -> v1.UpdateOptions build.openshift.io/v1, Kind=WatchEvent -> v1.WatchEvent certificates.k8s.io/__internal, Kind=WatchEvent -> v1.InternalEvent certificates.k8s.io/v1beta1, Kind=CertificateSigningRequest -> v1beta1.CertificateSigningRequest certificates.k8s.io/v1beta1, Kind=CertificateSigningRequestList -> v1beta1.CertificateSigningRequestList certificates.k8s.io/v1beta1, Kind=CreateOptions -> v1.CreateOptions certificates.k8s.io/v1beta1, Kind=DeleteOptions -> v1.DeleteOptions certificates.k8s.io/v1beta1, Kind=ExportOptions -> v1.ExportOptions certificates.k8s.io/v1beta1, Kind=GetOptions -> v1.GetOptions certificates.k8s.io/v1beta1, Kind=ListOptions -> v1.ListOptions certificates.k8s.io/v1beta1, Kind=UpdateOptions -> v1.UpdateOptions certificates.k8s.io/v1beta1, Kind=WatchEvent -> v1.WatchEvent coordination.k8s.io/__internal, Kind=WatchEvent -> v1.InternalEvent coordination.k8s.io/v1beta1, Kind=CreateOptions -> v1.CreateOptions coordination.k8s.io/v1beta1, Kind=DeleteOptions -> v1.DeleteOptions coordination.k8s.io/v1beta1, Kind=ExportOptions -> v1.ExportOptions coordination.k8s.io/v1beta1, Kind=GetOptions -> v1.GetOptions coordination.k8s.io/v1beta1, Kind=Lease -> v1beta1.Lease coordination.k8s.io/v1beta1, Kind=LeaseList -> v1beta1.LeaseList coordination.k8s.io/v1beta1, Kind=ListOptions -> v1.ListOptions coordination.k8s.io/v1beta1, Kind=UpdateOptions -> v1.UpdateOptions coordination.k8s.io/v1beta1, Kind=WatchEvent -> v1.WatchEvent events.k8s.io/__internal, Kind=WatchEvent -> v1.InternalEvent events.k8s.io/v1beta1, Kind=CreateOptions -> v1.CreateOptions events.k8s.io/v1beta1, Kind=DeleteOptions -> v1.DeleteOptions events.k8s.io/v1beta1, Kind=Event -> v1beta1.Event events.k8s.io/v1beta1, Kind=EventList -> v1beta1.EventList events.k8s.io/v1beta1, Kind=ExportOptions -> v1.ExportOptions events.k8s.io/v1beta1, Kind=GetOptions -> v1.GetOptions events.k8s.io/v1beta1, Kind=ListOptions -> v1.ListOptions events.k8s.io/v1beta1, Kind=UpdateOptions -> v1.UpdateOptions events.k8s.io/v1beta1, Kind=WatchEvent -> v1.WatchEvent extensions/__internal, Kind=WatchEvent -> v1.InternalEvent extensions/v1beta1, Kind=CreateOptions -> v1.CreateOptions extensions/v1beta1, Kind=DaemonSet -> v1beta1.DaemonSet extensions/v1beta1, Kind=DaemonSetList -> v1beta1.DaemonSetList extensions/v1beta1, Kind=DeleteOptions -> v1.DeleteOptions extensions/v1beta1, Kind=Deployment -> v1beta1.Deployment extensions/v1beta1, Kind=DeploymentList -> v1beta1.DeploymentList extensions/v1beta1, Kind=DeploymentRollback -> v1beta1.DeploymentRollback extensions/v1beta1, Kind=ExportOptions -> v1.ExportOptions extensions/v1beta1, Kind=GetOptions -> v1.GetOptions extensions/v1beta1, Kind=Ingress -> v1beta1.Ingress extensions/v1beta1, Kind=IngressList -> v1beta1.IngressList extensions/v1beta1, Kind=ListOptions -> v1.ListOptions extensions/v1beta1, Kind=NetworkPolicy -> v1beta1.NetworkPolicy extensions/v1beta1, Kind=NetworkPolicyList -> v1beta1.NetworkPolicyList extensions/v1beta1, Kind=PodSecurityPolicy -> v1beta1.PodSecurityPolicy extensions/v1beta1, Kind=PodSecurityPolicyList -> v1beta1.PodSecurityPolicyList extensions/v1beta1, Kind=ReplicaSet -> v1beta1.ReplicaSet extensions/v1beta1, Kind=ReplicaSetList -> v1beta1.ReplicaSetList extensions/v1beta1, Kind=ReplicationControllerDummy -> v1beta1.ReplicationControllerDummy extensions/v1beta1, Kind=Scale -> v1beta1.Scale extensions/v1beta1, Kind=UpdateOptions -> v1.UpdateOptions extensions/v1beta1, Kind=WatchEvent -> v1.WatchEvent image.openshift.io/1.0, Kind=DockerImage -> docker10.DockerImage image.openshift.io/__internal, Kind=WatchEvent -> v1.InternalEvent image.openshift.io/pre012, Kind=DockerImage -> dockerpre012.DockerImage image.openshift.io/v1, Kind=CreateOptions -> v1.CreateOptions image.openshift.io/v1, Kind=DeleteOptions -> v1.DeleteOptions image.openshift.io/v1, Kind=ExportOptions -> v1.ExportOptions image.openshift.io/v1, Kind=GetOptions -> v1.GetOptions image.openshift.io/v1, Kind=Image -> v1.Image image.openshift.io/v1, Kind=ImageList -> v1.ImageList image.openshift.io/v1, Kind=ImageSignature -> v1.ImageSignature image.openshift.io/v1, Kind=ImageStream -> v1.ImageStream image.openshift.io/v1, Kind=ImageStreamImage -> v1.ImageStreamImage image.openshift.io/v1, Kind=ImageStreamImport -> v1.ImageStreamImport image.openshift.io/v1, Kind=ImageStreamLayers -> v1.ImageStreamLayers image.openshift.io/v1, Kind=ImageStreamList -> v1.ImageStreamList image.openshift.io/v1, Kind=ImageStreamMapping -> v1.ImageStreamMapping image.openshift.io/v1, Kind=ImageStreamTag -> v1.ImageStreamTag image.openshift.io/v1, Kind=ImageStreamTagList -> v1.ImageStreamTagList image.openshift.io/v1, Kind=ListOptions -> v1.ListOptions image.openshift.io/v1, Kind=SecretList -> v1.SecretList image.openshift.io/v1, Kind=UpdateOptions -> v1.UpdateOptions image.openshift.io/v1, Kind=WatchEvent -> v1.WatchEvent network.openshift.io/__internal, Kind=WatchEvent -> v1.InternalEvent network.openshift.io/v1, Kind=ClusterNetwork -> v1.ClusterNetwork network.openshift.io/v1, Kind=ClusterNetworkList -> v1.ClusterNetworkList network.openshift.io/v1, Kind=CreateOptions -> v1.CreateOptions network.openshift.io/v1, Kind=DeleteOptions -> v1.DeleteOptions network.openshift.io/v1, Kind=EgressNetworkPolicy -> v1.EgressNetworkPolicy network.openshift.io/v1, Kind=EgressNetworkPolicyList -> v1.EgressNetworkPolicyList network.openshift.io/v1, Kind=ExportOptions -> v1.ExportOptions network.openshift.io/v1, Kind=GetOptions -> v1.GetOptions network.openshift.io/v1, Kind=HostSubnet -> v1.HostSubnet network.openshift.io/v1, Kind=HostSubnetList -> v1.HostSubnetList network.openshift.io/v1, Kind=ListOptions -> v1.ListOptions network.openshift.io/v1, Kind=NetNamespace -> v1.NetNamespace network.openshift.io/v1, Kind=NetNamespaceList -> v1.NetNamespaceList network.openshift.io/v1, Kind=UpdateOptions -> v1.UpdateOptions network.openshift.io/v1, Kind=WatchEvent -> v1.WatchEvent networking.k8s.io/__internal, Kind=WatchEvent -> v1.InternalEvent networking.k8s.io/v1, Kind=CreateOptions -> v1.CreateOptions networking.k8s.io/v1, Kind=DeleteOptions -> v1.DeleteOptions networking.k8s.io/v1, Kind=ExportOptions -> v1.ExportOptions networking.k8s.io/v1, Kind=GetOptions -> v1.GetOptions networking.k8s.io/v1, Kind=ListOptions -> v1.ListOptions networking.k8s.io/v1, Kind=NetworkPolicy -> v1.NetworkPolicy networking.k8s.io/v1, Kind=NetworkPolicyList -> v1.NetworkPolicyList networking.k8s.io/v1, Kind=UpdateOptions -> v1.UpdateOptions networking.k8s.io/v1, Kind=WatchEvent -> v1.WatchEvent oauth.openshift.io/__internal, Kind=WatchEvent -> v1.InternalEvent oauth.openshift.io/v1, Kind=CreateOptions -> v1.CreateOptions oauth.openshift.io/v1, Kind=DeleteOptions -> v1.DeleteOptions oauth.openshift.io/v1, Kind=ExportOptions -> v1.ExportOptions oauth.openshift.io/v1, Kind=GetOptions -> v1.GetOptions oauth.openshift.io/v1, Kind=ListOptions -> v1.ListOptions oauth.openshift.io/v1, Kind=OAuthAccessToken -> v1.OAuthAccessToken oauth.openshift.io/v1, Kind=OAuthAccessTokenList -> v1.OAuthAccessTokenList oauth.openshift.io/v1, Kind=OAuthAuthorizeToken -> v1.OAuthAuthorizeToken oauth.openshift.io/v1, Kind=OAuthAuthorizeTokenList -> v1.OAuthAuthorizeTokenList oauth.openshift.io/v1, Kind=OAuthClient -> v1.OAuthClient oauth.openshift.io/v1, Kind=OAuthClientAuthorization -> v1.OAuthClientAuthorization oauth.openshift.io/v1, Kind=OAuthClientAuthorizationList -> v1.OAuthClientAuthorizationList oauth.openshift.io/v1, Kind=OAuthClientList -> v1.OAuthClientList oauth.openshift.io/v1, Kind=OAuthRedirectReference -> v1.OAuthRedirectReference oauth.openshift.io/v1, Kind=UpdateOptions -> v1.UpdateOptions oauth.openshift.io/v1, Kind=WatchEvent -> v1.WatchEvent operator.openshift.io/__internal, Kind=WatchEvent -> v1.InternalEvent operator.openshift.io/v1alpha1, Kind=CreateOptions -> v1.CreateOptions operator.openshift.io/v1alpha1, Kind=DeleteOptions -> v1.DeleteOptions operator.openshift.io/v1alpha1, Kind=ExportOptions -> v1.ExportOptions operator.openshift.io/v1alpha1, Kind=GenericOperatorConfig -> v1alpha1.GenericOperatorConfig operator.openshift.io/v1alpha1, Kind=GetOptions -> v1.GetOptions operator.openshift.io/v1alpha1, Kind=ListOptions -> v1.ListOptions operator.openshift.io/v1alpha1, Kind=UpdateOptions -> v1.UpdateOptions operator.openshift.io/v1alpha1, Kind=WatchEvent -> v1.WatchEvent policy/__internal, Kind=WatchEvent -> v1.InternalEvent policy/v1beta1, Kind=CreateOptions -> v1.CreateOptions policy/v1beta1, Kind=DeleteOptions -> v1.DeleteOptions policy/v1beta1, Kind=Eviction -> v1beta1.Eviction policy/v1beta1, Kind=ExportOptions -> v1.ExportOptions policy/v1beta1, Kind=GetOptions -> v1.GetOptions policy/v1beta1, Kind=ListOptions -> v1.ListOptions policy/v1beta1, Kind=PodDisruptionBudget -> v1beta1.PodDisruptionBudget policy/v1beta1, Kind=PodDisruptionBudgetList -> v1beta1.PodDisruptionBudgetList policy/v1beta1, Kind=PodSecurityPolicy -> v1beta1.PodSecurityPolicy policy/v1beta1, Kind=PodSecurityPolicyList -> v1beta1.PodSecurityPolicyList policy/v1beta1, Kind=UpdateOptions -> v1.UpdateOptions policy/v1beta1, Kind=WatchEvent -> v1.WatchEvent project.openshift.io/__internal, Kind=WatchEvent -> v1.InternalEvent project.openshift.io/v1, Kind=CreateOptions -> v1.CreateOptions project.openshift.io/v1, Kind=DeleteOptions -> v1.DeleteOptions project.openshift.io/v1, Kind=ExportOptions -> v1.ExportOptions project.openshift.io/v1, Kind=GetOptions -> v1.GetOptions project.openshift.io/v1, Kind=ListOptions -> v1.ListOptions project.openshift.io/v1, Kind=Project -> v1.Project project.openshift.io/v1, Kind=ProjectList -> v1.ProjectList project.openshift.io/v1, Kind=ProjectRequest -> v1.ProjectRequest project.openshift.io/v1, Kind=UpdateOptions -> v1.UpdateOptions project.openshift.io/v1, Kind=WatchEvent -> v1.WatchEvent quota.openshift.io/__internal, Kind=WatchEvent -> v1.InternalEvent quota.openshift.io/v1, Kind=AppliedClusterResourceQuota -> v1.AppliedClusterResourceQuota quota.openshift.io/v1, Kind=AppliedClusterResourceQuotaList -> v1.AppliedClusterResourceQuotaList quota.openshift.io/v1, Kind=ClusterResourceQuota -> v1.ClusterResourceQuota quota.openshift.io/v1, Kind=ClusterResourceQuotaList -> v1.ClusterResourceQuotaList quota.openshift.io/v1, Kind=CreateOptions -> v1.CreateOptions quota.openshift.io/v1, Kind=DeleteOptions -> v1.DeleteOptions quota.openshift.io/v1, Kind=ExportOptions -> v1.ExportOptions quota.openshift.io/v1, Kind=GetOptions -> v1.GetOptions quota.openshift.io/v1, Kind=ListOptions -> v1.ListOptions quota.openshift.io/v1, Kind=UpdateOptions -> v1.UpdateOptions quota.openshift.io/v1, Kind=WatchEvent -> v1.WatchEvent rbac.authorization.k8s.io/__internal, Kind=WatchEvent -> v1.InternalEvent rbac.authorization.k8s.io/v1, Kind=ClusterRole -> v1.ClusterRole rbac.authorization.k8s.io/v1, Kind=ClusterRoleBinding -> v1.ClusterRoleBinding rbac.authorization.k8s.io/v1, Kind=ClusterRoleBindingList -> v1.ClusterRoleBindingList rbac.authorization.k8s.io/v1, Kind=ClusterRoleList -> v1.ClusterRoleList rbac.authorization.k8s.io/v1, Kind=CreateOptions -> v1.CreateOptions rbac.authorization.k8s.io/v1, Kind=DeleteOptions -> v1.DeleteOptions rbac.authorization.k8s.io/v1, Kind=ExportOptions -> v1.ExportOptions rbac.authorization.k8s.io/v1, Kind=GetOptions -> v1.GetOptions rbac.authorization.k8s.io/v1, Kind=ListOptions -> v1.ListOptions rbac.authorization.k8s.io/v1, Kind=Role -> v1.Role rbac.authorization.k8s.io/v1, Kind=RoleBinding -> v1.RoleBinding rbac.authorization.k8s.io/v1, Kind=RoleBindingList -> v1.RoleBindingList rbac.authorization.k8s.io/v1, Kind=RoleList -> v1.RoleList rbac.authorization.k8s.io/v1, Kind=UpdateOptions -> v1.UpdateOptions rbac.authorization.k8s.io/v1, Kind=WatchEvent -> v1.WatchEvent rbac.authorization.k8s.io/v1alpha1, Kind=ClusterRole -> v1alpha1.ClusterRole rbac.authorization.k8s.io/v1alpha1, Kind=ClusterRoleBinding -> v1alpha1.ClusterRoleBinding rbac.authorization.k8s.io/v1alpha1, Kind=ClusterRoleBindingList -> v1alpha1.ClusterRoleBindingList rbac.authorization.k8s.io/v1alpha1, Kind=ClusterRoleList -> v1alpha1.ClusterRoleList rbac.authorization.k8s.io/v1alpha1, Kind=CreateOptions -> v1.CreateOptions rbac.authorization.k8s.io/v1alpha1, Kind=DeleteOptions -> v1.DeleteOptions rbac.authorization.k8s.io/v1alpha1, Kind=ExportOptions -> v1.ExportOptions rbac.authorization.k8s.io/v1alpha1, Kind=GetOptions -> v1.GetOptions rbac.authorization.k8s.io/v1alpha1, Kind=ListOptions -> v1.ListOptions rbac.authorization.k8s.io/v1alpha1, Kind=Role -> v1alpha1.Role rbac.authorization.k8s.io/v1alpha1, Kind=RoleBinding -> v1alpha1.RoleBinding rbac.authorization.k8s.io/v1alpha1, Kind=RoleBindingList -> v1alpha1.RoleBindingList rbac.authorization.k8s.io/v1alpha1, Kind=RoleList -> v1alpha1.RoleList rbac.authorization.k8s.io/v1alpha1, Kind=UpdateOptions -> v1.UpdateOptions rbac.authorization.k8s.io/v1alpha1, Kind=WatchEvent -> v1.WatchEvent rbac.authorization.k8s.io/v1beta1, Kind=ClusterRole -> v1beta1.ClusterRole rbac.authorization.k8s.io/v1beta1, Kind=ClusterRoleBinding -> v1beta1.ClusterRoleBinding rbac.authorization.k8s.io/v1beta1, Kind=ClusterRoleBindingList -> v1beta1.ClusterRoleBindingList rbac.authorization.k8s.io/v1beta1, Kind=ClusterRoleList -> v1beta1.ClusterRoleList rbac.authorization.k8s.io/v1beta1, Kind=CreateOptions -> v1.CreateOptions rbac.authorization.k8s.io/v1beta1, Kind=DeleteOptions -> v1.DeleteOptions rbac.authorization.k8s.io/v1beta1, Kind=ExportOptions -> v1.ExportOptions rbac.authorization.k8s.io/v1beta1, Kind=GetOptions -> v1.GetOptions rbac.authorization.k8s.io/v1beta1, Kind=ListOptions -> v1.ListOptions rbac.authorization.k8s.io/v1beta1, Kind=Role -> v1beta1.Role rbac.authorization.k8s.io/v1beta1, Kind=RoleBinding -> v1beta1.RoleBinding rbac.authorization.k8s.io/v1beta1, Kind=RoleBindingList -> v1beta1.RoleBindingList rbac.authorization.k8s.io/v1beta1, Kind=RoleList -> v1beta1.RoleList rbac.authorization.k8s.io/v1beta1, Kind=UpdateOptions -> v1.UpdateOptions rbac.authorization.k8s.io/v1beta1, Kind=WatchEvent -> v1.WatchEvent route.openshift.io/__internal, Kind=WatchEvent -> v1.InternalEvent route.openshift.io/v1, Kind=CreateOptions -> v1.CreateOptions route.openshift.io/v1, Kind=DeleteOptions -> v1.DeleteOptions route.openshift.io/v1, Kind=ExportOptions -> v1.ExportOptions route.openshift.io/v1, Kind=GetOptions -> v1.GetOptions route.openshift.io/v1, Kind=ListOptions -> v1.ListOptions route.openshift.io/v1, Kind=Route -> v1.Route route.openshift.io/v1, Kind=RouteList -> v1.RouteList route.openshift.io/v1, Kind=UpdateOptions -> v1.UpdateOptions route.openshift.io/v1, Kind=WatchEvent -> v1.WatchEvent scheduling.k8s.io/__internal, Kind=WatchEvent -> v1.InternalEvent scheduling.k8s.io/v1alpha1, Kind=CreateOptions -> v1.CreateOptions scheduling.k8s.io/v1alpha1, Kind=DeleteOptions -> v1.DeleteOptions scheduling.k8s.io/v1alpha1, Kind=ExportOptions -> v1.ExportOptions scheduling.k8s.io/v1alpha1, Kind=GetOptions -> v1.GetOptions scheduling.k8s.io/v1alpha1, Kind=ListOptions -> v1.ListOptions scheduling.k8s.io/v1alpha1, Kind=PriorityClass -> v1alpha1.PriorityClass scheduling.k8s.io/v1alpha1, Kind=PriorityClassList -> v1alpha1.PriorityClassList scheduling.k8s.io/v1alpha1, Kind=UpdateOptions -> v1.UpdateOptions scheduling.k8s.io/v1alpha1, Kind=WatchEvent -> v1.WatchEvent scheduling.k8s.io/v1beta1, Kind=CreateOptions -> v1.CreateOptions scheduling.k8s.io/v1beta1, Kind=DeleteOptions -> v1.DeleteOptions scheduling.k8s.io/v1beta1, Kind=ExportOptions -> v1.ExportOptions scheduling.k8s.io/v1beta1, Kind=GetOptions -> v1.GetOptions scheduling.k8s.io/v1beta1, Kind=ListOptions -> v1.ListOptions scheduling.k8s.io/v1beta1, Kind=PriorityClass -> v1beta1.PriorityClass scheduling.k8s.io/v1beta1, Kind=PriorityClassList -> v1beta1.PriorityClassList scheduling.k8s.io/v1beta1, Kind=UpdateOptions -> v1.UpdateOptions scheduling.k8s.io/v1beta1, Kind=WatchEvent -> v1.WatchEvent security.openshift.io/__internal, Kind=WatchEvent -> v1.InternalEvent security.openshift.io/v1, Kind=CreateOptions -> v1.CreateOptions security.openshift.io/v1, Kind=DeleteOptions -> v1.DeleteOptions security.openshift.io/v1, Kind=ExportOptions -> v1.ExportOptions security.openshift.io/v1, Kind=GetOptions -> v1.GetOptions security.openshift.io/v1, Kind=ListOptions -> v1.ListOptions security.openshift.io/v1, Kind=PodSecurityPolicyReview -> v1.PodSecurityPolicyReview security.openshift.io/v1, Kind=PodSecurityPolicySelfSubjectReview -> v1.PodSecurityPolicySelfSubjectReview security.openshift.io/v1, Kind=PodSecurityPolicySubjectReview -> v1.PodSecurityPolicySubjectReview security.openshift.io/v1, Kind=RangeAllocation -> v1.RangeAllocation security.openshift.io/v1, Kind=RangeAllocationList -> v1.RangeAllocationList security.openshift.io/v1, Kind=SecurityContextConstraints -> v1.SecurityContextConstraints security.openshift.io/v1, Kind=SecurityContextConstraintsList -> v1.SecurityContextConstraintsList security.openshift.io/v1, Kind=UpdateOptions -> v1.UpdateOptions security.openshift.io/v1, Kind=WatchEvent -> v1.WatchEvent servicecertsigner.config.openshift.io/__internal, Kind=WatchEvent -> v1.InternalEvent servicecertsigner.config.openshift.io/v1alpha1, Kind=APIServiceCABundleInjectorConfig -> v1alpha1.APIServiceCABundleInjectorConfig servicecertsigner.config.openshift.io/v1alpha1, Kind=ConfigMapCABundleInjectorConfig -> v1alpha1.ConfigMapCABundleInjectorConfig servicecertsigner.config.openshift.io/v1alpha1, Kind=CreateOptions -> v1.CreateOptions servicecertsigner.config.openshift.io/v1alpha1, Kind=DeleteOptions -> v1.DeleteOptions servicecertsigner.config.openshift.io/v1alpha1, Kind=ExportOptions -> v1.ExportOptions servicecertsigner.config.openshift.io/v1alpha1, Kind=GetOptions -> v1.GetOptions servicecertsigner.config.openshift.io/v1alpha1, Kind=ListOptions -> v1.ListOptions servicecertsigner.config.openshift.io/v1alpha1, Kind=ServiceCertSignerOperatorConfig -> v1alpha1.ServiceCertSignerOperatorConfig servicecertsigner.config.openshift.io/v1alpha1, Kind=ServiceCertSignerOperatorConfigList -> v1alpha1.ServiceCertSignerOperatorConfigList servicecertsigner.config.openshift.io/v1alpha1, Kind=ServiceServingCertSignerConfig -> v1alpha1.ServiceServingCertSignerConfig servicecertsigner.config.openshift.io/v1alpha1, Kind=UpdateOptions -> v1.UpdateOptions servicecertsigner.config.openshift.io/v1alpha1, Kind=WatchEvent -> v1.WatchEvent settings.k8s.io/__internal, Kind=WatchEvent -> v1.InternalEvent settings.k8s.io/v1alpha1, Kind=CreateOptions -> v1.CreateOptions settings.k8s.io/v1alpha1, Kind=DeleteOptions -> v1.DeleteOptions settings.k8s.io/v1alpha1, Kind=ExportOptions -> v1.ExportOptions settings.k8s.io/v1alpha1, Kind=GetOptions -> v1.GetOptions settings.k8s.io/v1alpha1, Kind=ListOptions -> v1.ListOptions settings.k8s.io/v1alpha1, Kind=PodPreset -> v1alpha1.PodPreset settings.k8s.io/v1alpha1, Kind=PodPresetList -> v1alpha1.PodPresetList settings.k8s.io/v1alpha1, Kind=UpdateOptions -> v1.UpdateOptions settings.k8s.io/v1alpha1, Kind=WatchEvent -> v1.WatchEvent storage.k8s.io/__internal, Kind=WatchEvent -> v1.InternalEvent storage.k8s.io/v1, Kind=CreateOptions -> v1.CreateOptions storage.k8s.io/v1, Kind=DeleteOptions -> v1.DeleteOptions storage.k8s.io/v1, Kind=ExportOptions -> v1.ExportOptions storage.k8s.io/v1, Kind=GetOptions -> v1.GetOptions storage.k8s.io/v1, Kind=ListOptions -> v1.ListOptions storage.k8s.io/v1, Kind=StorageClass -> v1.StorageClass storage.k8s.io/v1, Kind=StorageClassList -> v1.StorageClassList storage.k8s.io/v1, Kind=UpdateOptions -> v1.UpdateOptions storage.k8s.io/v1, Kind=WatchEvent -> v1.WatchEvent storage.k8s.io/v1alpha1, Kind=CreateOptions -> v1.CreateOptions storage.k8s.io/v1alpha1, Kind=DeleteOptions -> v1.DeleteOptions storage.k8s.io/v1alpha1, Kind=ExportOptions -> v1.ExportOptions storage.k8s.io/v1alpha1, Kind=GetOptions -> v1.GetOptions storage.k8s.io/v1alpha1, Kind=ListOptions -> v1.ListOptions storage.k8s.io/v1alpha1, Kind=UpdateOptions -> v1.UpdateOptions storage.k8s.io/v1alpha1, Kind=VolumeAttachment -> v1alpha1.VolumeAttachment storage.k8s.io/v1alpha1, Kind=VolumeAttachmentList -> v1alpha1.VolumeAttachmentList storage.k8s.io/v1alpha1, Kind=WatchEvent -> v1.WatchEvent storage.k8s.io/v1beta1, Kind=CreateOptions -> v1.CreateOptions storage.k8s.io/v1beta1, Kind=DeleteOptions -> v1.DeleteOptions storage.k8s.io/v1beta1, Kind=ExportOptions -> v1.ExportOptions storage.k8s.io/v1beta1, Kind=GetOptions -> v1.GetOptions storage.k8s.io/v1beta1, Kind=ListOptions -> v1.ListOptions storage.k8s.io/v1beta1, Kind=StorageClass -> v1beta1.StorageClass storage.k8s.io/v1beta1, Kind=StorageClassList -> v1beta1.StorageClassList storage.k8s.io/v1beta1, Kind=UpdateOptions -> v1.UpdateOptions storage.k8s.io/v1beta1, Kind=VolumeAttachment -> v1beta1.VolumeAttachment storage.k8s.io/v1beta1, Kind=VolumeAttachmentList -> v1beta1.VolumeAttachmentList storage.k8s.io/v1beta1, Kind=WatchEvent -> v1.WatchEvent template.openshift.io/__internal, Kind=WatchEvent -> v1.InternalEvent template.openshift.io/v1, Kind=BrokerTemplateInstance -> v1.BrokerTemplateInstance template.openshift.io/v1, Kind=BrokerTemplateInstanceList -> v1.BrokerTemplateInstanceList template.openshift.io/v1, Kind=CreateOptions -> v1.CreateOptions template.openshift.io/v1, Kind=DeleteOptions -> v1.DeleteOptions template.openshift.io/v1, Kind=ExportOptions -> v1.ExportOptions template.openshift.io/v1, Kind=GetOptions -> v1.GetOptions template.openshift.io/v1, Kind=ListOptions -> v1.ListOptions template.openshift.io/v1, Kind=Template -> v1.Template template.openshift.io/v1, Kind=TemplateInstance -> v1.TemplateInstance template.openshift.io/v1, Kind=TemplateInstanceList -> v1.TemplateInstanceList template.openshift.io/v1, Kind=TemplateList -> v1.TemplateList template.openshift.io/v1, Kind=UpdateOptions -> v1.UpdateOptions template.openshift.io/v1, Kind=WatchEvent -> v1.WatchEvent user.openshift.io/__internal, Kind=WatchEvent -> v1.InternalEvent user.openshift.io/v1, Kind=CreateOptions -> v1.CreateOptions user.openshift.io/v1, Kind=DeleteOptions -> v1.DeleteOptions user.openshift.io/v1, Kind=ExportOptions -> v1.ExportOptions user.openshift.io/v1, Kind=GetOptions -> v1.GetOptions user.openshift.io/v1, Kind=Group -> v1.Group user.openshift.io/v1, Kind=GroupList -> v1.GroupList user.openshift.io/v1, Kind=Identity -> v1.Identity user.openshift.io/v1, Kind=IdentityList -> v1.IdentityList user.openshift.io/v1, Kind=ListOptions -> v1.ListOptions user.openshift.io/v1, Kind=UpdateOptions -> v1.UpdateOptions user.openshift.io/v1, Kind=User -> v1.User user.openshift.io/v1, Kind=UserIdentityMapping -> v1.UserIdentityMapping user.openshift.io/v1, Kind=UserList -> v1.UserList user.openshift.io/v1, Kind=WatchEvent -> v1.WatchEvent webconsole.config.openshift.io/__internal, Kind=WatchEvent -> v1.InternalEvent webconsole.config.openshift.io/v1, Kind=CreateOptions -> v1.CreateOptions webconsole.config.openshift.io/v1, Kind=DeleteOptions -> v1.DeleteOptions webconsole.config.openshift.io/v1, Kind=ExportOptions -> v1.ExportOptions webconsole.config.openshift.io/v1, Kind=GetOptions -> v1.GetOptions webconsole.config.openshift.io/v1, Kind=ListOptions -> v1.ListOptions webconsole.config.openshift.io/v1, Kind=UpdateOptions -> v1.UpdateOptions webconsole.config.openshift.io/v1, Kind=WatchEvent -> v1.WatchEvent webconsole.config.openshift.io/v1, Kind=WebConsoleConfiguration -> v1.WebConsoleConfiguration Dumping GVK ... - /v1, Kind=SecretList - image.openshift.io/v1, Kind=SecretList 2019-03-20T17:39:56.177+0100 INFO cmd my unstructured secrets {"secrets": 488} panic: multiple group-version-kinds associated with type *v1.SecretList, refusing to guess at one goroutine 1 [running]: main.main() /home/jreimann/gobase/controller-runtime-362/src/github.com/ctron/controller-runtime-362/cmd/main.go:106 +0xbd5 Process finished with exit code 2 ~~~
DirectXMan12 commented 5 years ago

hey, sorry about letting this fall through the cracks a bit -- lost track of it.

DirectXMan12 commented 5 years ago

Ok, so, I'm decently certain that this is actually an OpenShift bug, and here's why:

It's certainly possible to have two the same Go type associated with different GVKs, but it's almost certainly not what you meant. In controller-runtime, we assume that Group-Version-Kind is unique, and that, with the exception of historical weirdness around metav1.XYZMeta, the combination of package and type is unique. That is: there's a one-to-one mapping between Group-Version-Kind and "package".Type. That's a relatively sane assumption (IMO) that is relied upon across controller-runtime, and also almost certainly in a few spots in k/k. The only place I know of where that's broken in the existing kube ecosystem is for a few metav1 spots, and all of those are labeled "we should fix this, it's not what we're supposed to be doing" (and aren't actually top-level objects).

OpenShift is breaking this assumption here: https://github.com/openshift/api/blob/b772cc93d057f30f40f93347a043c3bcef11d268/image/v1/register.go#L48

where it's adding the existing corev1.SecretList type to a non corev1 API group. It looks like it mainly exists to generate a client for a subresource, but in that case the object shouldn't be re-added to a new API group -- it should simply be re-used from the old one, and the scheme for that client should have both API groups included. Either that, or type SecretList corev1.SecretList in that API group.

ctron commented 5 years ago

@DirectXMan12 Thanks for investigating this. I opened a new issue with the OpenShift API, and referenced your findings. Maybe we can find a proper solution then.

deads2k commented 5 years ago

Cross posting from https://github.com/openshift/api/issues/270

In general, cross registering types is an acceptable thing to do. That's why when the scheme maps them, it allows for multiple matches https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apimachinery/pkg/runtime/scheme.go#L236 .

It allows serialization of an existing type into a new group. We make use of cross registration for several types in k8s.io/apimachinery/apis/meta/v1 and it is a generically acceptable concept.

DirectXMan12 commented 5 years ago

We make use of cross registration for several types in k8s.io/apimachinery/apis/meta/v1 and it is a generically acceptable concept.

I was under the impression that most of the cross-mapping from meta/v1 had "this is bad, we should fix it" comments on them (some of those lines do indeed seem to have been refactored away), and that in general, cross-registration was undesirable. Is that not the case? It's unclear to me why you'd want to do it in most cases, especially since you could just do a newtype and preserve the nice property that any given type has a single associated GVK.

At any rate, we could make it so that we fall back to GVK from the GVK field, if we can't determine conclusively from the type, but this still feels to me like OpenShift is doing things that it shouldn't be (in fact, it's not clear to me why this subresource isn't just returning APIVersion: v1, Kind: SecretList (cross-group subresources, like we do for scale)).

DirectXMan12 commented 5 years ago

At any rate, we could make it so that we fall back to GVK from the GVK field, if we can't determine conclusively from the type

Although, I feel like this would lead to weird/unexpected behavior in certain cases (especially when combining controllers into a single manager), so I'd still prefer to try and just get a fix in OpenShift.

deads2k commented 5 years ago

I was under the impression that most of the cross-mapping from meta/v1 had "this is bad, we should fix it" comments on them (some of those lines do indeed seem to have been refactored away), and that in general, cross-registration was undesirable. Is that not the case? It's unclear to me why you'd want to do it in most cases, especially since you could just do a newtype and preserve the nice property that any given type has a single associated GVK.

Cross registration is a desired feature. It is the simplest way to transition a mistaken name and to allow multiple potential mappings. Consider the migration case, the meta case, or the old apps case. Being able to cross-register is a feature and not an undesireable one.

smarterclayton commented 5 years ago

I was under the impression that most of the cross-mapping from meta/v1 had "this is bad, we should fix it" comments on them (some of those lines do indeed seem to have been refactored away)

As the person who put a lot of these comments in, they're not about cross registration of types moving groups, they're about cross registration of meta types being registered in all groups. Not the same use case

GVK is unique re Openshift

No, we never intended that in Kube. The core runtime code explicitly and completely decouples resources from kinds. Only discovery is allowed to make up rules about resource to Kind mappings. You may not assume that Kind is only exposed on one aggregated API endpoint.

smarterclayton commented 5 years ago

That is: there's a one-to-one mapping between Group-Version-Kind and "package".Type. That's a relatively sane assumption (IMO) that is relied upon across controller-runtime, and also almost certainly in a few spots in k/k.

If it's relied on in k/k, that's broken code.

smarterclayton commented 5 years ago

Here's the relevant description in runtime/scheme.go

// In a Scheme, a Type is a particular Go struct, a Version is a point-in-time // identifier for a particular representation of that Type (typically backwards // compatible), a Kind is the unique name for that Type within the Version, and a // Group identifies a set of Versions, Kinds, and Types that evolve over time. An // Unversioned Type is one that is not yet formally bound to a type and is promised // to be backwards compatible (effectively a "v1" of a Type that does not expect // to break in the future).

and

// typeToGroupVersion allows one to find metadata for a given go object. // The reflect.Type we index by should not be a pointer. typeToGVK map[reflect.Type][]schema.GroupVersionKind

All types have a canonical GVK (primary) but may be registered multiple times and callers are not allowed to assume Go type == kind at this current time.

We have discussed, but not allowed, deviations from this in apimachinery. To change the definition of GVK/GVR/type mappings we'd need to have a KEP to alter it.

DirectXMan12 commented 5 years ago

It is the simplest way to transition a mistaken name and to allow multiple potential mappings

Type aliases seem just as simple, but I could be misunderstanding what you're saying.

You may not assume that Kind is only exposed on one aggregated API endpoint.

We don't. We use the primary RESTMapping, same as kubectl xyz -f does. Both rely on the principal "any given GVK that's not a subresource that you can actually perform CRUD on has a primary restmapping that's fine to always use". If that weren't the case, a lot of kubectl stuff would break, AFAICT.

If it's relied on in k/k, that's broken code.

Right or wrong, unless I'm misreading, lots of things assume as such by blindly using the first returned GVK (there's a ton more -- most invocations of ObjectKinds do this). My quick survey probably missed a few with preconditions that make this moot, but it seems like blindly assuming the first GVK is the correct one when multiple are present is suspect -- it assumes that the first added to the Scheme is always correct, which seems hard to know.

The only (AFAICT) difference from what we do is that we bail instead of trusting the first GVK to be the right one. Is there something I've missed here?

We have discussed, but not allowed, deviations from this in apimachinery. To change the definition of GVK/GVR/type mappings we'd need to have a KEP to alter it.

Is that a KEP you'd be opposed to? I still posit that "type corresponds to GVK" is a sane assertion, so I'd be happy to write up that KEP.

fejta-bot commented 5 years ago

Issues go stale after 90d of inactivity. Mark the issue as fresh with /remove-lifecycle stale. Stale issues rot after an additional 30d of inactivity and eventually close.

If this issue is safe to close now please do so with /close.

Send feedback to sig-testing, kubernetes/test-infra and/or fejta. /lifecycle stale

fejta-bot commented 5 years ago

Stale issues rot after 30d of inactivity. Mark the issue as fresh with /remove-lifecycle rotten. Rotten issues close after an additional 30d of inactivity.

If this issue is safe to close now please do so with /close.

Send feedback to sig-testing, kubernetes/test-infra and/or fejta. /lifecycle rotten

ctron commented 5 years ago

This issue is still an issue. It is not fixed. It is still a problem.

DirectXMan12 commented 5 years ago

/lifecycle frozen

the bot's just being overly agressive

vincepri commented 4 years ago

/priority awaiting-more-evidence

From backlog grooming: this issue needs to be triaged again, if it's not reproducible let's close it. In general, controller-runtime might not be the best place for a fix.

fejta-bot commented 4 years ago

Issues go stale after 90d of inactivity. Mark the issue as fresh with /remove-lifecycle stale. Stale issues rot after an additional 30d of inactivity and eventually close.

If this issue is safe to close now please do so with /close.

Send feedback to sig-testing, kubernetes/test-infra and/or fejta. /lifecycle stale

fejta-bot commented 4 years ago

Stale issues rot after 30d of inactivity. Mark the issue as fresh with /remove-lifecycle rotten. Rotten issues close after an additional 30d of inactivity.

If this issue is safe to close now please do so with /close.

Send feedback to sig-testing, kubernetes/test-infra and/or fejta. /lifecycle rotten

fejta-bot commented 4 years ago

Rotten issues close after 30d of inactivity. Reopen the issue with /reopen. Mark the issue as fresh with /remove-lifecycle rotten.

Send feedback to sig-testing, kubernetes/test-infra and/or fejta. /close

k8s-ci-robot commented 4 years ago

@fejta-bot: Closing this issue.

In response to [this](https://github.com/kubernetes-sigs/controller-runtime/issues/362#issuecomment-660705142): >Rotten issues close after 30d of inactivity. >Reopen the issue with `/reopen`. >Mark the issue as fresh with `/remove-lifecycle rotten`. > >Send feedback to sig-testing, kubernetes/test-infra and/or [fejta](https://github.com/fejta). >/close Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md). If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
alvaroaleman commented 3 years ago

/reopen

This is still unsolved, adding the imagev1 scheme breaks secretList.

k8s-ci-robot commented 3 years ago

@alvaroaleman: Reopened this issue.

In response to [this](https://github.com/kubernetes-sigs/controller-runtime/issues/362#issuecomment-723260097): >/reopen > >This is still unsolved, adding the imagev1 scheme breaks secretList. Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md). If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
alvaroaleman commented 3 years ago

So I fixed this instance of the problem in openshift/api#780 by re-redefining the type (type a b) (which is a different thing from aliasing a type, which doesn't help with this issue at all). That being said, the issue is that we make assumptions apimachinery doesn't guarantee, which happens to work most of the time and sometimes it doesn't. For those cases we should probably:

fejta-bot commented 3 years ago

Rotten issues close after 30d of inactivity. Reopen the issue with /reopen. Mark the issue as fresh with /remove-lifecycle rotten.

Send feedback to sig-testing, kubernetes/test-infra and/or fejta. /close

k8s-ci-robot commented 3 years ago

@fejta-bot: Closing this issue.

In response to [this](https://github.com/kubernetes-sigs/controller-runtime/issues/362#issuecomment-751284807): >Rotten issues close after 30d of inactivity. >Reopen the issue with `/reopen`. >Mark the issue as fresh with `/remove-lifecycle rotten`. > >Send feedback to sig-testing, kubernetes/test-infra and/or [fejta](https://github.com/fejta). >/close Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md). If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
justinsb commented 1 year ago

I was thinking about this. k/k might not assume that one Go type maps uniquely to one GVK, but it seems that CR does. A 1:1 mapping is certainly easier for users of the go types. I think the type redefinition suggested here makes it easy for people authoring types, even while reusing the upstream definitions.

So, should we simply say that not all generated go code is compatible with controller-runtime? CR users always have the option of using unstructured, but I think there are a myriad of ways to generate types that will crash controller-runtime, and I don't think we can or should aim to support them all.

(Aside: should we turn off fejtabot in this repo? I'm not convinced it adds signal, it definitely adds noise)

alvaroaleman commented 1 year ago

@justinsb in theory there are some ways we could improve this, for example we could allow ppl to explicitly set typemeta and then use that information in non-unstructured objects. Today, we simply use the scheme and directly bail out if we don't get exactly one result back.

The issue here is that in practise this just hasn't happened often enough for anyone to bother to improve this in controller-runtime, but not that we'd be opposed to such a change.

alvaroaleman commented 1 year ago

but I think there are a myriad of ways to generate types that will crash controller-runtime, and I don't think we can or should aim to support them all.

I missed this part before. There are? Do you have one or more examples? The issue here causes an error but not a crash.

justinsb commented 1 year ago

I mean, trivially, I can func init() { panic() } :-) I can hand-code a deep-copy method and do it more subtly. We could debate about whether X should be allowed or Y should be allowed, but we could also just say that when you link in arbitrary go code there are limits to the guarantees we can make.

The idea that a go type maps to a GVK is (IMO) one of the things that makes controller-runtime so much easier to use than the raw libraries, so I have a hard time thinking how we can solve this while keeping what makes CR so useful. I can imagine always populating the GVK on a read and then requiring it on an update, but we'd still have problems on a create operation (it would be a user-facing breaking change to require a GVK on typed objects for create, IIUC).

vincepri commented 1 year ago

/reopen

k8s-ci-robot commented 1 year ago

@vincepri: Reopened this issue.

In response to [this](https://github.com/kubernetes-sigs/controller-runtime/issues/362#issuecomment-1428331849): >/reopen Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md). If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
vincepri commented 1 year ago

/lifecycle frozen

vincepri commented 1 year ago

PTAL: https://github.com/kubernetes-sigs/controller-runtime/pull/2192

alvaroaleman commented 1 year ago

This got fixed in https://github.com/kubernetes-sigs/controller-runtime/pull/2192