Merge pull request #98312 from deads2k/finish-export-option-removal

finish removal of exportoptions
This commit is contained in:
Kubernetes Prow Robot
2021-01-25 08:15:15 -08:00
committed by GitHub
49 changed files with 297 additions and 2441 deletions

View File

@@ -167,7 +167,7 @@ var nonRoundTrippableTypes = sets.NewString(
"PatchOptions",
)
var commonKinds = []string{"Status", "ListOptions", "DeleteOptions", "ExportOptions", "GetOptions", "CreateOptions", "UpdateOptions", "PatchOptions"}
var commonKinds = []string{"Status", "ListOptions", "DeleteOptions", "GetOptions", "CreateOptions", "UpdateOptions", "PatchOptions"}
// TestCommonKindsRegistered verifies that all group/versions registered with
// the legacyscheme package have the common kinds.

View File

@@ -64,7 +64,6 @@ var typesAllowedTags = map[reflect.Type]bool{
reflect.TypeOf(metav1.OwnerReference{}): true,
reflect.TypeOf(metav1.LabelSelector{}): true,
reflect.TypeOf(metav1.GetOptions{}): true,
reflect.TypeOf(metav1.ExportOptions{}): true,
reflect.TypeOf(metav1.ListOptions{}): true,
reflect.TypeOf(metav1.DeleteOptions{}): true,
reflect.TypeOf(metav1.GroupVersionKind{}): true,

View File

@@ -160,18 +160,7 @@ func TestLegacyRestStorageStrategies(t *testing.T) {
t.Errorf("failed to create legacy REST storage: %v", err)
}
// Any new stores with export logic will need to be added here:
exceptions := registrytest.StrategyExceptions{
// Only these stores should have an export strategy defined:
HasExportStrategy: []string{
"secrets",
"limitRanges",
"nodes",
"podTemplates",
},
}
strategyErrors := registrytest.ValidateStorageStrategies(apiGroupInfo.VersionedResourcesStorageMap["v1"], exceptions)
strategyErrors := registrytest.ValidateStorageStrategies(apiGroupInfo.VersionedResourcesStorageMap["v1"])
for _, err := range strategyErrors {
t.Error(err)
}
@@ -187,14 +176,8 @@ func TestCertificatesRestStorageStrategies(t *testing.T) {
t.Fatalf("unexpected error from REST storage: %v", err)
}
exceptions := registrytest.StrategyExceptions{
HasExportStrategy: []string{
"certificatesigningrequests",
},
}
strategyErrors := registrytest.ValidateStorageStrategies(
apiGroupInfo.VersionedResourcesStorageMap[certificatesapiv1beta1.SchemeGroupVersion.Version], exceptions)
apiGroupInfo.VersionedResourcesStorageMap[certificatesapiv1beta1.SchemeGroupVersion.Version])
for _, err := range strategyErrors {
t.Error(err)
}

View File

@@ -46,7 +46,6 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, *Approva
CreateStrategy: csrregistry.Strategy,
UpdateStrategy: csrregistry.Strategy,
DeleteStrategy: csrregistry.Strategy,
ExportStrategy: csrregistry.Strategy,
TableConvertor: printerstorage.TableConvertor{TableGenerator: printers.NewTableGenerator().With(printersinternal.AddHandlers)},
}

View File

