Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move kubelet credential provider feature flag to beta and update the api's #108847

Merged
merged 1 commit into from Mar 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions api/api-rules/violation_exceptions.list
Expand Up @@ -353,6 +353,10 @@ API rule violation: list_type_missing,k8s.io/kubelet/config/v1alpha1,CredentialP
API rule violation: list_type_missing,k8s.io/kubelet/config/v1alpha1,CredentialProvider,Env
API rule violation: list_type_missing,k8s.io/kubelet/config/v1alpha1,CredentialProvider,MatchImages
API rule violation: list_type_missing,k8s.io/kubelet/config/v1alpha1,CredentialProviderConfig,Providers
API rule violation: list_type_missing,k8s.io/kubelet/config/v1beta1,CredentialProvider,Args
API rule violation: list_type_missing,k8s.io/kubelet/config/v1beta1,CredentialProvider,Env
API rule violation: list_type_missing,k8s.io/kubelet/config/v1beta1,CredentialProvider,MatchImages
API rule violation: list_type_missing,k8s.io/kubelet/config/v1beta1,CredentialProviderConfig,Providers
API rule violation: list_type_missing,k8s.io/kubelet/config/v1beta1,KubeletConfiguration,AllowedUnsafeSysctls
API rule violation: list_type_missing,k8s.io/kubelet/config/v1beta1,KubeletConfiguration,ClusterDNS
API rule violation: list_type_missing,k8s.io/kubelet/config/v1beta1,KubeletConfiguration,EnforceNodeAllocatable
Expand Down
46 changes: 46 additions & 0 deletions pkg/credentialprovider/plugin/config_test.go
Expand Up @@ -183,6 +183,52 @@ providers:
},
},
},
{
name: "v1beta1 config with multiple providers",
configData: `---
kind: CredentialProviderConfig
apiVersion: kubelet.config.k8s.io/v1beta1
providers:
- name: test1
matchImages:
- "registry.io/one"
defaultCacheDuration: 10m
apiVersion: credentialprovider.kubelet.k8s.io/v1beta1
- name: test2
matchImages:
- "registry.io/two"
defaultCacheDuration: 10m
apiVersion: credentialprovider.kubelet.k8s.io/v1beta1
args:
- --v=5
env:
- name: FOO
value: BAR`,

config: &kubeletconfig.CredentialProviderConfig{
Providers: []kubeletconfig.CredentialProvider{
{
Name: "test1",
MatchImages: []string{"registry.io/one"},
DefaultCacheDuration: &metav1.Duration{Duration: 10 * time.Minute},
APIVersion: "credentialprovider.kubelet.k8s.io/v1beta1",
},
{
Name: "test2",
MatchImages: []string{"registry.io/two"},
DefaultCacheDuration: &metav1.Duration{Duration: 10 * time.Minute},
APIVersion: "credentialprovider.kubelet.k8s.io/v1beta1",
Args: []string{"--v=5"},
Env: []kubeletconfig.ExecEnvVar{
{
Name: "FOO",
Value: "BAR",
},
},
},
},
},
},
{
name: "config with wrong Kind",
configData: `---
Expand Down
4 changes: 4 additions & 0 deletions pkg/credentialprovider/plugin/plugin.go
Expand Up @@ -39,9 +39,11 @@ import (
credentialproviderapi "k8s.io/kubelet/pkg/apis/credentialprovider"
"k8s.io/kubelet/pkg/apis/credentialprovider/install"
credentialproviderv1alpha1 "k8s.io/kubelet/pkg/apis/credentialprovider/v1alpha1"
credentialproviderv1beta1 "k8s.io/kubelet/pkg/apis/credentialprovider/v1beta1"
"k8s.io/kubernetes/pkg/credentialprovider"
kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
kubeletconfigv1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/config/v1alpha1"
kubeletconfigv1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/config/v1beta1"
"k8s.io/utils/clock"
)

Expand All @@ -56,13 +58,15 @@ var (

apiVersions = map[string]schema.GroupVersion{
credentialproviderv1alpha1.SchemeGroupVersion.String(): credentialproviderv1alpha1.SchemeGroupVersion,
credentialproviderv1beta1.SchemeGroupVersion.String(): credentialproviderv1beta1.SchemeGroupVersion,
}
)

adisky marked this conversation as resolved.
Show resolved Hide resolved
func init() {
install.Install(scheme)
kubeletconfig.AddToScheme(scheme)
kubeletconfigv1alpha1.AddToScheme(scheme)
kubeletconfigv1beta1.AddToScheme(scheme)
}

// RegisterCredentialProviderPlugins is called from kubelet to register external credential provider
Expand Down
42 changes: 36 additions & 6 deletions pkg/credentialprovider/plugin/plugin_test.go
Expand Up @@ -26,10 +26,12 @@ import (

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/rand"
"k8s.io/client-go/tools/cache"
credentialproviderapi "k8s.io/kubelet/pkg/apis/credentialprovider"
credentialproviderv1alpha1 "k8s.io/kubelet/pkg/apis/credentialprovider/v1alpha1"
credentialproviderv1beta1 "k8s.io/kubelet/pkg/apis/credentialprovider/v1beta1"
"k8s.io/kubernetes/pkg/credentialprovider"
kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
"k8s.io/utils/clock"
Expand Down Expand Up @@ -408,17 +410,28 @@ func Test_getCachedCredentials(t *testing.T) {
func Test_encodeRequest(t *testing.T) {
testcases := []struct {
name string
apiVersion string
apiVersion schema.GroupVersion
request *credentialproviderapi.CredentialProviderRequest
expectedData []byte
expectedErr bool
}{
{
name: "successful",
name: "successful with v1alpha1",
apiVersion: credentialproviderv1alpha1.SchemeGroupVersion,
request: &credentialproviderapi.CredentialProviderRequest{
Image: "test.registry.io/foobar",
},
expectedData: []byte(`{"kind":"CredentialProviderRequest","apiVersion":"credentialprovider.kubelet.k8s.io/v1alpha1","image":"test.registry.io/foobar"}
adisky marked this conversation as resolved.
Show resolved Hide resolved
`),
expectedErr: false,
},
{
name: "successful with v1beta1",
apiVersion: credentialproviderv1beta1.SchemeGroupVersion,
request: &credentialproviderapi.CredentialProviderRequest{
Image: "test.registry.io/foobar",
},
expectedData: []byte(`{"kind":"CredentialProviderRequest","apiVersion":"credentialprovider.kubelet.k8s.io/v1beta1","image":"test.registry.io/foobar"}
`),
expectedErr: false,
},
Expand All @@ -433,7 +446,7 @@ func Test_encodeRequest(t *testing.T) {
}

e := &execPlugin{
encoder: codecs.EncoderForVersion(info.Serializer, credentialproviderv1alpha1.SchemeGroupVersion),
encoder: codecs.EncoderForVersion(info.Serializer, testcase.apiVersion),
}

data, err := e.encodeRequest(testcase.request)
Expand Down Expand Up @@ -462,7 +475,24 @@ func Test_decodeResponse(t *testing.T) {
expectedErr bool
}{
{
name: "success",
name: "success with v1beta1",
data: []byte(`{"kind":"CredentialProviderResponse","apiVersion":"credentialprovider.kubelet.k8s.io/v1beta1","cacheKeyType":"Registry","cacheDuration":"1m","auth":{"*.registry.io":{"username":"user","password":"password"}}}`),
adisky marked this conversation as resolved.
Show resolved Hide resolved
expectedResponse: &credentialproviderapi.CredentialProviderResponse{
CacheKeyType: credentialproviderapi.RegistryPluginCacheKeyType,
CacheDuration: &metav1.Duration{
Duration: time.Minute,
},
Auth: map[string]credentialproviderapi.AuthConfig{
"*.registry.io": {
Username: "user",
Password: "password",
},
},
},
expectedErr: false,
},
{
name: "success with v1alpha1",
data: []byte(`{"kind":"CredentialProviderResponse","apiVersion":"credentialprovider.kubelet.k8s.io/v1alpha1","cacheKeyType":"Registry","cacheDuration":"1m","auth":{"*.registry.io":{"username":"user","password":"password"}}}`),
expectedResponse: &credentialproviderapi.CredentialProviderResponse{
CacheKeyType: credentialproviderapi.RegistryPluginCacheKeyType,
Expand All @@ -480,13 +510,13 @@ func Test_decodeResponse(t *testing.T) {
},
{
name: "wrong Kind",
data: []byte(`{"kind":"WrongKind","apiVersion":"credentialprovider.kubelet.k8s.io/v1alpha1","cacheKeyType":"Registry","cacheDuration":"1m","auth":{"*.registry.io":{"username":"user","password":"password"}}}`),
data: []byte(`{"kind":"WrongKind","apiVersion":"credentialprovider.kubelet.k8s.io/v1beta1","cacheKeyType":"Registry","cacheDuration":"1m","auth":{"*.registry.io":{"username":"user","password":"password"}}}`),
expectedResponse: nil,
expectedErr: true,
},
{
name: "wrong Group",
data: []byte(`{"kind":"CredentialProviderResponse","apiVersion":"foobar.kubelet.k8s.io/v1alpha1","cacheKeyType":"Registry","cacheDuration":"1m","auth":{"*.registry.io":{"username":"user","password":"password"}}}`),
data: []byte(`{"kind":"CredentialProviderResponse","apiVersion":"foobar.kubelet.k8s.io/v1beta1","cacheKeyType":"Registry","cacheDuration":"1m","auth":{"*.registry.io":{"username":"user","password":"password"}}}`),
expectedResponse: nil,
expectedErr: true,
},
Expand Down
5 changes: 3 additions & 2 deletions pkg/features/kube_features.go
Expand Up @@ -524,8 +524,9 @@ const (
// Lock to default and remove after v1.22 based on user feedback that should be reflected in KEP #1972 update
ExecProbeTimeout featuregate.Feature = "ExecProbeTimeout"

// owner: @andrewsykim
// owner: @andrewsykim @adisky
// alpha: v1.20
// beta: v1.24
//
// Enable kubelet exec plugins for image pull credentials.
KubeletCredentialProviders featuregate.Feature = "KubeletCredentialProviders"
Expand Down Expand Up @@ -917,7 +918,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
HPAContainerMetrics: {Default: false, PreRelease: featuregate.Alpha},
SizeMemoryBackedVolumes: {Default: true, PreRelease: featuregate.Beta},
ExecProbeTimeout: {Default: true, PreRelease: featuregate.GA}, // lock to default and remove after v1.22 based on KEP #1972 update
KubeletCredentialProviders: {Default: false, PreRelease: featuregate.Alpha},
KubeletCredentialProviders: {Default: true, PreRelease: featuregate.Beta},
GracefulNodeShutdown: {Default: true, PreRelease: featuregate.Beta},
GracefulNodeShutdownBasedOnPodPriority: {Default: true, PreRelease: featuregate.Beta},
ServiceLBNodePortControl: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.26
Expand Down
157 changes: 157 additions & 0 deletions pkg/generated/openapi/zz_generated.openapi.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

@@ -0,0 +1,3 @@
apiVersion: kubelet.config.k8s.io/v1beta1
kind: CredentialProviderConfig
providers: null
@@ -0,0 +1,2 @@
kind: CredentialProviderConfig
apiVersion: kubelet.config.k8s.io/v1beta1
@@ -0,0 +1,3 @@
apiVersion: kubelet.config.k8s.io/v1beta1
kind: CredentialProviderConfig
providers: null
1 change: 1 addition & 0 deletions pkg/kubelet/apis/config/types.go
Expand Up @@ -579,6 +579,7 @@ type CredentialProvider struct {
// Required input version of the exec CredentialProviderRequest. The returned CredentialProviderResponse
// MUST use the same encoding version as the input. Current supported values are:
// - credentialprovider.kubelet.k8s.io/v1alpha1
// - credentialprovider.kubelet.k8s.io/v1beta1
APIVersion string

// Arguments to pass to the command when executing it.
Expand Down