mirror of
https://github.com/vmware-tanzu/pinniped.git
synced 2026-07-28 11:02:52 +00:00
auto-disable MutatingAdmissionPolicy admission plugin when that kind does not exist
Signed-off-by: Ryan Richard <richardry@vmware.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
// Copyright 2024-2025 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2024-2026 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package admissionpluginconfig
|
||||
@@ -9,6 +9,8 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
mutatingadmissionpolicy "k8s.io/apiserver/pkg/admission/plugin/policy/mutating"
|
||||
validatingadmissionpolicy "k8s.io/apiserver/pkg/admission/plugin/policy/validating"
|
||||
"k8s.io/apiserver/pkg/server/options"
|
||||
"k8s.io/client-go/discovery"
|
||||
@@ -59,22 +61,20 @@ func configureAdmissionPlugins(
|
||||
recommendedOptions *options.RecommendedOptions,
|
||||
disableAdmissionPlugins []string,
|
||||
) error {
|
||||
if !slices.Contains(disableAdmissionPlugins, validatingadmissionpolicy.PluginName) {
|
||||
// The admin did not explicitly disable the ValidatingAdmissionPolicy plugin, but we may still need disable it if
|
||||
// the Kubernetes cluster on which we are running is too old. Check if the API server has such a resource.
|
||||
hasValidatingAdmissionPolicyResource, err := k8sAPIServerHasValidatingAdmissionPolicyResource(discoveryClient)
|
||||
if !slices.Contains(disableAdmissionPlugins, validatingadmissionpolicy.PluginName) || !slices.Contains(disableAdmissionPlugins, mutatingadmissionpolicy.PluginName) {
|
||||
discoveredResources, err := performAPIDiscovery(discoveryClient)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed looking up availability of ValidatingAdmissionPolicy resource: %w", err)
|
||||
return fmt.Errorf("failed to perform k8s API discovery for purpose of checking availability of %s resource types: %w",
|
||||
admissionregistrationv1.GroupName, err)
|
||||
}
|
||||
|
||||
if !hasValidatingAdmissionPolicyResource {
|
||||
// Customize the admission plugins to avoid using the new ValidatingAdmissionPolicy plugin.
|
||||
plog.Warning("could not find ValidatingAdmissionPolicy resource on this Kubernetes cluster " +
|
||||
"(which is normal for clusters older than Kubernetes 1.30); " +
|
||||
"disabling ValidatingAdmissionPolicy admission plugins for all Pinniped aggregated API resource types")
|
||||
disableAdmissionPlugins = autoDisablePluginWhenResourceNotFound(
|
||||
disableAdmissionPlugins, discoveredResources, validatingadmissionpolicy.PluginName, "1.30",
|
||||
)
|
||||
|
||||
disableAdmissionPlugins = append(disableAdmissionPlugins, validatingadmissionpolicy.PluginName)
|
||||
}
|
||||
disableAdmissionPlugins = autoDisablePluginWhenResourceNotFound(
|
||||
disableAdmissionPlugins, discoveredResources, mutatingadmissionpolicy.PluginName, "1.36",
|
||||
)
|
||||
}
|
||||
|
||||
// Mutate the recommendedOptions to potentially disable some admission plugins.
|
||||
@@ -84,10 +84,30 @@ func configureAdmissionPlugins(
|
||||
return nil
|
||||
}
|
||||
|
||||
func k8sAPIServerHasValidatingAdmissionPolicyResource(discoveryClient discovery.ServerResourcesInterface) (bool, error) {
|
||||
// Perform discovery. We are looking for ValidatingAdmissionPolicy in group
|
||||
// admissionregistration.k8s.io at any version.
|
||||
func autoDisablePluginWhenResourceNotFound(disableAdmissionPlugins []string, resources []*metav1.APIResourceList, pluginName string, since string) []string {
|
||||
if !slices.Contains(disableAdmissionPlugins, pluginName) {
|
||||
// The admin did not explicitly disable the plugin, but we may still need to disable it if
|
||||
// the Kubernetes cluster on which we are running is too old. Check if the API server has such a resource.
|
||||
hasResource := k8sAPIServerHasResource(resources, pluginName)
|
||||
|
||||
if !hasResource {
|
||||
plog.Warning("could not find resource type on this Kubernetes cluster "+
|
||||
"(which is normal for older Kubernetes clusters); "+
|
||||
"disabling admission plugins for all Pinniped aggregated API resource types for that Kind",
|
||||
"kind", pluginName, "kindIntroducedInKubernetesVersion", since)
|
||||
|
||||
// Customize the admission plugins to avoid using the new plugin.
|
||||
disableAdmissionPlugins = append(disableAdmissionPlugins, pluginName)
|
||||
}
|
||||
}
|
||||
|
||||
return disableAdmissionPlugins
|
||||
}
|
||||
|
||||
func performAPIDiscovery(discoveryClient discovery.ServerResourcesInterface) ([]*metav1.APIResourceList, error) {
|
||||
// Perform discovery. We are looking for resources in group admissionregistration.k8s.io at any version.
|
||||
resources, err := discoveryClient.ServerPreferredResources()
|
||||
|
||||
partialErr := &discovery.ErrGroupDiscoveryFailed{}
|
||||
if resources != nil && errors.As(err, &partialErr) {
|
||||
// This is a partial discovery error, most likely caused by Pinniped's own aggregated APIs
|
||||
@@ -99,30 +119,34 @@ func k8sAPIServerHasValidatingAdmissionPolicyResource(discoveryClient discovery.
|
||||
// There was an error for the specific group that we are trying to find, so
|
||||
// return an error. If we don't arrive here, then it must have been error(s) for
|
||||
// some other group(s) that we are not looking for, so we can ignore those error(s).
|
||||
return false, err
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
} else if err != nil {
|
||||
// We got some other type of error aside from a partial failure.
|
||||
return false, fmt.Errorf("failed to perform k8s API discovery: %w", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resources, nil
|
||||
}
|
||||
|
||||
func k8sAPIServerHasResource(resources []*metav1.APIResourceList, resourceKind string) bool {
|
||||
// Now look at all discovered groups until we find version v1 of group admissionregistration.k8s.io.
|
||||
for _, resourcesPerGV := range resources {
|
||||
if resourcesPerGV.GroupVersion == admissionregistrationv1.SchemeGroupVersion.String() {
|
||||
// Found the group, so now look to see if it includes ValidatingAdmissionPolicy as a resource,
|
||||
// Found the group, so now look to see if it includes the given resourceKind as a resource type,
|
||||
// which went GA in Kubernetes 1.30, and could be enabled by a feature flag in previous versions.
|
||||
for _, resource := range resourcesPerGV.APIResources {
|
||||
if resource.Kind == "ValidatingAdmissionPolicy" {
|
||||
if resource.Kind == resourceKind {
|
||||
// Found it!
|
||||
plog.Info("found ValidatingAdmissionPolicy resource on this Kubernetes cluster",
|
||||
plog.Info("found "+admissionregistrationv1.GroupName+" resource on this Kubernetes cluster",
|
||||
"groupVersion", resourcesPerGV.GroupVersion, "kind", resource.Kind)
|
||||
return true, nil
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Didn't findValidatingAdmissionPolicy on this cluster.
|
||||
return false, nil
|
||||
// Didn't the resource kind on this cluster.
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2024-2025 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2024-2026 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package admissionpluginconfig
|
||||
@@ -30,6 +30,30 @@ func TestValidateAdmissionPluginNames(t *testing.T) {
|
||||
name: "empty",
|
||||
pluginNames: []string{},
|
||||
},
|
||||
{
|
||||
name: "nil",
|
||||
pluginNames: nil,
|
||||
},
|
||||
{
|
||||
name: "only invalid values",
|
||||
pluginNames: []string{"foo", "bar"},
|
||||
wantErr: "admission plugin names not recognized: [foo bar] (each must be one of [NamespaceLifecycle MutatingAdmissionPolicy MutatingAdmissionWebhook ValidatingAdmissionPolicy ValidatingAdmissionWebhook])",
|
||||
},
|
||||
{
|
||||
name: "duplicate invalid names are reported once per occurrence",
|
||||
pluginNames: []string{"foobar", "NamespaceLifecycle", "foobar"},
|
||||
wantErr: "admission plugin names not recognized: [foobar foobar] (each must be one of [NamespaceLifecycle MutatingAdmissionPolicy MutatingAdmissionWebhook ValidatingAdmissionPolicy ValidatingAdmissionWebhook])",
|
||||
},
|
||||
{
|
||||
name: "comparison is case-sensitive",
|
||||
pluginNames: []string{"namespacelifecycle"},
|
||||
wantErr: "admission plugin names not recognized: [namespacelifecycle] (each must be one of [NamespaceLifecycle MutatingAdmissionPolicy MutatingAdmissionWebhook ValidatingAdmissionPolicy ValidatingAdmissionWebhook])",
|
||||
},
|
||||
{
|
||||
name: "empty string entry is not recognized",
|
||||
pluginNames: []string{""},
|
||||
wantErr: "admission plugin names not recognized: [] (each must be one of [NamespaceLifecycle MutatingAdmissionPolicy MutatingAdmissionWebhook ValidatingAdmissionPolicy ValidatingAdmissionWebhook])",
|
||||
},
|
||||
{
|
||||
name: "all current valid values (this list may change in future versions of Kubernetes packages)",
|
||||
pluginNames: []string{
|
||||
@@ -37,6 +61,7 @@ func TestValidateAdmissionPluginNames(t *testing.T) {
|
||||
"MutatingAdmissionWebhook",
|
||||
"ValidatingAdmissionPolicy",
|
||||
"ValidatingAdmissionWebhook",
|
||||
"MutatingAdmissionPolicy",
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -47,6 +72,7 @@ func TestValidateAdmissionPluginNames(t *testing.T) {
|
||||
"ValidatingAdmissionPolicy",
|
||||
"foobar",
|
||||
"ValidatingAdmissionWebhook",
|
||||
"MutatingAdmissionPolicy",
|
||||
},
|
||||
wantErr: "admission plugin names not recognized: [foobar] (each must be one of [NamespaceLifecycle MutatingAdmissionPolicy MutatingAdmissionWebhook ValidatingAdmissionPolicy ValidatingAdmissionWebhook])",
|
||||
},
|
||||
@@ -60,6 +86,7 @@ func TestValidateAdmissionPluginNames(t *testing.T) {
|
||||
"foobar",
|
||||
"ValidatingAdmissionWebhook",
|
||||
"foobaz",
|
||||
"MutatingAdmissionPolicy",
|
||||
},
|
||||
wantErr: "admission plugin names not recognized: [foobat foobar foobaz] (each must be one of [NamespaceLifecycle MutatingAdmissionPolicy MutatingAdmissionWebhook ValidatingAdmissionPolicy ValidatingAdmissionWebhook])",
|
||||
},
|
||||
@@ -95,23 +122,16 @@ func TestConfigureAdmissionPlugins(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
newStyleAdmissionResourcesWithValidatingAdmissionPolicies := &metav1.APIResourceList{
|
||||
newStyleAdmissionResources := &metav1.APIResourceList{
|
||||
GroupVersion: admissionregistrationv1.SchemeGroupVersion.String(),
|
||||
APIResources: []metav1.APIResource{
|
||||
{Name: "validatingwebhookconfigurations", Kind: "ValidatingWebhookConfiguration"},
|
||||
{Name: "validatingadmissionpolicies", Kind: "ValidatingAdmissionPolicy"},
|
||||
{Name: "mutatingadmissionpolicies", Kind: "MutatingAdmissionPolicy"},
|
||||
},
|
||||
}
|
||||
|
||||
newStyleAdmissionResourcesWithValidatingAdmissionPoliciesAtOlderAPIVersion := &metav1.APIResourceList{
|
||||
GroupVersion: admissionregistrationv1.SchemeGroupVersion.Group + "/v1beta1",
|
||||
APIResources: []metav1.APIResource{
|
||||
{Name: "validatingwebhookconfigurations", Kind: "ValidatingWebhookConfiguration"},
|
||||
{Name: "validatingadmissionpolicies", Kind: "ValidatingAdmissionPolicy"},
|
||||
},
|
||||
}
|
||||
|
||||
oldStyleAdmissionResourcesWithoutValidatingAdmissionPolicies := &metav1.APIResourceList{
|
||||
oldStyleAdmissionResources := &metav1.APIResourceList{
|
||||
GroupVersion: admissionregistrationv1.SchemeGroupVersion.String(),
|
||||
APIResources: []metav1.APIResource{
|
||||
{Name: "validatingwebhookconfigurations", Kind: "ValidatingWebhookConfiguration"},
|
||||
@@ -127,87 +147,158 @@ func TestConfigureAdmissionPlugins(t *testing.T) {
|
||||
wantDisabledPlugins []string
|
||||
}{
|
||||
{
|
||||
name: "when there is a ValidatingAdmissionPolicy resource and nil disabled list, then we do not change the plugin configuration",
|
||||
name: "when there are modern resource types and nil disabled list, then we do not change the plugin configuration",
|
||||
availableAPIResources: []*metav1.APIResourceList{
|
||||
coreResources,
|
||||
newStyleAdmissionResourcesWithValidatingAdmissionPolicies,
|
||||
newStyleAdmissionResources,
|
||||
appsResources,
|
||||
},
|
||||
disabledPlugins: nil,
|
||||
wantDisabledPlugins: nil,
|
||||
},
|
||||
{
|
||||
name: "when there is a ValidatingAdmissionPolicy resource and empty disabled list, then we do not change the plugin configuration",
|
||||
name: "when there are modern resource types resource and empty disabled list, then we do not change the plugin configuration",
|
||||
availableAPIResources: []*metav1.APIResourceList{
|
||||
coreResources,
|
||||
newStyleAdmissionResourcesWithValidatingAdmissionPolicies,
|
||||
newStyleAdmissionResources,
|
||||
appsResources,
|
||||
},
|
||||
disabledPlugins: []string{},
|
||||
wantDisabledPlugins: nil,
|
||||
},
|
||||
{
|
||||
name: "when there is no ValidatingAdmissionPolicy resource, as there would not be in an old Kubernetes cluster, then we disable that admission plugin",
|
||||
name: "when are modern resource types are missing, as there would not be in an old Kubernetes cluster, then we disable those admission plugins",
|
||||
availableAPIResources: []*metav1.APIResourceList{
|
||||
coreResources,
|
||||
oldStyleAdmissionResourcesWithoutValidatingAdmissionPolicies,
|
||||
oldStyleAdmissionResources,
|
||||
appsResources,
|
||||
},
|
||||
disabledPlugins: nil,
|
||||
wantDisabledPlugins: []string{"ValidatingAdmissionPolicy", "MutatingAdmissionPolicy"},
|
||||
},
|
||||
{
|
||||
name: "when only ValidatingAdmissionPolicy is missing, then we only automatically disable that admission plugin",
|
||||
availableAPIResources: []*metav1.APIResourceList{
|
||||
coreResources,
|
||||
{
|
||||
GroupVersion: admissionregistrationv1.SchemeGroupVersion.String(),
|
||||
APIResources: []metav1.APIResource{
|
||||
{Name: "validatingwebhookconfigurations", Kind: "ValidatingWebhookConfiguration"},
|
||||
{Name: "mutatingadmissionpolicies", Kind: "MutatingAdmissionPolicy"},
|
||||
},
|
||||
},
|
||||
appsResources,
|
||||
},
|
||||
disabledPlugins: nil,
|
||||
wantDisabledPlugins: []string{"ValidatingAdmissionPolicy"},
|
||||
},
|
||||
{
|
||||
name: "when there is only an older version of ValidatingAdmissionPolicy resource, as there would be in an old Kubernetes cluster with the feature flag enabled, then we disable that plugin (because the admission code wants to watch v1)",
|
||||
name: "when only MutatingAdmissionPolicy is missing, then we only automatically disable that admission plugin",
|
||||
availableAPIResources: []*metav1.APIResourceList{
|
||||
coreResources,
|
||||
newStyleAdmissionResourcesWithValidatingAdmissionPoliciesAtOlderAPIVersion,
|
||||
{
|
||||
GroupVersion: admissionregistrationv1.SchemeGroupVersion.String(),
|
||||
APIResources: []metav1.APIResource{
|
||||
{Name: "validatingwebhookconfigurations", Kind: "ValidatingWebhookConfiguration"},
|
||||
{Name: "validatingadmissionpolicies", Kind: "ValidatingAdmissionPolicy"},
|
||||
},
|
||||
},
|
||||
appsResources,
|
||||
},
|
||||
disabledPlugins: nil,
|
||||
wantDisabledPlugins: []string{"MutatingAdmissionPolicy"},
|
||||
},
|
||||
{
|
||||
name: "when only ValidatingAdmissionPolicy is explicitly disabled, then we may still need to automatically disable other admission plugins",
|
||||
availableAPIResources: []*metav1.APIResourceList{
|
||||
coreResources,
|
||||
{
|
||||
GroupVersion: admissionregistrationv1.SchemeGroupVersion.String(),
|
||||
APIResources: []metav1.APIResource{
|
||||
{Name: "validatingwebhookconfigurations", Kind: "ValidatingWebhookConfiguration"},
|
||||
{Name: "validatingadmissionpolicies", Kind: "ValidatingAdmissionPolicy"},
|
||||
},
|
||||
},
|
||||
appsResources,
|
||||
},
|
||||
disabledPlugins: []string{"ValidatingAdmissionPolicy"},
|
||||
wantDisabledPlugins: []string{"ValidatingAdmissionPolicy", "MutatingAdmissionPolicy"},
|
||||
},
|
||||
{
|
||||
name: "when only MutatingAdmissionPolicy is explicitly disabled, then we may still need to automatically disable other admission plugins",
|
||||
availableAPIResources: []*metav1.APIResourceList{
|
||||
coreResources,
|
||||
{
|
||||
GroupVersion: admissionregistrationv1.SchemeGroupVersion.String(),
|
||||
APIResources: []metav1.APIResource{
|
||||
{Name: "validatingwebhookconfigurations", Kind: "ValidatingWebhookConfiguration"},
|
||||
{Name: "mutatingadmissionpolicies", Kind: "MutatingAdmissionPolicy"},
|
||||
},
|
||||
},
|
||||
appsResources,
|
||||
},
|
||||
disabledPlugins: []string{"MutatingAdmissionPolicy"},
|
||||
wantDisabledPlugins: []string{"MutatingAdmissionPolicy", "ValidatingAdmissionPolicy"},
|
||||
},
|
||||
{
|
||||
name: "when there are only older version of are modern resource types, as there would be in an old Kubernetes cluster with the feature flag enabled, then we disable those plugins (because the admission code wants to watch v1)",
|
||||
availableAPIResources: []*metav1.APIResourceList{
|
||||
coreResources,
|
||||
{
|
||||
GroupVersion: admissionregistrationv1.SchemeGroupVersion.Group + "/v1beta1",
|
||||
APIResources: []metav1.APIResource{
|
||||
{Name: "validatingwebhookconfigurations", Kind: "ValidatingWebhookConfiguration"},
|
||||
{Name: "validatingadmissionpolicies", Kind: "ValidatingAdmissionPolicy"},
|
||||
{Name: "mutatingadmissionpolicies", Kind: "MutatingAdmissionPolicy"},
|
||||
},
|
||||
},
|
||||
appsResources,
|
||||
},
|
||||
disabledPlugins: []string{},
|
||||
wantDisabledPlugins: []string{"ValidatingAdmissionPolicy"},
|
||||
wantDisabledPlugins: []string{"ValidatingAdmissionPolicy", "MutatingAdmissionPolicy"},
|
||||
},
|
||||
{
|
||||
name: "when there is no ValidatingAdmissionPolicy resource, and the ValidatingAdmissionPolicy plugin was explicitly disabled, then do not perform discovery, and just disable it",
|
||||
name: "when there are no are modern resource types, and all the modern resource type plugins were explicitly disabled, then do not perform discovery, and just disable them",
|
||||
availableAPIResources: []*metav1.APIResourceList{},
|
||||
discoveryErr: errors.New("total error from API discovery client"),
|
||||
disabledPlugins: []string{"MutatingAdmissionWebhook", "ValidatingAdmissionPolicy"},
|
||||
wantDisabledPlugins: []string{"MutatingAdmissionWebhook", "ValidatingAdmissionPolicy"},
|
||||
discoveryErr: errors.New("total error from API discovery client"), // shouldn't matter because discovery should have been skipped
|
||||
disabledPlugins: []string{"MutatingAdmissionWebhook", "ValidatingAdmissionPolicy", "MutatingAdmissionPolicy"},
|
||||
wantDisabledPlugins: []string{"MutatingAdmissionWebhook", "ValidatingAdmissionPolicy", "MutatingAdmissionPolicy"},
|
||||
},
|
||||
{
|
||||
name: "when there is no ValidatingAdmissionPolicy resource, and the ValidatingAdmissionPolicy plugin was not explicitly disabled, still disable it",
|
||||
name: "when there are no modern resource types, and the modern resource type plugins were not explicitly disabled, still disable them",
|
||||
availableAPIResources: []*metav1.APIResourceList{
|
||||
coreResources,
|
||||
oldStyleAdmissionResourcesWithoutValidatingAdmissionPolicies,
|
||||
oldStyleAdmissionResources,
|
||||
appsResources,
|
||||
},
|
||||
disabledPlugins: []string{"MutatingAdmissionWebhook", "NamespaceLifecycle"},
|
||||
wantDisabledPlugins: []string{"MutatingAdmissionWebhook", "NamespaceLifecycle", "ValidatingAdmissionPolicy"},
|
||||
wantDisabledPlugins: []string{"MutatingAdmissionWebhook", "NamespaceLifecycle", "ValidatingAdmissionPolicy", "MutatingAdmissionPolicy"},
|
||||
},
|
||||
{
|
||||
name: "when there is a total error returned by discovery",
|
||||
discoveryErr: errors.New("total error from API discovery client"),
|
||||
wantErr: "failed looking up availability of ValidatingAdmissionPolicy resource: failed to perform k8s API discovery: total error from API discovery client",
|
||||
wantErr: "failed to perform k8s API discovery for purpose of checking availability of admissionregistration.k8s.io resource types: total error from API discovery client",
|
||||
wantDisabledPlugins: nil,
|
||||
},
|
||||
{
|
||||
name: "when there is a partial error returned by discovery which does include the group of interest, then we cannot ignore the error, because we could not discover anything about that group",
|
||||
availableAPIResources: []*metav1.APIResourceList{
|
||||
coreResources,
|
||||
oldStyleAdmissionResourcesWithoutValidatingAdmissionPolicies,
|
||||
oldStyleAdmissionResources,
|
||||
appsResources,
|
||||
},
|
||||
discoveryErr: &discovery.ErrGroupDiscoveryFailed{Groups: map[schema.GroupVersion]error{
|
||||
schema.GroupVersion{Group: "someGroup", Version: "v1"}: errors.New("fake error for someGroup"),
|
||||
schema.GroupVersion{Group: "admissionregistration.k8s.io", Version: "v1"}: errors.New("fake error for admissionregistration"),
|
||||
}},
|
||||
wantErr: "failed looking up availability of ValidatingAdmissionPolicy resource: unable to retrieve the complete list of server APIs: admissionregistration.k8s.io/v1: fake error for admissionregistration, someGroup/v1: fake error for someGroup",
|
||||
wantErr: "failed to perform k8s API discovery for purpose of checking availability of admissionregistration.k8s.io resource types: unable to retrieve the complete list of server APIs: admissionregistration.k8s.io/v1: fake error for admissionregistration, someGroup/v1: fake error for someGroup",
|
||||
wantDisabledPlugins: nil,
|
||||
},
|
||||
{
|
||||
name: "when there is a partial error returned by discovery on an new-style cluster which does not include the group of interest, then we can ignore the error and use the default plugins",
|
||||
availableAPIResources: []*metav1.APIResourceList{
|
||||
coreResources,
|
||||
newStyleAdmissionResourcesWithValidatingAdmissionPolicies,
|
||||
newStyleAdmissionResources,
|
||||
appsResources,
|
||||
},
|
||||
discoveryErr: &discovery.ErrGroupDiscoveryFailed{Groups: map[schema.GroupVersion]error{
|
||||
@@ -220,15 +311,87 @@ func TestConfigureAdmissionPlugins(t *testing.T) {
|
||||
name: "when there is a partial error returned by discovery on an old-style cluster which does not include the group of interest, then we can ignore the error and customize the plugins",
|
||||
availableAPIResources: []*metav1.APIResourceList{
|
||||
coreResources,
|
||||
oldStyleAdmissionResourcesWithoutValidatingAdmissionPolicies,
|
||||
oldStyleAdmissionResources,
|
||||
appsResources,
|
||||
},
|
||||
discoveryErr: &discovery.ErrGroupDiscoveryFailed{Groups: map[schema.GroupVersion]error{
|
||||
schema.GroupVersion{Group: "someGroup", Version: "v1"}: errors.New("fake error for someGroup"),
|
||||
schema.GroupVersion{Group: "someOtherGroup", Version: "v1"}: errors.New("fake error for someOtherGroup"),
|
||||
}},
|
||||
wantDisabledPlugins: []string{"ValidatingAdmissionPolicy", "MutatingAdmissionPolicy"},
|
||||
},
|
||||
{
|
||||
name: "when both modern resource type plugins are explicitly disabled on a modern cluster, discovery is skipped",
|
||||
availableAPIResources: []*metav1.APIResourceList{
|
||||
coreResources,
|
||||
newStyleAdmissionResources,
|
||||
appsResources,
|
||||
},
|
||||
discoveryErr: errors.New("discovery should not have been called"), // would surface if the short-circuit were removed
|
||||
disabledPlugins: []string{"ValidatingAdmissionPolicy", "MutatingAdmissionPolicy"},
|
||||
wantDisabledPlugins: []string{"ValidatingAdmissionPolicy", "MutatingAdmissionPolicy"},
|
||||
},
|
||||
{
|
||||
name: "when only ValidatingAdmissionPolicy is explicitly disabled on a fully modern cluster, then MutatingAdmissionPolicy is not auto-disabled",
|
||||
availableAPIResources: []*metav1.APIResourceList{
|
||||
coreResources,
|
||||
newStyleAdmissionResources,
|
||||
appsResources,
|
||||
},
|
||||
disabledPlugins: []string{"ValidatingAdmissionPolicy"},
|
||||
wantDisabledPlugins: []string{"ValidatingAdmissionPolicy"},
|
||||
},
|
||||
{
|
||||
name: "when only MutatingAdmissionPolicy is explicitly disabled on a fully modern cluster, then ValidatingAdmissionPolicy is not auto-disabled",
|
||||
availableAPIResources: []*metav1.APIResourceList{
|
||||
coreResources,
|
||||
newStyleAdmissionResources,
|
||||
appsResources,
|
||||
},
|
||||
disabledPlugins: []string{"MutatingAdmissionPolicy"},
|
||||
wantDisabledPlugins: []string{"MutatingAdmissionPolicy"},
|
||||
},
|
||||
{
|
||||
name: "when a non-policy plugin is explicitly disabled on a modern cluster, only that plugin is disabled",
|
||||
availableAPIResources: []*metav1.APIResourceList{
|
||||
coreResources,
|
||||
newStyleAdmissionResources,
|
||||
appsResources,
|
||||
},
|
||||
disabledPlugins: []string{"NamespaceLifecycle"},
|
||||
wantDisabledPlugins: []string{"NamespaceLifecycle"},
|
||||
},
|
||||
{
|
||||
name: "when discovery returns nil resources along with a partial error, then the error is returned",
|
||||
availableAPIResources: nil,
|
||||
discoveryErr: &discovery.ErrGroupDiscoveryFailed{Groups: map[schema.GroupVersion]error{
|
||||
schema.GroupVersion{Group: "someGroup", Version: "v1"}: errors.New("fake error for someGroup"),
|
||||
}},
|
||||
wantErr: "failed to perform k8s API discovery for purpose of checking availability of admissionregistration.k8s.io resource types: unable to retrieve the complete list of server APIs: someGroup/v1: fake error for someGroup",
|
||||
wantDisabledPlugins: nil,
|
||||
},
|
||||
{
|
||||
name: "when there is a partial error returned by discovery which includes the admissionregistration group at a non-v1 version, then we cannot ignore the error",
|
||||
availableAPIResources: []*metav1.APIResourceList{
|
||||
coreResources,
|
||||
oldStyleAdmissionResources,
|
||||
appsResources,
|
||||
},
|
||||
discoveryErr: &discovery.ErrGroupDiscoveryFailed{Groups: map[schema.GroupVersion]error{
|
||||
schema.GroupVersion{Group: "admissionregistration.k8s.io", Version: "v1beta1"}: errors.New("fake error for admissionregistration v1beta1"),
|
||||
}},
|
||||
wantErr: "failed to perform k8s API discovery for purpose of checking availability of admissionregistration.k8s.io resource types: unable to retrieve the complete list of server APIs: admissionregistration.k8s.io/v1beta1: fake error for admissionregistration v1beta1",
|
||||
wantDisabledPlugins: nil,
|
||||
},
|
||||
{
|
||||
name: "when the admissionregistration group is entirely absent from discovery, then we disable both modern admission plugins",
|
||||
availableAPIResources: []*metav1.APIResourceList{
|
||||
coreResources,
|
||||
appsResources,
|
||||
},
|
||||
disabledPlugins: nil,
|
||||
wantDisabledPlugins: []string{"ValidatingAdmissionPolicy", "MutatingAdmissionPolicy"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
||||
Reference in New Issue
Block a user