mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-20 18:31:15 +00:00
Merge pull request #113542 from ardaguclu/fix-shortname-disperancy
Set singular names for core types to pass to discovery
This commit is contained in:
commit
12c71fdf1c
@ -42,6 +42,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
|
||||
return obj.(*admissionregistration.MutatingWebhookConfiguration).Name, nil
|
||||
},
|
||||
DefaultQualifiedResource: admissionregistration.Resource("mutatingwebhookconfigurations"),
|
||||
SingularQualifiedResource: admissionregistration.Resource("mutatingwebhookconfiguration"),
|
||||
|
||||
CreateStrategy: mutatingwebhookconfiguration.Strategy,
|
||||
UpdateStrategy: mutatingwebhookconfiguration.Strategy,
|
||||
|
@ -48,6 +48,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter, authorizer authorizer.Authori
|
||||
return obj.(*admissionregistration.ValidatingAdmissionPolicy).Name, nil
|
||||
},
|
||||
DefaultQualifiedResource: groupResource,
|
||||
SingularQualifiedResource: admissionregistration.Resource("validatingadmissionpolicy"),
|
||||
|
||||
CreateStrategy: strategy,
|
||||
UpdateStrategy: strategy,
|
||||
|
@ -51,6 +51,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter, authorizer authorizer.Authori
|
||||
return obj.(*admissionregistration.ValidatingAdmissionPolicyBinding).Name, nil
|
||||
},
|
||||
DefaultQualifiedResource: groupResource,
|
||||
SingularQualifiedResource: admissionregistration.Resource("validatingadmissionpolicybinding"),
|
||||
|
||||
CreateStrategy: strategy,
|
||||
UpdateStrategy: strategy,
|
||||
|
@ -42,6 +42,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
|
||||
return obj.(*admissionregistration.ValidatingWebhookConfiguration).Name, nil
|
||||
},
|
||||
DefaultQualifiedResource: admissionregistration.Resource("validatingwebhookconfigurations"),
|
||||
SingularQualifiedResource: admissionregistration.Resource("validatingwebhookconfiguration"),
|
||||
|
||||
CreateStrategy: validatingwebhookconfiguration.Strategy,
|
||||
UpdateStrategy: validatingwebhookconfiguration.Strategy,
|
||||
|
@ -46,6 +46,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) {
|
||||
return obj.(*apiserverinternal.StorageVersion).Name, nil
|
||||
},
|
||||
DefaultQualifiedResource: apiserverinternal.Resource("storageversions"),
|
||||
SingularQualifiedResource: apiserverinternal.Resource("storageversion"),
|
||||
|
||||
CreateStrategy: strategy.Strategy,
|
||||
UpdateStrategy: strategy.Strategy,
|
||||
|
@ -38,6 +38,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
|
||||
NewFunc: func() runtime.Object { return &apps.ControllerRevision{} },
|
||||
NewListFunc: func() runtime.Object { return &apps.ControllerRevisionList{} },
|
||||
DefaultQualifiedResource: apps.Resource("controllerrevisions"),
|
||||
SingularQualifiedResource: apps.Resource("controllerrevision"),
|
||||
|
||||
CreateStrategy: controllerrevision.Strategy,
|
||||
UpdateStrategy: controllerrevision.Strategy,
|
||||
|
@ -43,6 +43,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) {
|
||||
NewFunc: func() runtime.Object { return &apps.DaemonSet{} },
|
||||
NewListFunc: func() runtime.Object { return &apps.DaemonSetList{} },
|
||||
DefaultQualifiedResource: apps.Resource("daemonsets"),
|
||||
SingularQualifiedResource: apps.Resource("daemonset"),
|
||||
|
||||
CreateStrategy: daemonset.Strategy,
|
||||
UpdateStrategy: daemonset.Strategy,
|
||||
|
@ -95,6 +95,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, *Rollbac
|
||||
NewFunc: func() runtime.Object { return &apps.Deployment{} },
|
||||
NewListFunc: func() runtime.Object { return &apps.DeploymentList{} },
|
||||
DefaultQualifiedResource: apps.Resource("deployments"),
|
||||
SingularQualifiedResource: apps.Resource("deployment"),
|
||||
|
||||
CreateStrategy: deployment.Strategy,
|
||||
UpdateStrategy: deployment.Strategy,
|
||||
|
@ -90,6 +90,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) {
|
||||
NewListFunc: func() runtime.Object { return &apps.ReplicaSetList{} },
|
||||
PredicateFunc: replicaset.MatchReplicaSet,
|
||||
DefaultQualifiedResource: apps.Resource("replicasets"),
|
||||
SingularQualifiedResource: apps.Resource("replicaset"),
|
||||
|
||||
CreateStrategy: replicaset.Strategy,
|
||||
UpdateStrategy: replicaset.Strategy,
|
||||
|
@ -87,6 +87,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) {
|
||||
NewFunc: func() runtime.Object { return &apps.StatefulSet{} },
|
||||
NewListFunc: func() runtime.Object { return &apps.StatefulSetList{} },
|
||||
DefaultQualifiedResource: apps.Resource("statefulsets"),
|
||||
SingularQualifiedResource: apps.Resource("statefulset"),
|
||||
|
||||
CreateStrategy: statefulset.Strategy,
|
||||
UpdateStrategy: statefulset.Strategy,
|
||||
|
@ -93,3 +93,9 @@ func (r *REST) Create(ctx context.Context, obj runtime.Object, createValidation
|
||||
|
||||
return selfSAR, nil
|
||||
}
|
||||
|
||||
var _ rest.SingularNameProvider = &REST{}
|
||||
|
||||
func (r *REST) GetSingularName() string {
|
||||
return "selfsubjectrulesreview"
|
||||
}
|
||||
|
@ -60,6 +60,12 @@ func (r *REST) Destroy() {
|
||||
// here explicitly.
|
||||
}
|
||||
|
||||
var _ rest.SingularNameProvider = &REST{}
|
||||
|
||||
func (r *REST) GetSingularName() string {
|
||||
return "tokenreview"
|
||||
}
|
||||
|
||||
func (r *REST) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) {
|
||||
tokenReview, ok := obj.(*authentication.TokenReview)
|
||||
if !ok {
|
||||
|
@ -53,6 +53,12 @@ func (r *REST) Destroy() {
|
||||
// here explicitly.
|
||||
}
|
||||
|
||||
var _ rest.SingularNameProvider = &REST{}
|
||||
|
||||
func (r *REST) GetSingularName() string {
|
||||
return "localsubjectaccessreview"
|
||||
}
|
||||
|
||||
func (r *REST) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) {
|
||||
localSubjectAccessReview, ok := obj.(*authorizationapi.LocalSubjectAccessReview)
|
||||
if !ok {
|
||||
|
@ -53,6 +53,12 @@ func (r *REST) Destroy() {
|
||||
// here explicitly.
|
||||
}
|
||||
|
||||
var _ rest.SingularNameProvider = &REST{}
|
||||
|
||||
func (r *REST) GetSingularName() string {
|
||||
return "selfsubjectaccessreview"
|
||||
}
|
||||
|
||||
func (r *REST) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) {
|
||||
selfSAR, ok := obj.(*authorizationapi.SelfSubjectAccessReview)
|
||||
if !ok {
|
||||
|
@ -95,6 +95,12 @@ func (r *REST) Create(ctx context.Context, obj runtime.Object, createValidation
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
var _ rest.SingularNameProvider = &REST{}
|
||||
|
||||
func (r *REST) GetSingularName() string {
|
||||
return "selfsubjectrulesreview"
|
||||
}
|
||||
|
||||
func getResourceRules(infos []authorizer.ResourceRuleInfo) []authorizationapi.ResourceRule {
|
||||
rules := make([]authorizationapi.ResourceRule, len(infos))
|
||||
for i, info := range infos {
|
||||
|
@ -52,6 +52,12 @@ func (r *REST) Destroy() {
|
||||
// here explicitly.
|
||||
}
|
||||
|
||||
var _ rest.SingularNameProvider = &REST{}
|
||||
|
||||
func (r *REST) GetSingularName() string {
|
||||
return "subjectaccessreview"
|
||||
}
|
||||
|
||||
func (r *REST) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) {
|
||||
subjectAccessReview, ok := obj.(*authorizationapi.SubjectAccessReview)
|
||||
if !ok {
|
||||
|
@ -43,6 +43,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) {
|
||||
NewFunc: func() runtime.Object { return &autoscaling.HorizontalPodAutoscaler{} },
|
||||
NewListFunc: func() runtime.Object { return &autoscaling.HorizontalPodAutoscalerList{} },
|
||||
DefaultQualifiedResource: autoscaling.Resource("horizontalpodautoscalers"),
|
||||
SingularQualifiedResource: autoscaling.Resource("horizontalpodautoscaler"),
|
||||
|
||||
CreateStrategy: horizontalpodautoscaler.Strategy,
|
||||
UpdateStrategy: horizontalpodautoscaler.Strategy,
|
||||
|
@ -43,6 +43,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) {
|
||||
NewFunc: func() runtime.Object { return &batch.CronJob{} },
|
||||
NewListFunc: func() runtime.Object { return &batch.CronJobList{} },
|
||||
DefaultQualifiedResource: batch.Resource("cronjobs"),
|
||||
SingularQualifiedResource: batch.Resource("cronjob"),
|
||||
|
||||
CreateStrategy: cronjob.Strategy,
|
||||
UpdateStrategy: cronjob.Strategy,
|
||||
|
@ -68,6 +68,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) {
|
||||
NewListFunc: func() runtime.Object { return &batch.JobList{} },
|
||||
PredicateFunc: job.MatchJob,
|
||||
DefaultQualifiedResource: batch.Resource("jobs"),
|
||||
SingularQualifiedResource: batch.Resource("job"),
|
||||
|
||||
CreateStrategy: job.Strategy,
|
||||
UpdateStrategy: job.Strategy,
|
||||
|
@ -43,6 +43,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, *Approva
|
||||
NewFunc: func() runtime.Object { return &certificates.CertificateSigningRequest{} },
|
||||
NewListFunc: func() runtime.Object { return &certificates.CertificateSigningRequestList{} },
|
||||
DefaultQualifiedResource: certificates.Resource("certificatesigningrequests"),
|
||||
SingularQualifiedResource: certificates.Resource("certificatesigningrequest"),
|
||||
|
||||
CreateStrategy: csrregistry.Strategy,
|
||||
UpdateStrategy: csrregistry.Strategy,
|
||||
|
@ -38,6 +38,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
|
||||
NewFunc: func() runtime.Object { return &coordinationapi.Lease{} },
|
||||
NewListFunc: func() runtime.Object { return &coordinationapi.LeaseList{} },
|
||||
DefaultQualifiedResource: coordinationapi.Resource("leases"),
|
||||
SingularQualifiedResource: coordinationapi.Resource("lease"),
|
||||
|
||||
CreateStrategy: lease.Strategy,
|
||||
UpdateStrategy: lease.Strategy,
|
||||
|
@ -58,6 +58,12 @@ func (rs *REST) New() runtime.Object {
|
||||
return &api.ComponentStatus{}
|
||||
}
|
||||
|
||||
var _ rest.SingularNameProvider = &REST{}
|
||||
|
||||
func (rs *REST) GetSingularName() string {
|
||||
return "componentstatus"
|
||||
}
|
||||
|
||||
// Destroy cleans up resources on shutdown.
|
||||
func (r *REST) Destroy() {
|
||||
// Given no underlying store, we don't destroy anything
|
||||
|
@ -41,6 +41,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
|
||||
NewListFunc: func() runtime.Object { return &api.ConfigMapList{} },
|
||||
PredicateFunc: configmap.Matcher,
|
||||
DefaultQualifiedResource: api.Resource("configmaps"),
|
||||
SingularQualifiedResource: api.Resource("configmap"),
|
||||
|
||||
CreateStrategy: configmap.Strategy,
|
||||
UpdateStrategy: configmap.Strategy,
|
||||
|
@ -39,6 +39,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
|
||||
NewFunc: func() runtime.Object { return &api.Endpoints{} },
|
||||
NewListFunc: func() runtime.Object { return &api.EndpointsList{} },
|
||||
DefaultQualifiedResource: api.Resource("endpoints"),
|
||||
SingularQualifiedResource: api.Resource("endpoints"),
|
||||
|
||||
CreateStrategy: endpoint.Strategy,
|
||||
UpdateStrategy: endpoint.Strategy,
|
||||
|
@ -43,6 +43,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter, ttl uint64) (*REST, error) {
|
||||
return ttl, nil
|
||||
},
|
||||
DefaultQualifiedResource: api.Resource("events"),
|
||||
SingularQualifiedResource: api.Resource("event"),
|
||||
|
||||
CreateStrategy: event.Strategy,
|
||||
UpdateStrategy: event.Strategy,
|
||||
|
@ -36,6 +36,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
|
||||
NewFunc: func() runtime.Object { return &api.LimitRange{} },
|
||||
NewListFunc: func() runtime.Object { return &api.LimitRangeList{} },
|
||||
DefaultQualifiedResource: api.Resource("limitranges"),
|
||||
SingularQualifiedResource: api.Resource("limitrange"),
|
||||
|
||||
CreateStrategy: limitrange.Strategy,
|
||||
UpdateStrategy: limitrange.Strategy,
|
||||
|
@ -63,6 +63,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, *Finaliz
|
||||
NewListFunc: func() runtime.Object { return &api.NamespaceList{} },
|
||||
PredicateFunc: namespace.MatchNamespace,
|
||||
DefaultQualifiedResource: api.Resource("namespaces"),
|
||||
SingularQualifiedResource: api.Resource("namespace"),
|
||||
|
||||
CreateStrategy: namespace.Strategy,
|
||||
UpdateStrategy: namespace.Strategy,
|
||||
@ -94,6 +95,12 @@ func (r *REST) NamespaceScoped() bool {
|
||||
return r.store.NamespaceScoped()
|
||||
}
|
||||
|
||||
var _ rest.SingularNameProvider = &REST{}
|
||||
|
||||
func (r *REST) GetSingularName() string {
|
||||
return r.store.GetSingularName()
|
||||
}
|
||||
|
||||
func (r *REST) New() runtime.Object {
|
||||
return r.store.New()
|
||||
}
|
||||
|
@ -100,6 +100,7 @@ func NewStorage(optsGetter generic.RESTOptionsGetter, kubeletClientConfig client
|
||||
NewListFunc: func() runtime.Object { return &api.NodeList{} },
|
||||
PredicateFunc: node.MatchNode,
|
||||
DefaultQualifiedResource: api.Resource("nodes"),
|
||||
SingularQualifiedResource: api.Resource("node"),
|
||||
|
||||
CreateStrategy: node.Strategy,
|
||||
UpdateStrategy: node.Strategy,
|
||||
|
@ -44,6 +44,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) {
|
||||
NewListFunc: func() runtime.Object { return &api.PersistentVolumeList{} },
|
||||
PredicateFunc: persistentvolume.MatchPersistentVolumes,
|
||||
DefaultQualifiedResource: api.Resource("persistentvolumes"),
|
||||
SingularQualifiedResource: api.Resource("persistentvolume"),
|
||||
|
||||
CreateStrategy: persistentvolume.Strategy,
|
||||
UpdateStrategy: persistentvolume.Strategy,
|
||||
|
@ -45,6 +45,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) {
|
||||
NewListFunc: func() runtime.Object { return &api.PersistentVolumeClaimList{} },
|
||||
PredicateFunc: persistentvolumeclaim.MatchPersistentVolumeClaim,
|
||||
DefaultQualifiedResource: api.Resource("persistentvolumeclaims"),
|
||||
SingularQualifiedResource: api.Resource("persistentvolumeclaim"),
|
||||
|
||||
CreateStrategy: persistentvolumeclaim.Strategy,
|
||||
UpdateStrategy: persistentvolumeclaim.Strategy,
|
||||
|
@ -77,6 +77,7 @@ func NewStorage(optsGetter generic.RESTOptionsGetter, k client.ConnectionInfoGet
|
||||
NewListFunc: func() runtime.Object { return &api.PodList{} },
|
||||
PredicateFunc: registrypod.MatchPod,
|
||||
DefaultQualifiedResource: api.Resource("pods"),
|
||||
SingularQualifiedResource: api.Resource("pod"),
|
||||
|
||||
CreateStrategy: registrypod.Strategy,
|
||||
UpdateStrategy: registrypod.Strategy,
|
||||
@ -288,6 +289,10 @@ func (r *LegacyBindingREST) Create(ctx context.Context, obj runtime.Object, crea
|
||||
return r.bindingRest.Create(ctx, metadata.GetName(), obj, createValidation, options)
|
||||
}
|
||||
|
||||
func (r *LegacyBindingREST) GetSingularName() string {
|
||||
return "binding"
|
||||
}
|
||||
|
||||
// StatusREST implements the REST endpoint for changing the status of a pod.
|
||||
type StatusREST struct {
|
||||
store *genericregistry.Store
|
||||
|
@ -38,6 +38,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
|
||||
NewFunc: func() runtime.Object { return &api.PodTemplate{} },
|
||||
NewListFunc: func() runtime.Object { return &api.PodTemplateList{} },
|
||||
DefaultQualifiedResource: api.Resource("podtemplates"),
|
||||
SingularQualifiedResource: api.Resource("podtemplate"),
|
||||
|
||||
CreateStrategy: podtemplate.Strategy,
|
||||
UpdateStrategy: podtemplate.Strategy,
|
||||
|
@ -86,6 +86,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) {
|
||||
NewListFunc: func() runtime.Object { return &api.ReplicationControllerList{} },
|
||||
PredicateFunc: replicationcontroller.MatchController,
|
||||
DefaultQualifiedResource: api.Resource("replicationcontrollers"),
|
||||
SingularQualifiedResource: api.Resource("replicationcontroller"),
|
||||
|
||||
CreateStrategy: replicationcontroller.Strategy,
|
||||
UpdateStrategy: replicationcontroller.Strategy,
|
||||
|
@ -43,6 +43,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) {
|
||||
NewFunc: func() runtime.Object { return &api.ResourceQuota{} },
|
||||
NewListFunc: func() runtime.Object { return &api.ResourceQuotaList{} },
|
||||
DefaultQualifiedResource: api.Resource("resourcequotas"),
|
||||
SingularQualifiedResource: api.Resource("resourcequota"),
|
||||
|
||||
CreateStrategy: resourcequota.Strategy,
|
||||
UpdateStrategy: resourcequota.Strategy,
|
||||
|
@ -40,6 +40,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
|
||||
NewListFunc: func() runtime.Object { return &api.SecretList{} },
|
||||
PredicateFunc: secret.Matcher,
|
||||
DefaultQualifiedResource: api.Resource("secrets"),
|
||||
SingularQualifiedResource: api.Resource("secret"),
|
||||
|
||||
CreateStrategy: secret.Strategy,
|
||||
UpdateStrategy: secret.Strategy,
|
||||
|
@ -89,6 +89,7 @@ func NewREST(
|
||||
NewFunc: func() runtime.Object { return &api.Service{} },
|
||||
NewListFunc: func() runtime.Object { return &api.ServiceList{} },
|
||||
DefaultQualifiedResource: api.Resource("services"),
|
||||
SingularQualifiedResource: api.Resource("service"),
|
||||
ReturnDeletedObject: true,
|
||||
|
||||
CreateStrategy: svcreg.Strategy,
|
||||
|
@ -44,6 +44,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter, issuer token.TokenGenerator,
|
||||
NewFunc: func() runtime.Object { return &api.ServiceAccount{} },
|
||||
NewListFunc: func() runtime.Object { return &api.ServiceAccountList{} },
|
||||
DefaultQualifiedResource: api.Resource("serviceaccounts"),
|
||||
SingularQualifiedResource: api.Resource("serviceaccount"),
|
||||
|
||||
CreateStrategy: serviceaccount.Strategy,
|
||||
UpdateStrategy: serviceaccount.Strategy,
|
||||
|
@ -38,6 +38,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
|
||||
NewFunc: func() runtime.Object { return &discovery.EndpointSlice{} },
|
||||
NewListFunc: func() runtime.Object { return &discovery.EndpointSliceList{} },
|
||||
DefaultQualifiedResource: discovery.Resource("endpointslices"),
|
||||
SingularQualifiedResource: discovery.Resource("endpointslice"),
|
||||
|
||||
CreateStrategy: endpointslice.Strategy,
|
||||
UpdateStrategy: endpointslice.Strategy,
|
||||
|
@ -49,6 +49,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) {
|
||||
NewFunc: func() runtime.Object { return &flowcontrol.FlowSchema{} },
|
||||
NewListFunc: func() runtime.Object { return &flowcontrol.FlowSchemaList{} },
|
||||
DefaultQualifiedResource: flowcontrol.Resource("flowschemas"),
|
||||
SingularQualifiedResource: flowcontrol.Resource("flowschema"),
|
||||
|
||||
CreateStrategy: flowschema.Strategy,
|
||||
UpdateStrategy: flowschema.Strategy,
|
||||
|
@ -49,6 +49,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) {
|
||||
NewFunc: func() runtime.Object { return &flowcontrol.PriorityLevelConfiguration{} },
|
||||
NewListFunc: func() runtime.Object { return &flowcontrol.PriorityLevelConfigurationList{} },
|
||||
DefaultQualifiedResource: flowcontrol.Resource("prioritylevelconfigurations"),
|
||||
SingularQualifiedResource: flowcontrol.Resource("prioritylevelconfiguration"),
|
||||
|
||||
CreateStrategy: prioritylevelconfiguration.Strategy,
|
||||
UpdateStrategy: prioritylevelconfiguration.Strategy,
|
||||
|
@ -39,6 +39,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
|
||||
NewFunc: func() runtime.Object { return &networkingapi.ClusterCIDR{} },
|
||||
NewListFunc: func() runtime.Object { return &networkingapi.ClusterCIDRList{} },
|
||||
DefaultQualifiedResource: networkingapi.Resource("clustercidrs"),
|
||||
SingularQualifiedResource: networkingapi.Resource("clustercidr"),
|
||||
|
||||
CreateStrategy: clustercidr.Strategy,
|
||||
UpdateStrategy: clustercidr.Strategy,
|
||||
|
@ -43,6 +43,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) {
|
||||
NewFunc: func() runtime.Object { return &networking.Ingress{} },
|
||||
NewListFunc: func() runtime.Object { return &networking.IngressList{} },
|
||||
DefaultQualifiedResource: networking.Resource("ingresses"),
|
||||
SingularQualifiedResource: networking.Resource("ingress"),
|
||||
|
||||
CreateStrategy: ingress.Strategy,
|
||||
UpdateStrategy: ingress.Strategy,
|
||||
|
@ -38,6 +38,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
|
||||
NewFunc: func() runtime.Object { return &networking.IngressClass{} },
|
||||
NewListFunc: func() runtime.Object { return &networking.IngressClassList{} },
|
||||
DefaultQualifiedResource: networking.Resource("ingressclasses"),
|
||||
SingularQualifiedResource: networking.Resource("ingressclass"),
|
||||
|
||||
CreateStrategy: ingressclass.Strategy,
|
||||
UpdateStrategy: ingressclass.Strategy,
|
||||
|
@ -44,6 +44,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) {
|
||||
NewFunc: func() runtime.Object { return &networkingapi.NetworkPolicy{} },
|
||||
NewListFunc: func() runtime.Object { return &networkingapi.NetworkPolicyList{} },
|
||||
DefaultQualifiedResource: networkingapi.Resource("networkpolicies"),
|
||||
SingularQualifiedResource: networkingapi.Resource("networkpolicy"),
|
||||
|
||||
CreateStrategy: networkpolicy.Strategy,
|
||||
UpdateStrategy: networkpolicy.Strategy,
|
||||
|
@ -41,6 +41,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
|
||||
return obj.(*node.RuntimeClass).Name, nil
|
||||
},
|
||||
DefaultQualifiedResource: node.Resource("runtimeclasses"),
|
||||
SingularQualifiedResource: node.Resource("runtimeclass"),
|
||||
|
||||
CreateStrategy: runtimeclass.Strategy,
|
||||
UpdateStrategy: runtimeclass.Strategy,
|
||||
|
@ -43,6 +43,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) {
|
||||
NewFunc: func() runtime.Object { return &policyapi.PodDisruptionBudget{} },
|
||||
NewListFunc: func() runtime.Object { return &policyapi.PodDisruptionBudgetList{} },
|
||||
DefaultQualifiedResource: policyapi.Resource("poddisruptionbudgets"),
|
||||
SingularQualifiedResource: policyapi.Resource("poddisruptionbudget"),
|
||||
|
||||
CreateStrategy: poddisruptionbudget.Strategy,
|
||||
UpdateStrategy: poddisruptionbudget.Strategy,
|
||||
|
@ -38,6 +38,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
|
||||
NewFunc: func() runtime.Object { return &policy.PodSecurityPolicy{} },
|
||||
NewListFunc: func() runtime.Object { return &policy.PodSecurityPolicyList{} },
|
||||
DefaultQualifiedResource: policy.Resource("podsecuritypolicies"),
|
||||
SingularQualifiedResource: policy.Resource("podsecuritypolicy"),
|
||||
|
||||
CreateStrategy: podsecuritypolicy.Strategy,
|
||||
UpdateStrategy: podsecuritypolicy.Strategy,
|
||||
|
@ -124,3 +124,13 @@ func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjec
|
||||
func hasAggregationRule(clusterRole *rbac.ClusterRole) bool {
|
||||
return clusterRole.AggregationRule != nil && len(clusterRole.AggregationRule.ClusterRoleSelectors) > 0
|
||||
}
|
||||
|
||||
var _ rest.SingularNameProvider = &Storage{}
|
||||
|
||||
func (s *Storage) GetSingularName() string {
|
||||
snp, ok := s.StandardStorage.(rest.SingularNameProvider)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return snp.GetSingularName()
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
|
||||
NewFunc: func() runtime.Object { return &rbac.ClusterRole{} },
|
||||
NewListFunc: func() runtime.Object { return &rbac.ClusterRoleList{} },
|
||||
DefaultQualifiedResource: rbac.Resource("clusterroles"),
|
||||
SingularQualifiedResource: rbac.Resource("clusterrole"),
|
||||
|
||||
CreateStrategy: clusterrole.Strategy,
|
||||
UpdateStrategy: clusterrole.Strategy,
|
||||
|
@ -127,3 +127,13 @@ func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjec
|
||||
|
||||
return s.StandardStorage.Update(ctx, name, nonEscalatingInfo, createValidation, updateValidation, forceAllowCreate, options)
|
||||
}
|
||||
|
||||
var _ rest.SingularNameProvider = &Storage{}
|
||||
|
||||
func (s *Storage) GetSingularName() string {
|
||||
snp, ok := s.StandardStorage.(rest.SingularNameProvider)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return snp.GetSingularName()
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
|
||||
NewFunc: func() runtime.Object { return &rbac.ClusterRoleBinding{} },
|
||||
NewListFunc: func() runtime.Object { return &rbac.ClusterRoleBindingList{} },
|
||||
DefaultQualifiedResource: rbac.Resource("clusterrolebindings"),
|
||||
SingularQualifiedResource: rbac.Resource("clusterrolebinding"),
|
||||
|
||||
CreateStrategy: clusterrolebinding.Strategy,
|
||||
UpdateStrategy: clusterrolebinding.Strategy,
|
||||
|
@ -99,3 +99,13 @@ func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjec
|
||||
|
||||
return s.StandardStorage.Update(ctx, name, nonEscalatingInfo, createValidation, updateValidation, forceAllowCreate, options)
|
||||
}
|
||||
|
||||
var _ rest.SingularNameProvider = &Storage{}
|
||||
|
||||
func (s *Storage) GetSingularName() string {
|
||||
snp, ok := s.StandardStorage.(rest.SingularNameProvider)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return snp.GetSingularName()
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
|
||||
NewFunc: func() runtime.Object { return &rbac.Role{} },
|
||||
NewListFunc: func() runtime.Object { return &rbac.RoleList{} },
|
||||
DefaultQualifiedResource: rbac.Resource("roles"),
|
||||
SingularQualifiedResource: rbac.Resource("role"),
|
||||
|
||||
CreateStrategy: role.Strategy,
|
||||
UpdateStrategy: role.Strategy,
|
||||
|
@ -142,3 +142,13 @@ func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjec
|
||||
|
||||
return s.StandardStorage.Update(ctx, name, nonEscalatingInfo, createValidation, updateValidation, forceAllowCreate, options)
|
||||
}
|
||||
|
||||
var _ rest.SingularNameProvider = &Storage{}
|
||||
|
||||
func (s *Storage) GetSingularName() string {
|
||||
snp, ok := s.StandardStorage.(rest.SingularNameProvider)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return snp.GetSingularName()
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
|
||||
NewFunc: func() runtime.Object { return &rbac.RoleBinding{} },
|
||||
NewListFunc: func() runtime.Object { return &rbac.RoleBindingList{} },
|
||||
DefaultQualifiedResource: rbac.Resource("rolebindings"),
|
||||
SingularQualifiedResource: rbac.Resource("rolebinding"),
|
||||
|
||||
CreateStrategy: rolebinding.Strategy,
|
||||
UpdateStrategy: rolebinding.Strategy,
|
||||
|
@ -44,6 +44,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) {
|
||||
NewListFunc: func() runtime.Object { return &resource.PodSchedulingList{} },
|
||||
PredicateFunc: podscheduling.Match,
|
||||
DefaultQualifiedResource: resource.Resource("podschedulings"),
|
||||
SingularQualifiedResource: resource.Resource("podscheduling"),
|
||||
|
||||
CreateStrategy: podscheduling.Strategy,
|
||||
UpdateStrategy: podscheduling.Strategy,
|
||||
|
@ -44,6 +44,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) {
|
||||
NewListFunc: func() runtime.Object { return &resource.ResourceClaimList{} },
|
||||
PredicateFunc: resourceclaim.Match,
|
||||
DefaultQualifiedResource: resource.Resource("resourceclaims"),
|
||||
SingularQualifiedResource: resource.Resource("resourceclaim"),
|
||||
|
||||
CreateStrategy: resourceclaim.Strategy,
|
||||
UpdateStrategy: resourceclaim.Strategy,
|
||||
|
@ -38,6 +38,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
|
||||
NewFunc: func() runtime.Object { return &resource.ResourceClaimTemplate{} },
|
||||
NewListFunc: func() runtime.Object { return &resource.ResourceClaimTemplateList{} },
|
||||
DefaultQualifiedResource: resource.Resource("resourceclaimtemplates"),
|
||||
SingularQualifiedResource: resource.Resource("resourceclaimtemplate"),
|
||||
|
||||
CreateStrategy: resourceclaimtemplate.Strategy,
|
||||
UpdateStrategy: resourceclaimtemplate.Strategy,
|
||||
|
@ -38,6 +38,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
|
||||
NewFunc: func() runtime.Object { return &resource.ResourceClass{} },
|
||||
NewListFunc: func() runtime.Object { return &resource.ResourceClassList{} },
|
||||
DefaultQualifiedResource: resource.Resource("resourceclasses"),
|
||||
SingularQualifiedResource: resource.Resource("resourceclass"),
|
||||
|
||||
CreateStrategy: resourceclass.Strategy,
|
||||
UpdateStrategy: resourceclass.Strategy,
|
||||
|
@ -44,6 +44,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
|
||||
NewFunc: func() runtime.Object { return &scheduling.PriorityClass{} },
|
||||
NewListFunc: func() runtime.Object { return &scheduling.PriorityClassList{} },
|
||||
DefaultQualifiedResource: scheduling.Resource("priorityclasses"),
|
||||
SingularQualifiedResource: scheduling.Resource("priorityclass"),
|
||||
|
||||
CreateStrategy: priorityclass.Strategy,
|
||||
UpdateStrategy: priorityclass.Strategy,
|
||||
|
@ -43,6 +43,7 @@ func NewStorage(optsGetter generic.RESTOptionsGetter) (*CSIDriverStorage, error)
|
||||
NewFunc: func() runtime.Object { return &storageapi.CSIDriver{} },
|
||||
NewListFunc: func() runtime.Object { return &storageapi.CSIDriverList{} },
|
||||
DefaultQualifiedResource: storageapi.Resource("csidrivers"),
|
||||
SingularQualifiedResource: storageapi.Resource("csidriver"),
|
||||
|
||||
CreateStrategy: csidriver.Strategy,
|
||||
UpdateStrategy: csidriver.Strategy,
|
||||
|
@ -43,6 +43,7 @@ func NewStorage(optsGetter generic.RESTOptionsGetter) (*CSINodeStorage, error) {
|
||||
NewFunc: func() runtime.Object { return &storageapi.CSINode{} },
|
||||
NewListFunc: func() runtime.Object { return &storageapi.CSINodeList{} },
|
||||
DefaultQualifiedResource: storageapi.Resource("csinodes"),
|
||||
SingularQualifiedResource: storageapi.Resource("csinode"),
|
||||
|
||||
CreateStrategy: csinode.Strategy,
|
||||
UpdateStrategy: csinode.Strategy,
|
||||
|
@ -41,6 +41,7 @@ func NewStorage(optsGetter generic.RESTOptionsGetter) (*CSIStorageCapacityStorag
|
||||
NewFunc: func() runtime.Object { return &storageapi.CSIStorageCapacity{} },
|
||||
NewListFunc: func() runtime.Object { return &storageapi.CSIStorageCapacityList{} },
|
||||
DefaultQualifiedResource: storageapi.Resource("csistoragecapacities"),
|
||||
SingularQualifiedResource: storageapi.Resource("csistoragecapacity"),
|
||||
|
||||
TableConvertor: rest.NewDefaultTableConvertor(storageapi.Resource("csistoragecapacities")),
|
||||
|
||||
|
@ -39,6 +39,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
|
||||
NewFunc: func() runtime.Object { return &storageapi.StorageClass{} },
|
||||
NewListFunc: func() runtime.Object { return &storageapi.StorageClassList{} },
|
||||
DefaultQualifiedResource: storageapi.Resource("storageclasses"),
|
||||
SingularQualifiedResource: storageapi.Resource("storageclass"),
|
||||
|
||||
CreateStrategy: storageclass.Strategy,
|
||||
UpdateStrategy: storageclass.Strategy,
|
||||
|
@ -49,6 +49,7 @@ func NewStorage(optsGetter generic.RESTOptionsGetter) (*VolumeAttachmentStorage,
|
||||
NewFunc: func() runtime.Object { return &storageapi.VolumeAttachment{} },
|
||||
NewListFunc: func() runtime.Object { return &storageapi.VolumeAttachmentList{} },
|
||||
DefaultQualifiedResource: storageapi.Resource("volumeattachments"),
|
||||
SingularQualifiedResource: storageapi.Resource("volumeattachment"),
|
||||
|
||||
CreateStrategy: volumeattachment.Strategy,
|
||||
UpdateStrategy: volumeattachment.Strategy,
|
||||
|
@ -732,6 +732,7 @@ func (r *crdHandler) getOrCreateServingInfoFor(uid types.UID, name string) (*crd
|
||||
parameterCodec := runtime.NewParameterCodec(parameterScheme)
|
||||
|
||||
resource := schema.GroupVersionResource{Group: crd.Spec.Group, Version: v.Name, Resource: crd.Status.AcceptedNames.Plural}
|
||||
singularResource := schema.GroupVersionResource{Group: crd.Spec.Group, Version: v.Name, Resource: crd.Status.AcceptedNames.Singular}
|
||||
kind := schema.GroupVersionKind{Group: crd.Spec.Group, Version: v.Name, Kind: crd.Status.AcceptedNames.Kind}
|
||||
equivalentResourceRegistry.RegisterKindFor(resource, "", kind)
|
||||
|
||||
@ -801,6 +802,7 @@ func (r *crdHandler) getOrCreateServingInfoFor(uid types.UID, name string) (*crd
|
||||
|
||||
storages[v.Name] = customresource.NewStorage(
|
||||
resource.GroupResource(),
|
||||
singularResource.GroupResource(),
|
||||
kind,
|
||||
schema.GroupVersionKind{Group: crd.Spec.Group, Version: v.Name, Kind: crd.Status.AcceptedNames.ListKind},
|
||||
customresource.NewStrategy(
|
||||
|
@ -41,7 +41,7 @@ type CustomResourceStorage struct {
|
||||
Scale *ScaleREST
|
||||
}
|
||||
|
||||
func NewStorage(resource schema.GroupResource, kind, listKind schema.GroupVersionKind, strategy customResourceStrategy, optsGetter generic.RESTOptionsGetter, categories []string, tableConvertor rest.TableConvertor, replicasPathMapping fieldmanager.ResourcePathMappings) CustomResourceStorage {
|
||||
func NewStorage(resource schema.GroupResource, singularResource schema.GroupResource, kind, listKind schema.GroupVersionKind, strategy customResourceStrategy, optsGetter generic.RESTOptionsGetter, categories []string, tableConvertor rest.TableConvertor, replicasPathMapping fieldmanager.ResourcePathMappings) CustomResourceStorage {
|
||||
var storage CustomResourceStorage
|
||||
store := &genericregistry.Store{
|
||||
NewFunc: func() runtime.Object {
|
||||
@ -58,6 +58,7 @@ func NewStorage(resource schema.GroupResource, kind, listKind schema.GroupVersio
|
||||
},
|
||||
PredicateFunc: strategy.MatchCustomResourceDefinitionStorage,
|
||||
DefaultQualifiedResource: resource,
|
||||
SingularQualifiedResource: singularResource,
|
||||
|
||||
CreateStrategy: strategy,
|
||||
UpdateStrategy: strategy,
|
||||
|
@ -93,6 +93,7 @@ func newStorage(t *testing.T) (customresource.CustomResourceStorage, *etcd3testi
|
||||
table, _ := tableconvertor.New(headers)
|
||||
|
||||
storage := customresource.NewStorage(
|
||||
groupResource,
|
||||
groupResource,
|
||||
kind,
|
||||
schema.GroupVersionKind{Group: "mygroup.example.com", Version: "v1beta1", Kind: "NoxuItemList"},
|
||||
|
@ -47,6 +47,7 @@ func NewREST(scheme *runtime.Scheme, optsGetter generic.RESTOptionsGetter) (*RES
|
||||
NewListFunc: func() runtime.Object { return &apiextensions.CustomResourceDefinitionList{} },
|
||||
PredicateFunc: MatchCustomResourceDefinition,
|
||||
DefaultQualifiedResource: apiextensions.Resource("customresourcedefinitions"),
|
||||
SingularQualifiedResource: apiextensions.Resource("customresourcedefinition"),
|
||||
|
||||
CreateStrategy: strategy,
|
||||
UpdateStrategy: strategy,
|
||||
|
@ -372,6 +372,10 @@ func (storage *SimpleRESTStorage) ConvertToTable(ctx context.Context, obj runtim
|
||||
return rest.NewDefaultTableConvertor(schema.GroupResource{Resource: "simple"}).ConvertToTable(ctx, obj, tableOptions)
|
||||
}
|
||||
|
||||
func (storate *SimpleRESTStorage) GetSingularName() string {
|
||||
return "simple"
|
||||
}
|
||||
|
||||
func (storage *SimpleRESTStorage) List(ctx context.Context, options *metainternalversion.ListOptions) (runtime.Object, error) {
|
||||
storage.checkContext(ctx)
|
||||
result := &genericapitesting.SimpleList{
|
||||
@ -575,6 +579,10 @@ func (s *ConnecterRESTStorage) NewConnectOptions() (runtime.Object, bool, string
|
||||
return s.emptyConnectOptions, false, ""
|
||||
}
|
||||
|
||||
func (s *ConnecterRESTStorage) GetSingularName() string {
|
||||
return "simple"
|
||||
}
|
||||
|
||||
type MetadataRESTStorage struct {
|
||||
*SimpleRESTStorage
|
||||
types []string
|
||||
@ -619,6 +627,10 @@ type GetWithOptionsRootRESTStorage struct {
|
||||
takesPath string
|
||||
}
|
||||
|
||||
func (r *GetWithOptionsRootRESTStorage) GetSingularName() string {
|
||||
return "simple"
|
||||
}
|
||||
|
||||
func (r *GetWithOptionsRootRESTStorage) NamespaceScoped() bool {
|
||||
return false
|
||||
}
|
||||
@ -687,6 +699,10 @@ func (storage *SimpleTypedStorage) checkContext(ctx context.Context) {
|
||||
storage.actualNamespace, storage.namespacePresent = request.NamespaceFrom(ctx)
|
||||
}
|
||||
|
||||
func (storage *SimpleTypedStorage) GetSingularName() string {
|
||||
return "simple"
|
||||
}
|
||||
|
||||
func bodyOrDie(response *http.Response) string {
|
||||
defer response.Body.Close()
|
||||
body, err := ioutil.ReadAll(response.Body)
|
||||
@ -823,6 +839,10 @@ func (UnimplementedRESTStorage) New() runtime.Object {
|
||||
func (UnimplementedRESTStorage) Destroy() {
|
||||
}
|
||||
|
||||
func (UnimplementedRESTStorage) GetSingularName() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// TestUnimplementedRESTStorage ensures that if a rest.Storage does not implement a given
|
||||
// method, that it is literally not registered with the server. In the past,
|
||||
// we registered everything, and returned method not supported if it didn't support
|
||||
@ -4289,6 +4309,10 @@ func (storage *SimpleXGSubresourceRESTStorage) GroupVersionKind(containingGV sch
|
||||
return storage.itemGVK
|
||||
}
|
||||
|
||||
func (storage *SimpleXGSubresourceRESTStorage) GetSingularName() string {
|
||||
return "simple"
|
||||
}
|
||||
|
||||
func TestXGSubresource(t *testing.T) {
|
||||
container := restful.NewContainer()
|
||||
container.Router(restful.CurlyRouter{})
|
||||
|
@ -1080,6 +1080,14 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
||||
if categoriesProvider, ok := storage.(rest.CategoriesProvider); ok {
|
||||
apiResource.Categories = categoriesProvider.Categories()
|
||||
}
|
||||
if !isSubresource {
|
||||
singularNameProvider, ok := storage.(rest.SingularNameProvider)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("resource %s must implement SingularNameProvider", resource)
|
||||
}
|
||||
apiResource.SingularName = singularNameProvider.GetSingularName()
|
||||
}
|
||||
|
||||
if gvkProvider, ok := storage.(rest.GroupVersionKindProvider); ok {
|
||||
gvk := gvkProvider.GroupVersionKind(a.group.GroupVersion)
|
||||
apiResource.Group = gvk.Group
|
||||
|
@ -110,6 +110,9 @@ type Store struct {
|
||||
// See qualifiedResourceFromContext for details.
|
||||
DefaultQualifiedResource schema.GroupResource
|
||||
|
||||
// SingularQualifiedResource is the singular name of the resource.
|
||||
SingularQualifiedResource schema.GroupResource
|
||||
|
||||
// KeyRootFunc returns the root etcd key for this resource; should not
|
||||
// include trailing "/". This is used for operations that work on the
|
||||
// entire collection (listing and watching).
|
||||
@ -229,6 +232,8 @@ var _ rest.StandardStorage = &Store{}
|
||||
var _ rest.TableConvertor = &Store{}
|
||||
var _ GenericStore = &Store{}
|
||||
|
||||
var _ rest.SingularNameProvider = &Store{}
|
||||
|
||||
const (
|
||||
OptimisticLockErrorMsg = "the object has been modified; please apply your changes to the latest version and try again"
|
||||
resourceCountPollPeriodJitter = 1.2
|
||||
@ -1320,6 +1325,12 @@ func (e *Store) CompleteWithOptions(options *generic.StoreOptions) error {
|
||||
if e.DefaultQualifiedResource.Empty() {
|
||||
return fmt.Errorf("store %#v must have a non-empty qualified resource", e)
|
||||
}
|
||||
if e.SingularQualifiedResource.Empty() {
|
||||
return fmt.Errorf("store %#v must have a non-empty singular qualified resource", e)
|
||||
}
|
||||
if e.DefaultQualifiedResource.Group != e.SingularQualifiedResource.Group {
|
||||
return fmt.Errorf("store for %#v, singular and plural qualified resource's group name's must match", e)
|
||||
}
|
||||
if e.NewFunc == nil {
|
||||
return fmt.Errorf("store for %s must have NewFunc set", e.DefaultQualifiedResource.String())
|
||||
}
|
||||
@ -1515,6 +1526,10 @@ func (e *Store) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set {
|
||||
return e.ResetFieldsStrategy.GetResetFields()
|
||||
}
|
||||
|
||||
func (e *Store) GetSingularName() string {
|
||||
return e.SingularQualifiedResource.Resource
|
||||
}
|
||||
|
||||
// validateIndexers will check the prefix of indexers.
|
||||
func validateIndexers(indexers *cache.Indexers) error {
|
||||
if indexers == nil {
|
||||
|
@ -2342,6 +2342,7 @@ func newTestGenericStoreRegistry(t *testing.T, scheme *runtime.Scheme, hasCacheE
|
||||
NewFunc: func() runtime.Object { return &example.Pod{} },
|
||||
NewListFunc: func() runtime.Object { return &example.PodList{} },
|
||||
DefaultQualifiedResource: example.Resource("pods"),
|
||||
SingularQualifiedResource: example.Resource("pod"),
|
||||
CreateStrategy: strategy,
|
||||
UpdateStrategy: strategy,
|
||||
DeleteStrategy: strategy,
|
||||
|
@ -89,6 +89,12 @@ type CategoriesProvider interface {
|
||||
Categories() []string
|
||||
}
|
||||
|
||||
// SingularNameProvider returns singular name of resources. This is used by kubectl discovery to have singular
|
||||
// name representation of resources. In case of shortcut conflicts(with CRD shortcuts) singular name should always map to this resource.
|
||||
type SingularNameProvider interface {
|
||||
GetSingularName() string
|
||||
}
|
||||
|
||||
// GroupVersionKindProvider is used to specify a particular GroupVersionKind to discovery. This is used for polymorphic endpoints
|
||||
// which generally point to foreign versions. Scale refers to Scale.v1beta1.extensions for instance.
|
||||
// This trumps KindProvider since it is capable of providing the information required.
|
||||
|
@ -551,6 +551,10 @@ func (p *testGetterStorage) Get(ctx context.Context, name string, options *metav
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (p *testGetterStorage) GetSingularName() string {
|
||||
return "getter"
|
||||
}
|
||||
|
||||
type testNoVerbsStorage struct {
|
||||
Version string
|
||||
}
|
||||
@ -571,6 +575,10 @@ func (p *testNoVerbsStorage) New() runtime.Object {
|
||||
func (p *testNoVerbsStorage) Destroy() {
|
||||
}
|
||||
|
||||
func (p *testNoVerbsStorage) GetSingularName() string {
|
||||
return "noverb"
|
||||
}
|
||||
|
||||
func fakeVersion() version.Info {
|
||||
return version.Info{
|
||||
Major: "42",
|
||||
|
@ -45,6 +45,7 @@ func NewREST(scheme *runtime.Scheme, optsGetter generic.RESTOptionsGetter) *REST
|
||||
NewListFunc: func() runtime.Object { return &apiregistration.APIServiceList{} },
|
||||
PredicateFunc: apiservice.MatchAPIService,
|
||||
DefaultQualifiedResource: apiregistration.Resource("apiservices"),
|
||||
SingularQualifiedResource: apiregistration.Resource("apiservice"),
|
||||
|
||||
CreateStrategy: strategy,
|
||||
UpdateStrategy: strategy,
|
||||
|
@ -34,6 +34,7 @@ func NewREST(scheme *runtime.Scheme, optsGetter generic.RESTOptionsGetter) (*reg
|
||||
NewListFunc: func() runtime.Object { return &wardle.FischerList{} },
|
||||
PredicateFunc: MatchFischer,
|
||||
DefaultQualifiedResource: wardle.Resource("fischers"),
|
||||
SingularQualifiedResource: wardle.Resource("fischer"),
|
||||
|
||||
CreateStrategy: strategy,
|
||||
UpdateStrategy: strategy,
|
||||
|
@ -34,6 +34,7 @@ func NewREST(scheme *runtime.Scheme, optsGetter generic.RESTOptionsGetter) (*reg
|
||||
NewListFunc: func() runtime.Object { return &wardle.FlunderList{} },
|
||||
PredicateFunc: MatchFlunder,
|
||||
DefaultQualifiedResource: wardle.Resource("flunders"),
|
||||
SingularQualifiedResource: wardle.Resource("flunder"),
|
||||
|
||||
CreateStrategy: strategy,
|
||||
UpdateStrategy: strategy,
|
||||
|
@ -55,7 +55,152 @@ run_assert_short_name_tests() {
|
||||
output_message=$(kubectl get --raw=/api/v1)
|
||||
|
||||
## test if a short name is exported during discovery
|
||||
kube::test::if_has_string "${output_message}" '{"name":"configmaps","singularName":"","namespaced":true,"kind":"ConfigMap","verbs":\["create","delete","deletecollection","get","list","patch","update","watch"\],"shortNames":\["cm"\],"storageVersionHash":'
|
||||
kube::test::if_has_string "${output_message}" '{"name":"configmaps","singularName":"configmap","namespaced":true,"kind":"ConfigMap","verbs":\["create","delete","deletecollection","get","list","patch","update","watch"\],"shortNames":\["cm"\],"storageVersionHash":'
|
||||
|
||||
# check that there is no pod with the name test-crd-example
|
||||
output_message=$(kubectl get pod)
|
||||
kube::test::if_has_not_string "${output_message}" "test-crd-example"
|
||||
|
||||
kubectl create -f - << __EOF__
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: examples.test.com
|
||||
spec:
|
||||
group: test.com
|
||||
scope: Namespaced
|
||||
versions:
|
||||
- name: v1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
properties:
|
||||
test:
|
||||
type: string
|
||||
names:
|
||||
plural: examples
|
||||
singular: example
|
||||
shortNames:
|
||||
- pod
|
||||
kind: Example
|
||||
__EOF__
|
||||
|
||||
# Test that we can list this new custom resource
|
||||
kube::test::wait_object_assert customresourcedefinitions "{{range.items}}{{if eq ${id_field:?} \"examples.test.com\"}}{{$id_field}}:{{end}}{{end}}" 'examples.test.com:'
|
||||
|
||||
kubectl create -f - << __EOF__
|
||||
apiVersion: test.com/v1
|
||||
kind: Example
|
||||
metadata:
|
||||
name: test-crd-example
|
||||
spec:
|
||||
test: test
|
||||
__EOF__
|
||||
|
||||
# Test that we can list this new custom resource
|
||||
kube::test::wait_object_assert examples "{{range.items}}{{${id_field:?}}}:{{end}}" 'test-crd-example:'
|
||||
|
||||
output_message=$(kubectl get examples)
|
||||
kube::test::if_has_string "${output_message}" "test-crd-example"
|
||||
|
||||
# test that get pod returns v1/pod instead crd
|
||||
output_message=$(kubectl get pod)
|
||||
kube::test::if_has_not_string "${output_message}" "test-crd-example"
|
||||
|
||||
# invalidate cache and assure that still correct resource is shown
|
||||
kubectl api-resources
|
||||
|
||||
# retest the above cases after invalidating cache
|
||||
output_message=$(kubectl get examples)
|
||||
kube::test::if_has_string "${output_message}" "test-crd-example"
|
||||
|
||||
output_message=$(kubectl get pod)
|
||||
kube::test::if_has_not_string "${output_message}" "test-crd-example"
|
||||
|
||||
# Cleanup
|
||||
kubectl delete examples/test-crd-example
|
||||
kubectl delete customresourcedefinition examples.test.com
|
||||
|
||||
set +o nounset
|
||||
set +o errexit
|
||||
}
|
||||
|
||||
run_assert_singular_name_tests() {
|
||||
set -o nounset
|
||||
set -o errexit
|
||||
|
||||
create_and_use_new_namespace
|
||||
kube::log::status "Testing assert singular name"
|
||||
|
||||
# check that there is no pod with the name test-crd-example
|
||||
output_message=$(kubectl get pod)
|
||||
kube::test::if_has_not_string "${output_message}" "test-crd-example"
|
||||
|
||||
kubectl create -f - << __EOF__
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: examples.test.com
|
||||
spec:
|
||||
group: test.com
|
||||
scope: Namespaced
|
||||
versions:
|
||||
- name: v1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
properties:
|
||||
test:
|
||||
type: string
|
||||
names:
|
||||
plural: examples
|
||||
singular: pod
|
||||
kind: Example
|
||||
__EOF__
|
||||
|
||||
# Test that we can list this new custom resource
|
||||
kube::test::wait_object_assert customresourcedefinitions "{{range.items}}{{if eq ${id_field:?} \"examples.test.com\"}}{{$id_field}}:{{end}}{{end}}" 'examples.test.com:'
|
||||
|
||||
kubectl create -f - << __EOF__
|
||||
apiVersion: test.com/v1
|
||||
kind: Example
|
||||
metadata:
|
||||
name: test-crd-example
|
||||
spec:
|
||||
test: test
|
||||
__EOF__
|
||||
|
||||
# Test that we can list this new custom resource
|
||||
kube::test::wait_object_assert examples "{{range.items}}{{$id_field}}:{{end}}" 'test-crd-example:'
|
||||
|
||||
output_message=$(kubectl get examples)
|
||||
kube::test::if_has_string "${output_message}" "test-crd-example"
|
||||
|
||||
output_message=$(kubectl get pod)
|
||||
kube::test::if_has_not_string "${output_message}" "test-crd-example"
|
||||
|
||||
# invalidate cache and assure that still correct resource is shown
|
||||
kubectl api-resources
|
||||
|
||||
output_message=$(kubectl get examples)
|
||||
kube::test::if_has_string "${output_message}" "test-crd-example"
|
||||
|
||||
output_message=$(kubectl get pod)
|
||||
kube::test::if_has_not_string "${output_message}" "test-crd-example"
|
||||
|
||||
# Cleanup
|
||||
kubectl delete examples/test-crd-example
|
||||
kubectl delete customresourcedefinition examples.test.com
|
||||
|
||||
set +o nounset
|
||||
set +o errexit
|
||||
|
@ -504,7 +504,17 @@ runTests() {
|
||||
# Assert short name #
|
||||
#########################
|
||||
|
||||
if kube::test::if_supports_resource "${customresourcedefinitions}" && kube::test::if_supports_resource "${pods}" && kube::test::if_supports_resource "${configmaps}" ; then
|
||||
record_command run_assert_short_name_tests
|
||||
fi
|
||||
|
||||
#########################
|
||||
# Assert singular name #
|
||||
#########################
|
||||
|
||||
if kube::test::if_supports_resource "${customresourcedefinitions}" && kube::test::if_supports_resource "${pods}" ; then
|
||||
record_command run_assert_singular_name_tests
|
||||
fi
|
||||
|
||||
#########################
|
||||
# Assert categories #
|
||||
|
@ -690,6 +690,33 @@ func TestGroupPriorty(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestSingularNames(t *testing.T) {
|
||||
server := kubeapiservertesting.StartTestServerOrDie(t, nil, []string{"--runtime-config=api/all=true"}, framework.SharedEtcd())
|
||||
t.Cleanup(server.TearDownFn)
|
||||
|
||||
kubeClientSet, err := kubernetes.NewForConfig(server.ClientConfig)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, resources, err := kubeClientSet.Discovery().ServerGroupsAndResources()
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, rr := range resources {
|
||||
for _, r := range rr.APIResources {
|
||||
if strings.Contains(r.Name, "/") {
|
||||
continue
|
||||
}
|
||||
if r.SingularName == "" {
|
||||
t.Errorf("missing singularName for resource %q in %q", r.Name, rr.GroupVersion)
|
||||
continue
|
||||
}
|
||||
if r.SingularName != strings.ToLower(r.Kind) {
|
||||
t.Errorf("expected singularName for resource %q in %q to be %q, got %q", r.Name, rr.GroupVersion, strings.ToLower(r.Kind), r.SingularName)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func makeCRDSpec(group string, kind string, namespaced bool, versions []string, categories ...string) apiextensionsv1.CustomResourceDefinitionSpec {
|
||||
scope := apiextensionsv1.NamespaceScoped
|
||||
if !namespaced {
|
||||
|
Loading…
Reference in New Issue
Block a user