diff --git a/api/api-rules/violation_exceptions.list b/api/api-rules/violation_exceptions.list index fc4997fad70..8a8c2644425 100644 --- a/api/api-rules/violation_exceptions.list +++ b/api/api-rules/violation_exceptions.list @@ -56,6 +56,10 @@ API rule violation: names_match,k8s.io/api/resource/v1alpha3,DeviceAttribute,Boo API rule violation: names_match,k8s.io/api/resource/v1alpha3,DeviceAttribute,IntValue API rule violation: names_match,k8s.io/api/resource/v1alpha3,DeviceAttribute,StringValue API rule violation: names_match,k8s.io/api/resource/v1alpha3,DeviceAttribute,VersionValue +API rule violation: names_match,k8s.io/api/resource/v1beta1,DeviceAttribute,BoolValue +API rule violation: names_match,k8s.io/api/resource/v1beta1,DeviceAttribute,IntValue +API rule violation: names_match,k8s.io/api/resource/v1beta1,DeviceAttribute,StringValue +API rule violation: names_match,k8s.io/api/resource/v1beta1,DeviceAttribute,VersionValue API rule violation: names_match,k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1,JSONSchemaProps,Ref API rule violation: names_match,k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1,JSONSchemaProps,Schema API rule violation: names_match,k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1,JSONSchemaProps,XEmbeddedResource diff --git a/cmd/kube-apiserver/app/aggregator.go b/cmd/kube-apiserver/app/aggregator.go index e561980d64d..74923724ee2 100644 --- a/cmd/kube-apiserver/app/aggregator.go +++ b/cmd/kube-apiserver/app/aggregator.go @@ -51,6 +51,8 @@ var apiVersionPriorities = merge(controlplaneapiserver.DefaultGenericAPIServiceP {Group: "node.k8s.io", Version: "v1"}: {Group: 16300, Version: 15}, {Group: "node.k8s.io", Version: "v1alpha1"}: {Group: 16300, Version: 1}, {Group: "node.k8s.io", Version: "v1beta1"}: {Group: 16300, Version: 9}, + {Group: "resource.k8s.io", Version: "v1beta1"}: {Group: 16200, Version: 9}, + {Group: "resource.k8s.io", Version: "v1alpha3"}: {Group: 16200, Version: 1}, // Append a new group to the end of the list if unsure. // You can use min(existing group)-100 as the initial value for a group. // Version can be set to 9 (to have space around) for a new group. diff --git a/hack/lib/init.sh b/hack/lib/init.sh index 2c6cdf3172f..d27c0a2798a 100755 --- a/hack/lib/init.sh +++ b/hack/lib/init.sh @@ -94,6 +94,7 @@ coordination.k8s.io/v1beta1 \ coordination.k8s.io/v1 \ discovery.k8s.io/v1 \ discovery.k8s.io/v1beta1 \ +resource.k8s.io/v1beta1 \ resource.k8s.io/v1alpha3 \ extensions/v1beta1 \ events.k8s.io/v1 \ diff --git a/pkg/api/testing/defaulting_test.go b/pkg/api/testing/defaulting_test.go index fa6ca54226a..06b59825d0b 100644 --- a/pkg/api/testing/defaulting_test.go +++ b/pkg/api/testing/defaulting_test.go @@ -139,6 +139,10 @@ func TestDefaulting(t *testing.T) { {Group: "resource.k8s.io", Version: "v1alpha3", Kind: "ResourceClaimList"}: {}, {Group: "resource.k8s.io", Version: "v1alpha3", Kind: "ResourceClaimTemplate"}: {}, {Group: "resource.k8s.io", Version: "v1alpha3", Kind: "ResourceClaimTemplateList"}: {}, + {Group: "resource.k8s.io", Version: "v1beta1", Kind: "ResourceClaim"}: {}, + {Group: "resource.k8s.io", Version: "v1beta1", Kind: "ResourceClaimList"}: {}, + {Group: "resource.k8s.io", Version: "v1beta1", Kind: "ResourceClaimTemplate"}: {}, + {Group: "resource.k8s.io", Version: "v1beta1", Kind: "ResourceClaimTemplateList"}: {}, {Group: "admissionregistration.k8s.io", Version: "v1alpha1", Kind: "ValidatingAdmissionPolicy"}: {}, {Group: "admissionregistration.k8s.io", Version: "v1alpha1", Kind: "ValidatingAdmissionPolicyList"}: {}, {Group: "admissionregistration.k8s.io", Version: "v1alpha1", Kind: "ValidatingAdmissionPolicyBinding"}: {}, diff --git a/pkg/apis/resource/install/install.go b/pkg/apis/resource/install/install.go index eea8fe21e85..be85f811a67 100644 --- a/pkg/apis/resource/install/install.go +++ b/pkg/apis/resource/install/install.go @@ -24,6 +24,7 @@ import ( "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/resource" "k8s.io/kubernetes/pkg/apis/resource/v1alpha3" + "k8s.io/kubernetes/pkg/apis/resource/v1beta1" ) func init() { @@ -34,5 +35,6 @@ func init() { func Install(scheme *runtime.Scheme) { utilruntime.Must(resource.AddToScheme(scheme)) utilruntime.Must(v1alpha3.AddToScheme(scheme)) + utilruntime.Must(v1beta1.AddToScheme(scheme)) utilruntime.Must(scheme.SetVersionPriority(v1alpha3.SchemeGroupVersion)) } diff --git a/pkg/controlplane/instance.go b/pkg/controlplane/instance.go index e5480d3ad18..a34728a5097 100644 --- a/pkg/controlplane/instance.go +++ b/pkg/controlplane/instance.go @@ -48,7 +48,8 @@ import ( nodev1 "k8s.io/api/node/v1" policyapiv1 "k8s.io/api/policy/v1" rbacv1 "k8s.io/api/rbac/v1" - resourceapi "k8s.io/api/resource/v1alpha3" + resourcev1alpha3 "k8s.io/api/resource/v1alpha3" + resourcev1beta1 "k8s.io/api/resource/v1beta1" schedulingapiv1 "k8s.io/api/scheduling/v1" storageapiv1 "k8s.io/api/storage/v1" storageapiv1alpha1 "k8s.io/api/storage/v1alpha1" @@ -461,6 +462,7 @@ var ( flowcontrolv1beta2.SchemeGroupVersion, flowcontrolv1beta3.SchemeGroupVersion, networkingapiv1beta1.SchemeGroupVersion, + resourcev1beta1.SchemeGroupVersion, } // alphaAPIGroupVersionsDisabledByDefault holds the alpha APIs we have. They are always disabled by default. @@ -470,7 +472,7 @@ var ( authenticationv1alpha1.SchemeGroupVersion, apiserverinternalv1alpha1.SchemeGroupVersion, coordinationv1alpha1.SchemeGroupVersion, - resourceapi.SchemeGroupVersion, + resourcev1alpha3.SchemeGroupVersion, certificatesv1alpha1.SchemeGroupVersion, networkingapiv1alpha1.SchemeGroupVersion, storageapiv1alpha1.SchemeGroupVersion, diff --git a/pkg/registry/resource/resourceclaim/strategy.go b/pkg/registry/resource/resourceclaim/strategy.go index ea8f11a758b..4313577f97b 100644 --- a/pkg/registry/resource/resourceclaim/strategy.go +++ b/pkg/registry/resource/resourceclaim/strategy.go @@ -58,6 +58,9 @@ func (resourceclaimStrategy) GetResetFields() map[fieldpath.APIVersion]*fieldpat "resource.k8s.io/v1alpha3": fieldpath.NewSet( fieldpath.MakePathOrDie("status"), ), + "resource.k8s.io/v1beta1": fieldpath.NewSet( + fieldpath.MakePathOrDie("status"), + ), } return fields @@ -123,6 +126,9 @@ func (resourceclaimStatusStrategy) GetResetFields() map[fieldpath.APIVersion]*fi "resource.k8s.io/v1alpha3": fieldpath.NewSet( fieldpath.MakePathOrDie("spec"), ), + "resource.k8s.io/v1beta1": fieldpath.NewSet( + fieldpath.MakePathOrDie("spec"), + ), } return fields diff --git a/pkg/registry/resource/rest/storage_resource.go b/pkg/registry/resource/rest/storage_resource.go index a829abeff79..18c18d95601 100644 --- a/pkg/registry/resource/rest/storage_resource.go +++ b/pkg/registry/resource/rest/storage_resource.go @@ -18,6 +18,7 @@ package rest import ( resourcev1alpha3 "k8s.io/api/resource/v1alpha3" + resourcev1beta1 "k8s.io/api/resource/v1beta1" "k8s.io/apiserver/pkg/registry/generic" "k8s.io/apiserver/pkg/registry/rest" genericapiserver "k8s.io/apiserver/pkg/server" @@ -47,6 +48,12 @@ func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorag apiGroupInfo.VersionedResourcesStorageMap[resourcev1alpha3.SchemeGroupVersion.Version] = storageMap } + if storageMap, err := p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter); err != nil { + return genericapiserver.APIGroupInfo{}, err + } else if len(storageMap) > 0 { + apiGroupInfo.VersionedResourcesStorageMap[resourcev1beta1.SchemeGroupVersion.Version] = storageMap + } + return apiGroupInfo, nil } @@ -89,6 +96,45 @@ func (p RESTStorageProvider) v1alpha3Storage(apiResourceConfigSource serverstora return storage, nil } +func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) { + storage := map[string]rest.Storage{} + + if resource := "deviceclasses"; apiResourceConfigSource.ResourceEnabled(resourcev1beta1.SchemeGroupVersion.WithResource(resource)) { + deviceclassStorage, err := deviceclassstore.NewREST(restOptionsGetter) + if err != nil { + return nil, err + } + storage[resource] = deviceclassStorage + } + + if resource := "resourceclaims"; apiResourceConfigSource.ResourceEnabled(resourcev1beta1.SchemeGroupVersion.WithResource(resource)) { + resourceClaimStorage, resourceClaimStatusStorage, err := resourceclaimstore.NewREST(restOptionsGetter) + if err != nil { + return nil, err + } + storage[resource] = resourceClaimStorage + storage[resource+"/status"] = resourceClaimStatusStorage + } + + if resource := "resourceclaimtemplates"; apiResourceConfigSource.ResourceEnabled(resourcev1beta1.SchemeGroupVersion.WithResource(resource)) { + resourceClaimTemplateStorage, err := resourceclaimtemplatestore.NewREST(restOptionsGetter) + if err != nil { + return nil, err + } + storage[resource] = resourceClaimTemplateStorage + } + + if resource := "resourceslices"; apiResourceConfigSource.ResourceEnabled(resourcev1beta1.SchemeGroupVersion.WithResource(resource)) { + resourceSliceStorage, err := resourceslicestore.NewREST(restOptionsGetter) + if err != nil { + return nil, err + } + storage[resource] = resourceSliceStorage + } + + return storage, nil +} + func (p RESTStorageProvider) GroupName() string { return resource.GroupName } diff --git a/staging/src/k8s.io/api/roundtrip_test.go b/staging/src/k8s.io/api/roundtrip_test.go index 12435b463ed..0faa385926a 100644 --- a/staging/src/k8s.io/api/roundtrip_test.go +++ b/staging/src/k8s.io/api/roundtrip_test.go @@ -69,7 +69,8 @@ import ( rbacv1 "k8s.io/api/rbac/v1" rbacv1alpha1 "k8s.io/api/rbac/v1alpha1" rbacv1beta1 "k8s.io/api/rbac/v1beta1" - resourceapi "k8s.io/api/resource/v1alpha3" + resourcev1alpha3 "k8s.io/api/resource/v1alpha3" + resourcev1beta1 "k8s.io/api/resource/v1beta1" schedulingv1 "k8s.io/api/scheduling/v1" schedulingv1alpha1 "k8s.io/api/scheduling/v1alpha1" schedulingv1beta1 "k8s.io/api/scheduling/v1beta1" @@ -135,7 +136,8 @@ var groups = []runtime.SchemeBuilder{ rbacv1alpha1.SchemeBuilder, rbacv1beta1.SchemeBuilder, rbacv1.SchemeBuilder, - resourceapi.SchemeBuilder, + resourcev1alpha3.SchemeBuilder, + resourcev1beta1.SchemeBuilder, schedulingv1alpha1.SchemeBuilder, schedulingv1beta1.SchemeBuilder, schedulingv1.SchemeBuilder, diff --git a/test/integration/apiserver/apply/reset_fields_test.go b/test/integration/apiserver/apply/reset_fields_test.go index 5ac835dd6ba..fd9aefc97e0 100644 --- a/test/integration/apiserver/apply/reset_fields_test.go +++ b/test/integration/apiserver/apply/reset_fields_test.go @@ -60,6 +60,7 @@ var resetFieldsStatusData = map[schema.GroupVersionResource]string{ gvr("policy", "v1", "poddisruptionbudgets"): `{"status": {"currentHealthy": 25}}`, gvr("policy", "v1beta1", "poddisruptionbudgets"): `{"status": {"currentHealthy": 25}}`, gvr("resource.k8s.io", "v1alpha3", "resourceclaims"): `{"status": {"allocation": {"nodeSelector": {"nodeSelectorTerms": [{"matchExpressions": [{"key": "some-label", "operator": "In", "values": ["some-other-value"]}] }]}}}}`, + gvr("resource.k8s.io", "v1beta1", "resourceclaims"): `{"status": {"allocation": {"nodeSelector": {"nodeSelectorTerms": [{"matchExpressions": [{"key": "some-label", "operator": "In", "values": ["some-other-value"]}] }]}}}}`, gvr("internal.apiserver.k8s.io", "v1alpha1", "storageversions"): `{"status": {"commonEncodingVersion":"v1","storageVersions":[{"apiServerID":"1","decodableVersions":["v1","v2"],"encodingVersion":"v1"}],"conditions":[{"type":"AllEncodingVersionsEqual","status":"False","lastTransitionTime":"2020-01-01T00:00:00Z","reason":"allEncodingVersionsEqual","message":"all encoding versions are set to v1"}]}}`, // standard for []metav1.Condition gvr("admissionregistration.k8s.io", "v1alpha1", "validatingadmissionpolicies"): `{"status": {"conditions":[{"type":"Accepted","status":"True","lastTransitionTime":"2020-01-01T00:00:00Z","reason":"RuleApplied","message":"Rule was applied"}]}}`, @@ -150,6 +151,9 @@ var resetFieldsSpecData = map[schema.GroupVersionResource]string{ gvr("resource.k8s.io", "v1alpha3", "deviceclasses"): `{"metadata": {"labels":{"a":"c"}}}`, gvr("resource.k8s.io", "v1alpha3", "resourceclaims"): `{"spec": {"devices": {"requests": [{"name": "req-0", "deviceClassName": "other-class"}]}}}`, // spec is immutable, but that doesn't matter for the test. gvr("resource.k8s.io", "v1alpha3", "resourceclaimtemplates"): `{"spec": {"spec": {"resourceClassName": "class2name"}}}`, + gvr("resource.k8s.io", "v1beta1", "deviceclasses"): `{"metadata": {"labels":{"a":"c"}}}`, + gvr("resource.k8s.io", "v1beta1", "resourceclaims"): `{"spec": {"devices": {"requests": [{"name": "req-0", "deviceClassName": "other-class"}]}}}`, // spec is immutable, but that doesn't matter for the test. + gvr("resource.k8s.io", "v1beta1", "resourceclaimtemplates"): `{"spec": {"spec": {"resourceClassName": "class2name"}}}`, gvr("internal.apiserver.k8s.io", "v1alpha1", "storageversions"): `{}`, gvr("admissionregistration.k8s.io", "v1alpha1", "validatingadmissionpolicies"): `{"metadata": {"labels": {"a":"c"}}, "spec": {"paramKind": {"apiVersion": "apps/v1", "kind": "Deployment"}}}`, gvr("admissionregistration.k8s.io", "v1beta1", "validatingadmissionpolicies"): `{"metadata": {"labels": {"a":"c"}}, "spec": {"paramKind": {"apiVersion": "apps/v1", "kind": "Deployment"}}}`, diff --git a/test/integration/apiserver/apply/status_test.go b/test/integration/apiserver/apply/status_test.go index 6fbff8db175..f2528a6fdcd 100644 --- a/test/integration/apiserver/apply/status_test.go +++ b/test/integration/apiserver/apply/status_test.go @@ -56,6 +56,7 @@ var statusData = map[schema.GroupVersionResource]string{ gvr("policy", "v1", "poddisruptionbudgets"): `{"status": {"currentHealthy": 5}}`, gvr("policy", "v1beta1", "poddisruptionbudgets"): `{"status": {"currentHealthy": 5}}`, gvr("resource.k8s.io", "v1alpha3", "resourceclaims"): `{"status": {"allocation": {"nodeSelector": {"nodeSelectorTerms": [{"matchExpressions": [{"key": "some-label", "operator": "In", "values": ["some-value"]}] }]}}}}`, + gvr("resource.k8s.io", "v1beta1", "resourceclaims"): `{"status": {"allocation": {"nodeSelector": {"nodeSelectorTerms": [{"matchExpressions": [{"key": "some-label", "operator": "In", "values": ["some-value"]}] }]}}}}`, gvr("internal.apiserver.k8s.io", "v1alpha1", "storageversions"): `{"status": {"commonEncodingVersion":"v1","storageVersions":[{"apiServerID":"1","decodableVersions":["v1","v2"],"encodingVersion":"v1"}],"conditions":[{"type":"AllEncodingVersionsEqual","status":"True","lastTransitionTime":"2020-01-01T00:00:00Z","reason":"allEncodingVersionsEqual","message":"all encoding versions are set to v1"}]}}`, // standard for []metav1.Condition gvr("admissionregistration.k8s.io", "v1alpha1", "validatingadmissionpolicies"): `{"status": {"conditions":[{"type":"Accepted","status":"False","lastTransitionTime":"2020-01-01T00:00:00Z","reason":"RuleApplied","message":"Rule was applied"}]}}`, diff --git a/test/integration/etcd/data.go b/test/integration/etcd/data.go index 01dad0df1ec..7af2a1bd500 100644 --- a/test/integration/etcd/data.go +++ b/test/integration/etcd/data.go @@ -445,6 +445,29 @@ func GetEtcdStorageDataForNamespace(namespace string) map[schema.GroupVersionRes }, // -- + // k8s.io/kubernetes/pkg/apis/resource/v1beta1 + gvr("resource.k8s.io", "v1beta1", "deviceclasses"): { + Stub: `{"metadata": {"name": "class2name"}}`, + ExpectedEtcdPath: "/registry/deviceclasses/class2name", + ExpectedGVK: gvkP("resource.k8s.io", "v1alpha3", "DeviceClass"), + }, + gvr("resource.k8s.io", "v1beta1", "resourceclaims"): { + Stub: `{"metadata": {"name": "claim2name"}, "spec": {"devices": {"requests": [{"name": "req-0", "deviceClassName": "example-class", "allocationMode": "ExactCount", "count": 1}]}}}`, + ExpectedEtcdPath: "/registry/resourceclaims/" + namespace + "/claim2name", + ExpectedGVK: gvkP("resource.k8s.io", "v1alpha3", "ResourceClaim"), + }, + gvr("resource.k8s.io", "v1beta1", "resourceclaimtemplates"): { + Stub: `{"metadata": {"name": "claimtemplate2name"}, "spec": {"spec": {"devices": {"requests": [{"name": "req-0", "deviceClassName": "example-class", "allocationMode": "ExactCount", "count": 1}]}}}}`, + ExpectedEtcdPath: "/registry/resourceclaimtemplates/" + namespace + "/claimtemplate2name", + ExpectedGVK: gvkP("resource.k8s.io", "v1alpha3", "ResourceClaimTemplate"), + }, + gvr("resource.k8s.io", "v1beta1", "resourceslices"): { + Stub: `{"metadata": {"name": "node2slice"}, "spec": {"nodeName": "worker1", "driver": "dra.example.com", "pool": {"name": "worker1", "resourceSliceCount": 1}}}`, + ExpectedEtcdPath: "/registry/resourceslices/node2slice", + ExpectedGVK: gvkP("resource.k8s.io", "v1alpha3", "ResourceSlice"), + }, + // -- + // k8s.io/apiserver/pkg/apis/apiserverinternal/v1alpha1 gvr("internal.apiserver.k8s.io", "v1alpha1", "storageversions"): { Stub: `{"metadata":{"name":"sv1.test"},"spec":{}}`,