@@ -118,21 +118,6 @@ func (csrStrategy) AllowUnconditionalUpdate() bool {
return true
}
func (s csrStrategy) Export(ctx context.Context, obj runtime.Object, exact bool) error {
csr, ok := obj.(*certificates.CertificateSigningRequest)
if !ok {
// unexpected programmer error
return fmt.Errorf("unexpected object: %v", obj)
}
s.PrepareForCreate(ctx, obj)
if exact {
return nil
}
// CSRs allow direct subresource edits, we clear them without exact so the CSR value can be reused.
csr.Status = certificates.CertificateSigningRequestStatus{}
return nil
}
// Storage strategy for the Status subresource
type csrStatusStrategy struct {
csrStrategy

View File

@@ -40,7 +40,6 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
CreateStrategy: limitrange.Strategy,
UpdateStrategy: limitrange.Strategy,
DeleteStrategy: limitrange.Strategy,
ExportStrategy: limitrange.Strategy,
// TODO: define table converter that exposes more than name/creation timestamp
TableConvertor: rest.NewDefaultTableConvertor(api.Resource("limitranges")),

View File

@@ -72,10 +72,3 @@ func (limitrangeStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.O
func (limitrangeStrategy) AllowUnconditionalUpdate() bool {
return true
}
func (limitrangeStrategy) Export(context.Context, runtime.Object, bool) error {
// Copied from OpenShift exporter
// TODO: this needs to be fixed
// limitrange.Strategy.PrepareForCreate(ctx, obj)
return nil
}

View File

@@ -119,10 +119,6 @@ func (r *REST) Watch(ctx context.Context, options *metainternalversion.ListOptio
return r.store.Watch(ctx, options)
}
func (r *REST) Export(ctx context.Context, name string, opts metav1.ExportOptions) (runtime.Object, error) {
return r.store.Export(ctx, name, opts)
}
// Delete enforces life-cycle rules for namespace termination
func (r *REST) Delete(ctx context.Context, name string, deleteValidation rest.ValidateObjectFunc, options *metav1.DeleteOptions) (runtime.Object, bool, error) {
nsObj, err := r.Get(ctx, name, &metav1.GetOptions{})

View File

@@ -88,7 +88,6 @@ func NewStorage(optsGetter generic.RESTOptionsGetter, kubeletClientConfig client
CreateStrategy: node.Strategy,
UpdateStrategy: node.Strategy,
DeleteStrategy: node.Strategy,
ExportStrategy: node.Strategy,
TableConvertor: printerstorage.TableConvertor{TableGenerator: printers.NewTableGenerator().With(printersinternal.AddHandlers)},
}

View File

@@ -141,22 +141,6 @@ func (nodeStrategy) AllowUnconditionalUpdate() bool {
return true
}
func (ns nodeStrategy) Export(ctx context.Context, obj runtime.Object, exact bool) error {
n, ok := obj.(*api.Node)
if !ok {
// unexpected programmer error
return fmt.Errorf("unexpected object: %v", obj)
}
ns.PrepareForCreate(ctx, obj)
if exact {
return nil
}
// Nodes are the only resources that allow direct status edits, therefore
// we clear that without exact so that the node value can be reused.
n.Status = api.NodeStatus{}
return nil
}
type nodeStatusStrategy struct {
nodeStrategy
}

View File

@@ -42,7 +42,6 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
CreateStrategy: podtemplate.Strategy,
UpdateStrategy: podtemplate.Strategy,
DeleteStrategy: podtemplate.Strategy,
ExportStrategy: podtemplate.Strategy,
ReturnDeletedObject: true,

View File

@@ -87,8 +87,3 @@ func (podTemplateStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.
func (podTemplateStrategy) AllowUnconditionalUpdate() bool {
return true
}
func (podTemplateStrategy) Export(ctx context.Context, obj runtime.Object, exact bool) error {
// Do nothing
return nil
}

View File

@@ -17,7 +17,6 @@ go_library(
"//pkg/api/legacyscheme:go_default_library",
"//pkg/apis/core:go_default_library",
"//pkg/apis/core/validation:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/fields:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
@@ -37,9 +36,6 @@ go_test(
"//pkg/api/testing:go_default_library",
"//pkg/apis/core:go_default_library",
"//pkg/apis/core/install:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
],
)

View File

@@ -44,7 +44,6 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
CreateStrategy: secret.Strategy,
UpdateStrategy: secret.Strategy,
DeleteStrategy: secret.Strategy,
ExportStrategy: secret.Strategy,
TableConvertor: printerstorage.TableConvertor{TableGenerator: printers.NewTableGenerator().With(printersinternal.AddHandlers)},
}

View File

@@ -20,7 +20,6 @@ import (
"context"
"fmt"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
@@ -85,26 +84,6 @@ func (strategy) AllowUnconditionalUpdate() bool {
return true
}
func (s strategy) Export(ctx context.Context, obj runtime.Object, exact bool) error {
t, ok := obj.(*api.Secret)
if !ok {
// unexpected programmer error
return fmt.Errorf("unexpected object: %v", obj)
}
s.PrepareForCreate(ctx, obj)
if exact {
return nil
}
// secrets that are tied to the UID of a service account cannot be exported anyway
if t.Type == api.SecretTypeServiceAccountToken || len(t.Annotations[api.ServiceAccountUIDKey]) > 0 {
errs := []*field.Error{
field.Invalid(field.NewPath("type"), t, "can not export service account secrets"),
}
return errors.NewInvalid(api.Kind("Secret"), t.Name, errs)
}
return nil
}
// GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
secret, ok := obj.(*api.Secret)

View File

@@ -17,12 +17,8 @@ limitations under the License.
package secret
import (
"reflect"
"testing"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
apitesting "k8s.io/kubernetes/pkg/api/testing"
api "k8s.io/kubernetes/pkg/apis/core"
@@ -30,80 +26,6 @@ import (
_ "k8s.io/kubernetes/pkg/apis/core/install"
)
func TestExportSecret(t *testing.T) {
tests := []struct {
objIn runtime.Object
objOut runtime.Object
exact bool
expectErr bool
}{
{
objIn: &api.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
Namespace: "bar",
},
Data: map[string][]byte{
"foo": []byte("bar"),
},
},
objOut: &api.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
Namespace: "bar",
},
Data: map[string][]byte{
"foo": []byte("bar"),
},
},
exact: true,
},
{
objIn: &api.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
Namespace: "bar",
},
Type: api.SecretTypeServiceAccountToken,
},
expectErr: true,
},
{
objIn: &api.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
Namespace: "bar",
Annotations: map[string]string{
api.ServiceAccountUIDKey: "true",
},
},
},
expectErr: true,
},
{
objIn: &api.Pod{},
expectErr: true,
},
}
for _, test := range tests {
err := Strategy.Export(genericapirequest.NewContext(), test.objIn, test.exact)
if err != nil {
if !test.expectErr {
t.Errorf("unexpected error: %v", err)
}
continue
}
if test.expectErr {
t.Error("unexpected non-error")
continue
}
if !reflect.DeepEqual(test.objIn, test.objOut) {
t.Errorf("expected:\n%v\nsaw:\n%v\n", test.objOut, test.objIn)
}
}
}
func TestSelectableFieldLabelConversions(t *testing.T) {
apitesting.TestSelectableFieldLabelConversionsOfKind(t,
"v1",

View File

@@ -79,7 +79,6 @@ type ServiceStorage interface {
rest.CreaterUpdater
rest.GracefulDeleter
rest.Watcher
rest.Exporter
rest.StorageVersionProvider
}
@@ -189,10 +188,6 @@ func (rs *REST) Watch(ctx context.Context, options *metainternalversion.ListOpti
return rs.services.Watch(ctx, options)
}
func (rs *REST) Export(ctx context.Context, name string, opts metav1.ExportOptions) (runtime.Object, error) {
return rs.services.Export(ctx, name, opts)
}
func (rs *REST) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) {
service := obj.(*api.Service)

View File

@@ -163,10 +163,6 @@ func (s *serviceStorage) ConvertToTable(ctx context.Context, object runtime.Obje
panic("not implemented")
}
func (s *serviceStorage) Export(ctx context.Context, name string, opts metav1.ExportOptions) (runtime.Object, error) {
panic("not implemented")
}
func (s *serviceStorage) StorageVersion() runtime.GroupVersioner {
panic("not implemented")
}

View File

@@ -57,7 +57,6 @@ func NewGenericREST(optsGetter generic.RESTOptionsGetter, serviceCIDR net.IPNet,
CreateStrategy: strategy,
UpdateStrategy: strategy,
DeleteStrategy: strategy,
ExportStrategy: strategy,
TableConvertor: printerstorage.TableConvertor{TableGenerator: printers.NewTableGenerator().With(printersinternal.AddHandlers)},
}

View File

@@ -18,7 +18,6 @@ package service
import (
"context"
"fmt"
"net"
"reflect"
@@ -37,7 +36,6 @@ import (
type Strategy interface {
rest.RESTCreateUpdateStrategy
rest.RESTExportStrategy
}
// svcStrategy implements behavior for Services
@@ -139,30 +137,6 @@ func (svcStrategy) AllowUnconditionalUpdate() bool {
return true
}
func (svcStrategy) Export(ctx context.Context, obj runtime.Object, exact bool) error {
t, ok := obj.(*api.Service)
if !ok {
// unexpected programmer error
return fmt.Errorf("unexpected object: %v", obj)
}
// TODO: service does not yet have a prepare create strategy (see above)
t.Status = api.ServiceStatus{}
if exact {
return nil
}
//set ClusterIPs as nil - if ClusterIPs[0] != None
if len(t.Spec.ClusterIPs) > 0 && t.Spec.ClusterIPs[0] != api.ClusterIPNone {
t.Spec.ClusterIP = ""
t.Spec.ClusterIPs = nil
}
if t.Spec.Type == api.ServiceTypeNodePort {
for i := range t.Spec.Ports {
t.Spec.Ports[i].NodePort = 0
}
}
return nil
}
// dropServiceDisabledFields drops fields that are not used if their associated feature gates
// are not enabled. The typical pattern is:
// if !utilfeature.DefaultFeatureGate.Enabled(features.MyFeature) && !myFeatureInUse(oldSvc) {

View File

@@ -47,115 +47,6 @@ func newStrategy(cidr string, hasSecondary bool) (testStrategy Strategy, testSta
return
}
func TestExportService(t *testing.T) {
testStrategy, _ := newStrategy("10.0.0.0/16", false)
tests := []struct {
objIn runtime.Object
objOut runtime.Object
exact bool
expectErr bool
}{
{
objIn: &api.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
Namespace: "bar",
},
Status: api.ServiceStatus{
LoadBalancer: api.LoadBalancerStatus{
Ingress: []api.LoadBalancerIngress{
{IP: "1.2.3.4"},
},
},
},
},
objOut: &api.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
Namespace: "bar",
},
},
exact: true,
},
{
objIn: &api.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
Namespace: "bar",
},
Spec: api.ServiceSpec{
ClusterIPs: []string{"10.0.0.1"},
},
Status: api.ServiceStatus{
LoadBalancer: api.LoadBalancerStatus{
Ingress: []api.LoadBalancerIngress{
{IP: "1.2.3.4"},
},
},
},
},
objOut: &api.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
Namespace: "bar",
},
Spec: api.ServiceSpec{
ClusterIPs: nil,
},
},
},
{
objIn: &api.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
Namespace: "bar",
},
Spec: api.ServiceSpec{
ClusterIPs: []string{"10.0.0.1", "2001::1"},
},
Status: api.ServiceStatus{
LoadBalancer: api.LoadBalancerStatus{
Ingress: []api.LoadBalancerIngress{
{IP: "1.2.3.4"},
},
},
},
},
objOut: &api.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
Namespace: "bar",
},
Spec: api.ServiceSpec{
ClusterIPs: nil,
},
},
},
{
objIn: &api.Pod{},
expectErr: true,
},
}
for _, test := range tests {
err := testStrategy.Export(genericapirequest.NewContext(), test.objIn, test.exact)
if err != nil {
if !test.expectErr {
t.Errorf("unexpected error: %v", err)
}
continue
}
if test.expectErr {
t.Error("unexpected non-error")
continue
}
if !reflect.DeepEqual(test.objIn, test.objOut) {
t.Errorf("expected:\n%v\nsaw:\n%v\n", test.objOut, test.objIn)
}
}
}
func TestCheckGeneratedNameError(t *testing.T) {
testStrategy, _ := newStrategy("10.0.0.0/16", false)
expect := errors.NewNotFound(api.Resource("foos"), "bar")

View File

@@ -21,7 +21,6 @@ go_library(
deps = [
"//pkg/apis/core:go_default_library",
"//pkg/kubeapiserver:go_default_library",
"//pkg/util/slice:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",

View File

@@ -117,10 +117,3 @@ func (r *ServiceRegistry) WatchServices(ctx context.Context, options *metaintern
return nil, r.Err
}
func (r *ServiceRegistry) ExportService(ctx context.Context, name string, options metav1.ExportOptions) (*api.Service, error) {
r.mu.Lock()
defer r.mu.Unlock()
return r.Service, r.Err
}

View File

@@ -21,17 +21,13 @@ import (
"k8s.io/apiserver/pkg/registry/generic/registry"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/kubernetes/pkg/util/slice"
)
// ValidateStorageStrategies ensures any instances of the generic registry.Store in the given storage map
// have expected strategies defined.
func ValidateStorageStrategies(storageMap map[string]rest.Storage, exceptions StrategyExceptions) []error {
func ValidateStorageStrategies(storageMap map[string]rest.Storage) []error {
errs := []error{}
// Used to ensure we saw all the expected exceptions:
hasExportExceptionsSeen := []string{}
for k, storage := range storageMap {
switch t := storage.(type) {
case registry.GenericStore:
@@ -46,27 +42,6 @@ func ValidateStorageStrategies(storageMap map[string]rest.Storage, exceptions St
if t.GetDeleteStrategy() == nil {
errs = append(errs, fmt.Errorf("store for type [%v] does not have a DeleteStrategy", k))
}
// Check that ExportStrategy is set if applicable:
if slice.ContainsString(exceptions.HasExportStrategy, k, nil) {
hasExportExceptionsSeen = append(hasExportExceptionsSeen, k)
if t.GetExportStrategy() == nil {
errs = append(errs, fmt.Errorf("store for type [%v] does not have an ExportStrategy", k))
}
} else {
// By default we expect Stores to not have additional export logic:
if t.GetExportStrategy() != nil {
errs = append(errs, fmt.Errorf("store for type [%v] has an unexpected ExportStrategy", k))
}
}
}
}
// Ensure that we saw all our expected exceptions:
for _, expKey := range exceptions.HasExportStrategy {
if !slice.ContainsString(hasExportExceptionsSeen, expKey, nil) {
errs = append(errs, fmt.Errorf("no generic store seen for expected ExportStrategy: %v", expKey))
}
}