diff --git a/api/api-rules/violation_exceptions.list b/api/api-rules/violation_exceptions.list index b4131c24db3..0bd369813bd 100644 --- a/api/api-rules/violation_exceptions.list +++ b/api/api-rules/violation_exceptions.list @@ -349,6 +349,10 @@ API rule violation: list_type_missing,k8s.io/kube-scheduler/config/v1beta2,Exten API rule violation: list_type_missing,k8s.io/kube-scheduler/config/v1beta3,ExtenderTLSConfig,CAData API rule violation: list_type_missing,k8s.io/kube-scheduler/config/v1beta3,ExtenderTLSConfig,CertData API rule violation: list_type_missing,k8s.io/kube-scheduler/config/v1beta3,ExtenderTLSConfig,KeyData +API rule violation: list_type_missing,k8s.io/kubelet/config/v1,CredentialProvider,Args +API rule violation: list_type_missing,k8s.io/kubelet/config/v1,CredentialProvider,Env +API rule violation: list_type_missing,k8s.io/kubelet/config/v1,CredentialProvider,MatchImages +API rule violation: list_type_missing,k8s.io/kubelet/config/v1,CredentialProviderConfig,Providers API rule violation: list_type_missing,k8s.io/kubelet/config/v1alpha1,CredentialProvider,Args 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 diff --git a/hack/.import-aliases b/hack/.import-aliases index 8dfdba37eb7..0d722127b68 100644 --- a/hack/.import-aliases +++ b/hack/.import-aliases @@ -45,6 +45,7 @@ "k8s.io/kubelet/apis/stats/v1alpha1": "kubeletstatsv1alpha1", "k8s.io/kubernetes/pkg/controller/apis/config/v1alpha1": "controllerconfigv1alpha1", "k8s.io/kubernetes/pkg/kubelet/apis/config/v1beta1": "kubeletconfigv1beta1", + "k8s.io/kubernetes/pkg/kubelet/apis/config/v1": "kubeletconfigv1", "k8s.io/kubelet/pkg/apis/deviceplugin/v1alpha": "kubeletdevicepluginv1alpha", "k8s.io/kubelet/pkg/apis/deviceplugin/v1beta1": "kubeletdevicepluginv1beta1", "k8s.io/kubelet/pkg/apis/pluginregistration/v1": "kubeletpluginregistrationv1", diff --git a/pkg/credentialprovider/plugin/config_test.go b/pkg/credentialprovider/plugin/config_test.go index 6e6ef0f57d4..940109cc44d 100644 --- a/pkg/credentialprovider/plugin/config_test.go +++ b/pkg/credentialprovider/plugin/config_test.go @@ -229,6 +229,52 @@ providers: }, }, }, + { + name: "v1 config with multiple providers", + configData: `--- +kind: CredentialProviderConfig +apiVersion: kubelet.config.k8s.io/v1 +providers: + - name: test1 + matchImages: + - "registry.io/one" + defaultCacheDuration: 10m + apiVersion: credentialprovider.kubelet.k8s.io/v1 + - name: test2 + matchImages: + - "registry.io/two" + defaultCacheDuration: 10m + apiVersion: credentialprovider.kubelet.k8s.io/v1 + 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/v1", + }, + { + Name: "test2", + MatchImages: []string{"registry.io/two"}, + DefaultCacheDuration: &metav1.Duration{Duration: 10 * time.Minute}, + APIVersion: "credentialprovider.kubelet.k8s.io/v1", + Args: []string{"--v=5"}, + Env: []kubeletconfig.ExecEnvVar{ + { + Name: "FOO", + Value: "BAR", + }, + }, + }, + }, + }, + }, { name: "config with wrong Kind", configData: `--- diff --git a/pkg/credentialprovider/plugin/plugin.go b/pkg/credentialprovider/plugin/plugin.go index 5e6db98b465..dc458634eeb 100644 --- a/pkg/credentialprovider/plugin/plugin.go +++ b/pkg/credentialprovider/plugin/plugin.go @@ -38,10 +38,12 @@ import ( "k8s.io/klog/v2" credentialproviderapi "k8s.io/kubelet/pkg/apis/credentialprovider" "k8s.io/kubelet/pkg/apis/credentialprovider/install" + credentialproviderv1 "k8s.io/kubelet/pkg/apis/credentialprovider/v1" 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" + kubeletconfigv1 "k8s.io/kubernetes/pkg/kubelet/apis/config/v1" kubeletconfigv1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/config/v1alpha1" kubeletconfigv1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/config/v1beta1" "k8s.io/utils/clock" @@ -59,6 +61,7 @@ var ( apiVersions = map[string]schema.GroupVersion{ credentialproviderv1alpha1.SchemeGroupVersion.String(): credentialproviderv1alpha1.SchemeGroupVersion, credentialproviderv1beta1.SchemeGroupVersion.String(): credentialproviderv1beta1.SchemeGroupVersion, + credentialproviderv1.SchemeGroupVersion.String(): credentialproviderv1.SchemeGroupVersion, } ) @@ -67,6 +70,7 @@ func init() { kubeletconfig.AddToScheme(scheme) kubeletconfigv1alpha1.AddToScheme(scheme) kubeletconfigv1beta1.AddToScheme(scheme) + kubeletconfigv1.AddToScheme(scheme) } // RegisterCredentialProviderPlugins is called from kubelet to register external credential provider diff --git a/pkg/credentialprovider/plugin/plugin_test.go b/pkg/credentialprovider/plugin/plugin_test.go index 68d0bee804c..1f02992b11d 100644 --- a/pkg/credentialprovider/plugin/plugin_test.go +++ b/pkg/credentialprovider/plugin/plugin_test.go @@ -30,6 +30,7 @@ import ( "k8s.io/apimachinery/pkg/util/rand" "k8s.io/client-go/tools/cache" credentialproviderapi "k8s.io/kubelet/pkg/apis/credentialprovider" + credentialproviderv1 "k8s.io/kubelet/pkg/apis/credentialprovider/v1" credentialproviderv1alpha1 "k8s.io/kubelet/pkg/apis/credentialprovider/v1alpha1" credentialproviderv1beta1 "k8s.io/kubelet/pkg/apis/credentialprovider/v1beta1" "k8s.io/kubernetes/pkg/credentialprovider" @@ -432,6 +433,16 @@ func Test_encodeRequest(t *testing.T) { Image: "test.registry.io/foobar", }, expectedData: []byte(`{"kind":"CredentialProviderRequest","apiVersion":"credentialprovider.kubelet.k8s.io/v1beta1","image":"test.registry.io/foobar"} +`), + expectedErr: false, + }, + { + name: "successful with v1", + apiVersion: credentialproviderv1.SchemeGroupVersion, + request: &credentialproviderapi.CredentialProviderRequest{ + Image: "test.registry.io/foobar", + }, + expectedData: []byte(`{"kind":"CredentialProviderRequest","apiVersion":"credentialprovider.kubelet.k8s.io/v1","image":"test.registry.io/foobar"} `), expectedErr: false, }, @@ -474,6 +485,23 @@ func Test_decodeResponse(t *testing.T) { expectedResponse *credentialproviderapi.CredentialProviderResponse expectedErr bool }{ + { + name: "success with v1", + data: []byte(`{"kind":"CredentialProviderResponse","apiVersion":"credentialprovider.kubelet.k8s.io/v1","cacheKeyType":"Registry","cacheDuration":"1m","auth":{"*.registry.io":{"username":"user","password":"password"}}}`), + 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 v1beta1", data: []byte(`{"kind":"CredentialProviderResponse","apiVersion":"credentialprovider.kubelet.k8s.io/v1beta1","cacheKeyType":"Registry","cacheDuration":"1m","auth":{"*.registry.io":{"username":"user","password":"password"}}}`), diff --git a/pkg/features/kube_features.go b/pkg/features/kube_features.go index 80d42b9c6d2..ec228f554d7 100644 --- a/pkg/features/kube_features.go +++ b/pkg/features/kube_features.go @@ -446,9 +446,10 @@ const ( // yet. JobTrackingWithFinalizers featuregate.Feature = "JobTrackingWithFinalizers" - // owner: @andrewsykim @adisky + // owner: @andrewsykim @adisky @ndixita // alpha: v1.20 // beta: v1.24 + // GA: v1.26 // // Enable kubelet exec plugins for image pull credentials. KubeletCredentialProviders featuregate.Feature = "KubeletCredentialProviders" @@ -911,7 +912,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS JobTrackingWithFinalizers: {Default: true, PreRelease: featuregate.Beta}, - KubeletCredentialProviders: {Default: true, PreRelease: featuregate.Beta}, + KubeletCredentialProviders: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.28 KubeletInUserNamespace: {Default: false, PreRelease: featuregate.Alpha}, diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index 52d093a1c3e..86ae7c1b7c3 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -1090,6 +1090,9 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "k8s.io/kube-scheduler/config/v1beta3.ScoringStrategy": schema_k8sio_kube_scheduler_config_v1beta3_ScoringStrategy(ref), "k8s.io/kube-scheduler/config/v1beta3.UtilizationShapePoint": schema_k8sio_kube_scheduler_config_v1beta3_UtilizationShapePoint(ref), "k8s.io/kube-scheduler/config/v1beta3.VolumeBindingArgs": schema_k8sio_kube_scheduler_config_v1beta3_VolumeBindingArgs(ref), + "k8s.io/kubelet/config/v1.CredentialProvider": schema_k8sio_kubelet_config_v1_CredentialProvider(ref), + "k8s.io/kubelet/config/v1.CredentialProviderConfig": schema_k8sio_kubelet_config_v1_CredentialProviderConfig(ref), + "k8s.io/kubelet/config/v1.ExecEnvVar": schema_k8sio_kubelet_config_v1_ExecEnvVar(ref), "k8s.io/kubelet/config/v1alpha1.CredentialProvider": schema_k8sio_kubelet_config_v1alpha1_CredentialProvider(ref), "k8s.io/kubelet/config/v1alpha1.CredentialProviderConfig": schema_k8sio_kubelet_config_v1alpha1_CredentialProviderConfig(ref), "k8s.io/kubelet/config/v1alpha1.ExecEnvVar": schema_k8sio_kubelet_config_v1alpha1_ExecEnvVar(ref), @@ -54728,6 +54731,160 @@ func schema_k8sio_kube_scheduler_config_v1beta3_VolumeBindingArgs(ref common.Ref } } +func schema_k8sio_kubelet_config_v1_CredentialProvider(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "CredentialProvider represents an exec plugin to be invoked by the kubelet. The plugin is only invoked when an image being pulled matches the images handled by the plugin (see matchImages).", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "name": { + SchemaProps: spec.SchemaProps{ + Description: "name is the required name of the credential provider. It must match the name of the provider executable as seen by the kubelet. The executable must be in the kubelet's bin directory (set by the --image-credential-provider-bin-dir flag).", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "matchImages": { + SchemaProps: spec.SchemaProps{ + Description: "matchImages is a required list of strings used to match against images in order to determine if this provider should be invoked. If one of the strings matches the requested image from the kubelet, the plugin will be invoked and given a chance to provide credentials. Images are expected to contain the registry domain and URL path.\n\nEach entry in matchImages is a pattern which can optionally contain a port and a path. Globs can be used in the domain, but not in the port or the path. Globs are supported as subdomains like '*.k8s.io' or 'k8s.*.io', and top-level-domains such as 'k8s.*'. Matching partial subdomains like 'app*.k8s.io' is also supported. Each glob can only match a single subdomain segment, so *.io does not match *.k8s.io.\n\nA match exists between an image and a matchImage when all of the below are true: - Both contain the same number of domain parts and each part matches. - The URL path of an imageMatch must be a prefix of the target image URL path. - If the imageMatch contains a port, then the port must match in the image as well.\n\nExample values of matchImages:\n - 123456789.dkr.ecr.us-east-1.amazonaws.com\n - *.azurecr.io\n - gcr.io\n - *.*.registry.io\n - registry.io:8080/path", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "defaultCacheDuration": { + SchemaProps: spec.SchemaProps{ + Description: "defaultCacheDuration is the default duration the plugin will cache credentials in-memory if a cache duration is not provided in the plugin response. This field is required.", + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"), + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Description: "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/v1", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "args": { + SchemaProps: spec.SchemaProps{ + Description: "Arguments to pass to the command when executing it.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "env": { + SchemaProps: spec.SchemaProps{ + Description: "Env defines additional environment variables to expose to the process. These are unioned with the host's environment, as well as variables client-go uses to pass argument to the plugin.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/kubelet/config/v1.ExecEnvVar"), + }, + }, + }, + }, + }, + }, + Required: []string{"name", "matchImages", "defaultCacheDuration", "apiVersion"}, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/apis/meta/v1.Duration", "k8s.io/kubelet/config/v1.ExecEnvVar"}, + } +} + +func schema_k8sio_kubelet_config_v1_CredentialProviderConfig(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "CredentialProviderConfig is the configuration containing information about each exec credential provider. Kubelet reads this configuration from disk and enables each provider as specified by the CredentialProvider type.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + Type: []string{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + Type: []string{"string"}, + Format: "", + }, + }, + "providers": { + SchemaProps: spec.SchemaProps{ + Description: "providers is a list of credential provider plugins that will be enabled by the kubelet. Multiple providers may match against a single image, in which case credentials from all providers will be returned to the kubelet. If multiple providers are called for a single image, the results are combined. If providers return overlapping auth keys, the value from the provider earlier in this list is used.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/kubelet/config/v1.CredentialProvider"), + }, + }, + }, + }, + }, + }, + Required: []string{"providers"}, + }, + }, + Dependencies: []string{ + "k8s.io/kubelet/config/v1.CredentialProvider"}, + } +} + +func schema_k8sio_kubelet_config_v1_ExecEnvVar(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ExecEnvVar is used for setting environment variables when executing an exec-based credential plugin.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "name": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "value": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"name", "value"}, + }, + }, + } +} + func schema_k8sio_kubelet_config_v1alpha1_CredentialProvider(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ diff --git a/pkg/kubelet/apis/config/scheme/scheme.go b/pkg/kubelet/apis/config/scheme/scheme.go index 0a5ae0b5eea..a8120b5436c 100644 --- a/pkg/kubelet/apis/config/scheme/scheme.go +++ b/pkg/kubelet/apis/config/scheme/scheme.go @@ -20,6 +20,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/serializer" kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config" + kubeletconfigv1 "k8s.io/kubernetes/pkg/kubelet/apis/config/v1" kubeletconfigv1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/config/v1beta1" ) @@ -36,6 +37,9 @@ func NewSchemeAndCodecs(mutators ...serializer.CodecFactoryOptionsMutator) (*run if err := kubeletconfigv1beta1.AddToScheme(scheme); err != nil { return nil, nil, err } + if err := kubeletconfigv1.AddToScheme(scheme); err != nil { + return nil, nil, err + } codecs := serializer.NewCodecFactory(scheme, mutators...) return scheme, &codecs, nil } diff --git a/pkg/kubelet/apis/config/scheme/testdata/CredentialProviderConfig/after/v1.yaml b/pkg/kubelet/apis/config/scheme/testdata/CredentialProviderConfig/after/v1.yaml new file mode 100644 index 00000000000..782a369be84 --- /dev/null +++ b/pkg/kubelet/apis/config/scheme/testdata/CredentialProviderConfig/after/v1.yaml @@ -0,0 +1,3 @@ +apiVersion: kubelet.config.k8s.io/v1 +kind: CredentialProviderConfig +providers: null diff --git a/pkg/kubelet/apis/config/scheme/testdata/CredentialProviderConfig/before/v1.yaml b/pkg/kubelet/apis/config/scheme/testdata/CredentialProviderConfig/before/v1.yaml new file mode 100644 index 00000000000..c4bacc56b44 --- /dev/null +++ b/pkg/kubelet/apis/config/scheme/testdata/CredentialProviderConfig/before/v1.yaml @@ -0,0 +1,2 @@ +kind: CredentialProviderConfig +apiVersion: kubelet.config.k8s.io/v1 \ No newline at end of file diff --git a/pkg/kubelet/apis/config/scheme/testdata/CredentialProviderConfig/roundtrip/default/v1.yaml b/pkg/kubelet/apis/config/scheme/testdata/CredentialProviderConfig/roundtrip/default/v1.yaml new file mode 100644 index 00000000000..782a369be84 --- /dev/null +++ b/pkg/kubelet/apis/config/scheme/testdata/CredentialProviderConfig/roundtrip/default/v1.yaml @@ -0,0 +1,3 @@ +apiVersion: kubelet.config.k8s.io/v1 +kind: CredentialProviderConfig +providers: null diff --git a/pkg/kubelet/apis/config/types.go b/pkg/kubelet/apis/config/types.go index c57e71f0f7d..e4e079faaf0 100644 --- a/pkg/kubelet/apis/config/types.go +++ b/pkg/kubelet/apis/config/types.go @@ -595,6 +595,7 @@ type CredentialProvider struct { // MUST use the same encoding version as the input. Current supported values are: // - credentialprovider.kubelet.k8s.io/v1alpha1 // - credentialprovider.kubelet.k8s.io/v1beta1 + // - credentialprovider.kubelet.k8s.io/v1 APIVersion string // Arguments to pass to the command when executing it. diff --git a/pkg/kubelet/apis/config/v1/doc.go b/pkg/kubelet/apis/config/v1/doc.go new file mode 100644 index 00000000000..713be2de60a --- /dev/null +++ b/pkg/kubelet/apis/config/v1/doc.go @@ -0,0 +1,24 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// +k8s:deepcopy-gen=package +// +k8s:conversion-gen=k8s.io/kubernetes/pkg/kubelet/apis/config +// +k8s:conversion-gen-external-types=k8s.io/kubelet/config/v1 +// +k8s:defaulter-gen=TypeMeta +// +k8s:defaulter-gen-input=k8s.io/kubelet/config/v1 +// +groupName=kubelet.config.k8s.io + +package v1 // import "k8s.io/kubernetes/pkg/kubelet/apis/config/v1" diff --git a/pkg/kubelet/apis/config/v1/register.go b/pkg/kubelet/apis/config/v1/register.go new file mode 100644 index 00000000000..efd8f35fa95 --- /dev/null +++ b/pkg/kubelet/apis/config/v1/register.go @@ -0,0 +1,36 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + kubeletconfigv1 "k8s.io/kubelet/config/v1" +) + +// GroupName is the group name used in this package +const GroupName = "kubelet.config.k8s.io" + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"} + +var ( + // localSchemeBuilder extends the SchemeBuilder instance with the external types. In this package, + // defaulting and conversion init funcs are registered as well. + localSchemeBuilder = &kubeletconfigv1.SchemeBuilder + // AddToScheme is a global function that registers this API group & version to a scheme + AddToScheme = localSchemeBuilder.AddToScheme +) diff --git a/pkg/kubelet/apis/config/v1/zz_generated.conversion.go b/pkg/kubelet/apis/config/v1/zz_generated.conversion.go new file mode 100644 index 00000000000..8c6ac6e0468 --- /dev/null +++ b/pkg/kubelet/apis/config/v1/zz_generated.conversion.go @@ -0,0 +1,144 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by conversion-gen. DO NOT EDIT. + +package v1 + +import ( + unsafe "unsafe" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + conversion "k8s.io/apimachinery/pkg/conversion" + runtime "k8s.io/apimachinery/pkg/runtime" + v1 "k8s.io/kubelet/config/v1" + config "k8s.io/kubernetes/pkg/kubelet/apis/config" +) + +func init() { + localSchemeBuilder.Register(RegisterConversions) +} + +// RegisterConversions adds conversion functions to the given scheme. +// Public to allow building arbitrary schemes. +func RegisterConversions(s *runtime.Scheme) error { + if err := s.AddGeneratedConversionFunc((*v1.CredentialProvider)(nil), (*config.CredentialProvider)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1_CredentialProvider_To_config_CredentialProvider(a.(*v1.CredentialProvider), b.(*config.CredentialProvider), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.CredentialProvider)(nil), (*v1.CredentialProvider)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_CredentialProvider_To_v1_CredentialProvider(a.(*config.CredentialProvider), b.(*v1.CredentialProvider), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1.CredentialProviderConfig)(nil), (*config.CredentialProviderConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1_CredentialProviderConfig_To_config_CredentialProviderConfig(a.(*v1.CredentialProviderConfig), b.(*config.CredentialProviderConfig), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.CredentialProviderConfig)(nil), (*v1.CredentialProviderConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_CredentialProviderConfig_To_v1_CredentialProviderConfig(a.(*config.CredentialProviderConfig), b.(*v1.CredentialProviderConfig), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1.ExecEnvVar)(nil), (*config.ExecEnvVar)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1_ExecEnvVar_To_config_ExecEnvVar(a.(*v1.ExecEnvVar), b.(*config.ExecEnvVar), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.ExecEnvVar)(nil), (*v1.ExecEnvVar)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_ExecEnvVar_To_v1_ExecEnvVar(a.(*config.ExecEnvVar), b.(*v1.ExecEnvVar), scope) + }); err != nil { + return err + } + return nil +} + +func autoConvert_v1_CredentialProvider_To_config_CredentialProvider(in *v1.CredentialProvider, out *config.CredentialProvider, s conversion.Scope) error { + out.Name = in.Name + out.MatchImages = *(*[]string)(unsafe.Pointer(&in.MatchImages)) + out.DefaultCacheDuration = (*metav1.Duration)(unsafe.Pointer(in.DefaultCacheDuration)) + out.APIVersion = in.APIVersion + out.Args = *(*[]string)(unsafe.Pointer(&in.Args)) + out.Env = *(*[]config.ExecEnvVar)(unsafe.Pointer(&in.Env)) + return nil +} + +// Convert_v1_CredentialProvider_To_config_CredentialProvider is an autogenerated conversion function. +func Convert_v1_CredentialProvider_To_config_CredentialProvider(in *v1.CredentialProvider, out *config.CredentialProvider, s conversion.Scope) error { + return autoConvert_v1_CredentialProvider_To_config_CredentialProvider(in, out, s) +} + +func autoConvert_config_CredentialProvider_To_v1_CredentialProvider(in *config.CredentialProvider, out *v1.CredentialProvider, s conversion.Scope) error { + out.Name = in.Name + out.MatchImages = *(*[]string)(unsafe.Pointer(&in.MatchImages)) + out.DefaultCacheDuration = (*metav1.Duration)(unsafe.Pointer(in.DefaultCacheDuration)) + out.APIVersion = in.APIVersion + out.Args = *(*[]string)(unsafe.Pointer(&in.Args)) + out.Env = *(*[]v1.ExecEnvVar)(unsafe.Pointer(&in.Env)) + return nil +} + +// Convert_config_CredentialProvider_To_v1_CredentialProvider is an autogenerated conversion function. +func Convert_config_CredentialProvider_To_v1_CredentialProvider(in *config.CredentialProvider, out *v1.CredentialProvider, s conversion.Scope) error { + return autoConvert_config_CredentialProvider_To_v1_CredentialProvider(in, out, s) +} + +func autoConvert_v1_CredentialProviderConfig_To_config_CredentialProviderConfig(in *v1.CredentialProviderConfig, out *config.CredentialProviderConfig, s conversion.Scope) error { + out.Providers = *(*[]config.CredentialProvider)(unsafe.Pointer(&in.Providers)) + return nil +} + +// Convert_v1_CredentialProviderConfig_To_config_CredentialProviderConfig is an autogenerated conversion function. +func Convert_v1_CredentialProviderConfig_To_config_CredentialProviderConfig(in *v1.CredentialProviderConfig, out *config.CredentialProviderConfig, s conversion.Scope) error { + return autoConvert_v1_CredentialProviderConfig_To_config_CredentialProviderConfig(in, out, s) +} + +func autoConvert_config_CredentialProviderConfig_To_v1_CredentialProviderConfig(in *config.CredentialProviderConfig, out *v1.CredentialProviderConfig, s conversion.Scope) error { + out.Providers = *(*[]v1.CredentialProvider)(unsafe.Pointer(&in.Providers)) + return nil +} + +// Convert_config_CredentialProviderConfig_To_v1_CredentialProviderConfig is an autogenerated conversion function. +func Convert_config_CredentialProviderConfig_To_v1_CredentialProviderConfig(in *config.CredentialProviderConfig, out *v1.CredentialProviderConfig, s conversion.Scope) error { + return autoConvert_config_CredentialProviderConfig_To_v1_CredentialProviderConfig(in, out, s) +} + +func autoConvert_v1_ExecEnvVar_To_config_ExecEnvVar(in *v1.ExecEnvVar, out *config.ExecEnvVar, s conversion.Scope) error { + out.Name = in.Name + out.Value = in.Value + return nil +} + +// Convert_v1_ExecEnvVar_To_config_ExecEnvVar is an autogenerated conversion function. +func Convert_v1_ExecEnvVar_To_config_ExecEnvVar(in *v1.ExecEnvVar, out *config.ExecEnvVar, s conversion.Scope) error { + return autoConvert_v1_ExecEnvVar_To_config_ExecEnvVar(in, out, s) +} + +func autoConvert_config_ExecEnvVar_To_v1_ExecEnvVar(in *config.ExecEnvVar, out *v1.ExecEnvVar, s conversion.Scope) error { + out.Name = in.Name + out.Value = in.Value + return nil +} + +// Convert_config_ExecEnvVar_To_v1_ExecEnvVar is an autogenerated conversion function. +func Convert_config_ExecEnvVar_To_v1_ExecEnvVar(in *config.ExecEnvVar, out *v1.ExecEnvVar, s conversion.Scope) error { + return autoConvert_config_ExecEnvVar_To_v1_ExecEnvVar(in, out, s) +} diff --git a/pkg/kubelet/apis/config/v1/zz_generated.deepcopy.go b/pkg/kubelet/apis/config/v1/zz_generated.deepcopy.go new file mode 100644 index 00000000000..87181b43048 --- /dev/null +++ b/pkg/kubelet/apis/config/v1/zz_generated.deepcopy.go @@ -0,0 +1,22 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1 diff --git a/pkg/kubelet/apis/config/v1/zz_generated.defaults.go b/pkg/kubelet/apis/config/v1/zz_generated.defaults.go new file mode 100644 index 00000000000..dac177e93bd --- /dev/null +++ b/pkg/kubelet/apis/config/v1/zz_generated.defaults.go @@ -0,0 +1,33 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by defaulter-gen. DO NOT EDIT. + +package v1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// RegisterDefaults adds defaulters functions to the given scheme. +// Public to allow building arbitrary schemes. +// All generated defaulters are covering - they call all nested defaulters. +func RegisterDefaults(scheme *runtime.Scheme) error { + return nil +} diff --git a/pkg/kubelet/kuberuntime/kuberuntime_manager.go b/pkg/kubelet/kuberuntime/kuberuntime_manager.go index 89eaf8b4fcd..634c1bdcd0e 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_manager.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_manager.go @@ -32,7 +32,6 @@ import ( kubetypes "k8s.io/apimachinery/pkg/types" utilruntime "k8s.io/apimachinery/pkg/util/runtime" utilversion "k8s.io/apimachinery/pkg/util/version" - utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/tools/record" ref "k8s.io/client-go/tools/reference" "k8s.io/client-go/util/flowcontrol" @@ -42,7 +41,6 @@ import ( "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/credentialprovider" "k8s.io/kubernetes/pkg/credentialprovider/plugin" - "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/kubelet/cm" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/kubelet/events" @@ -251,12 +249,7 @@ func NewKubeGenericRuntimeManager( } } - if !utilfeature.DefaultFeatureGate.Enabled(features.KubeletCredentialProviders) && (imageCredentialProviderConfigFile != "" || imageCredentialProviderBinDir != "") { - klog.InfoS("Flags --image-credential-provider-config or --image-credential-provider-bin-dir were set but the feature gate was disabled, these flags will be ignored", - "featureGate", features.KubeletCredentialProviders) - } - - if utilfeature.DefaultFeatureGate.Enabled(features.KubeletCredentialProviders) && (imageCredentialProviderConfigFile != "" || imageCredentialProviderBinDir != "") { + if imageCredentialProviderConfigFile != "" || imageCredentialProviderBinDir != "" { if err := plugin.RegisterCredentialProviderPlugins(imageCredentialProviderConfigFile, imageCredentialProviderBinDir); err != nil { klog.ErrorS(err, "Failed to register CRI auth plugins") os.Exit(1) diff --git a/staging/src/k8s.io/component-base/config/testing/apigroup.go b/staging/src/k8s.io/component-base/config/testing/apigroup.go index 2759f6524da..ead01ad2bc6 100644 --- a/staging/src/k8s.io/component-base/config/testing/apigroup.go +++ b/staging/src/k8s.io/component-base/config/testing/apigroup.go @@ -56,11 +56,10 @@ const ( ) var testingFuncs = map[string]testingFunc{ - verifyTagNaming: verifyTagNamingFunc, - verifyGroupNameSuffix: verifyGroupNameSuffixFunc, - verifyGroupNameMatch: verifyGroupNameMatchFunc, - verifyCorrectGroupName: verifyCorrectGroupNameFunc, - verifyComponentConfigKindExists: verifyComponentConfigKindExistsFunc, + verifyTagNaming: verifyTagNamingFunc, + verifyGroupNameSuffix: verifyGroupNameSuffixFunc, + verifyGroupNameMatch: verifyGroupNameMatchFunc, + verifyCorrectGroupName: verifyCorrectGroupNameFunc, } // VerifyExternalTypePackage tests if external component config package is defined correctly @@ -94,7 +93,8 @@ func VerifyInternalTypePackage(pkginfo *ComponentConfigPackage) error { return fmt.Errorf("test setup error: %v", err) } extraFns := map[string]testingFunc{ - verifyInternalAPIVersion: verifyInternalAPIVersionFunc, + verifyInternalAPIVersion: verifyInternalAPIVersionFunc, + verifyComponentConfigKindExists: verifyComponentConfigKindExistsFunc, } return runFuncs(scheme, pkginfo, extraFns) } diff --git a/staging/src/k8s.io/kubelet/config/v1/doc.go b/staging/src/k8s.io/kubelet/config/v1/doc.go new file mode 100644 index 00000000000..b411f7151b7 --- /dev/null +++ b/staging/src/k8s.io/kubelet/config/v1/doc.go @@ -0,0 +1,21 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// +k8s:deepcopy-gen=package +// +k8s:openapi-gen=true +// +groupName=kubelet.config.k8s.io + +package v1 // import "k8s.io/kubelet/config/v1" diff --git a/staging/src/k8s.io/kubelet/config/v1/register.go b/staging/src/k8s.io/kubelet/config/v1/register.go new file mode 100644 index 00000000000..effb5b38171 --- /dev/null +++ b/staging/src/k8s.io/kubelet/config/v1/register.go @@ -0,0 +1,43 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName is the group name used in this package +const GroupName = "kubelet.config.k8s.io" + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"} + +var ( + // SchemeBuilder is the scheme builder with scheme init functions to run for this API package + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + // AddToScheme is a global function that registers this API group & version to a scheme + AddToScheme = SchemeBuilder.AddToScheme +) + +// addKnownTypes registers known types to the given scheme +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &CredentialProviderConfig{}, + ) + return nil +} diff --git a/staging/src/k8s.io/kubelet/config/v1/register_test.go b/staging/src/k8s.io/kubelet/config/v1/register_test.go new file mode 100644 index 00000000000..cadf2cf2bab --- /dev/null +++ b/staging/src/k8s.io/kubelet/config/v1/register_test.go @@ -0,0 +1,36 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + "testing" + + componentconfigtesting "k8s.io/component-base/config/testing" +) + +func TestComponentConfigSetup(t *testing.T) { + pkginfo := &componentconfigtesting.ComponentConfigPackage{ + ComponentName: "kubelet", + GroupName: GroupName, + SchemeGroupVersion: SchemeGroupVersion, + AddToScheme: AddToScheme, + } + + if err := componentconfigtesting.VerifyExternalTypePackage(pkginfo); err != nil { + t.Fatal(err) + } +} diff --git a/staging/src/k8s.io/kubelet/config/v1/types.go b/staging/src/k8s.io/kubelet/config/v1/types.go new file mode 100644 index 00000000000..1b59a7d8dc6 --- /dev/null +++ b/staging/src/k8s.io/kubelet/config/v1/types.go @@ -0,0 +1,97 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// CredentialProviderConfig is the configuration containing information about +// each exec credential provider. Kubelet reads this configuration from disk and enables +// each provider as specified by the CredentialProvider type. +type CredentialProviderConfig struct { + metav1.TypeMeta `json:",inline"` + + // providers is a list of credential provider plugins that will be enabled by the kubelet. + // Multiple providers may match against a single image, in which case credentials + // from all providers will be returned to the kubelet. If multiple providers are called + // for a single image, the results are combined. If providers return overlapping + // auth keys, the value from the provider earlier in this list is used. + Providers []CredentialProvider `json:"providers"` +} + +// CredentialProvider represents an exec plugin to be invoked by the kubelet. The plugin is only +// invoked when an image being pulled matches the images handled by the plugin (see matchImages). +type CredentialProvider struct { + // name is the required name of the credential provider. It must match the name of the + // provider executable as seen by the kubelet. The executable must be in the kubelet's + // bin directory (set by the --image-credential-provider-bin-dir flag). + Name string `json:"name"` + + // matchImages is a required list of strings used to match against images in order to + // determine if this provider should be invoked. If one of the strings matches the + // requested image from the kubelet, the plugin will be invoked and given a chance + // to provide credentials. Images are expected to contain the registry domain + // and URL path. + // + // Each entry in matchImages is a pattern which can optionally contain a port and a path. + // Globs can be used in the domain, but not in the port or the path. Globs are supported + // as subdomains like '*.k8s.io' or 'k8s.*.io', and top-level-domains such as 'k8s.*'. + // Matching partial subdomains like 'app*.k8s.io' is also supported. Each glob can only match + // a single subdomain segment, so *.io does not match *.k8s.io. + // + // A match exists between an image and a matchImage when all of the below are true: + // - Both contain the same number of domain parts and each part matches. + // - The URL path of an imageMatch must be a prefix of the target image URL path. + // - If the imageMatch contains a port, then the port must match in the image as well. + // + // Example values of matchImages: + // - 123456789.dkr.ecr.us-east-1.amazonaws.com + // - *.azurecr.io + // - gcr.io + // - *.*.registry.io + // - registry.io:8080/path + MatchImages []string `json:"matchImages"` + + // defaultCacheDuration is the default duration the plugin will cache credentials in-memory + // if a cache duration is not provided in the plugin response. This field is required. + DefaultCacheDuration *metav1.Duration `json:"defaultCacheDuration"` + + // 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/v1 + APIVersion string `json:"apiVersion"` + + // Arguments to pass to the command when executing it. + // +optional + Args []string `json:"args,omitempty"` + + // Env defines additional environment variables to expose to the process. These + // are unioned with the host's environment, as well as variables client-go uses + // to pass argument to the plugin. + // +optional + Env []ExecEnvVar `json:"env,omitempty"` +} + +// ExecEnvVar is used for setting environment variables when executing an exec-based +// credential plugin. +type ExecEnvVar struct { + Name string `json:"name"` + Value string `json:"value"` +} diff --git a/staging/src/k8s.io/kubelet/config/v1/zz_generated.deepcopy.go b/staging/src/k8s.io/kubelet/config/v1/zz_generated.deepcopy.go new file mode 100644 index 00000000000..8b5189769b5 --- /dev/null +++ b/staging/src/k8s.io/kubelet/config/v1/zz_generated.deepcopy.go @@ -0,0 +1,111 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CredentialProvider) DeepCopyInto(out *CredentialProvider) { + *out = *in + if in.MatchImages != nil { + in, out := &in.MatchImages, &out.MatchImages + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.DefaultCacheDuration != nil { + in, out := &in.DefaultCacheDuration, &out.DefaultCacheDuration + *out = new(metav1.Duration) + **out = **in + } + if in.Args != nil { + in, out := &in.Args, &out.Args + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Env != nil { + in, out := &in.Env, &out.Env + *out = make([]ExecEnvVar, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialProvider. +func (in *CredentialProvider) DeepCopy() *CredentialProvider { + if in == nil { + return nil + } + out := new(CredentialProvider) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CredentialProviderConfig) DeepCopyInto(out *CredentialProviderConfig) { + *out = *in + out.TypeMeta = in.TypeMeta + if in.Providers != nil { + in, out := &in.Providers, &out.Providers + *out = make([]CredentialProvider, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialProviderConfig. +func (in *CredentialProviderConfig) DeepCopy() *CredentialProviderConfig { + if in == nil { + return nil + } + out := new(CredentialProviderConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *CredentialProviderConfig) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExecEnvVar) DeepCopyInto(out *ExecEnvVar) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExecEnvVar. +func (in *ExecEnvVar) DeepCopy() *ExecEnvVar { + if in == nil { + return nil + } + out := new(ExecEnvVar) + in.DeepCopyInto(out) + return out +} diff --git a/staging/src/k8s.io/kubelet/pkg/apis/credentialprovider/install/install.go b/staging/src/k8s.io/kubelet/pkg/apis/credentialprovider/install/install.go index f3f8b1dfa3c..58461310054 100644 --- a/staging/src/k8s.io/kubelet/pkg/apis/credentialprovider/install/install.go +++ b/staging/src/k8s.io/kubelet/pkg/apis/credentialprovider/install/install.go @@ -20,6 +20,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/kubelet/pkg/apis/credentialprovider" + v1 "k8s.io/kubelet/pkg/apis/credentialprovider/v1" "k8s.io/kubelet/pkg/apis/credentialprovider/v1alpha1" "k8s.io/kubelet/pkg/apis/credentialprovider/v1beta1" ) @@ -31,4 +32,6 @@ func Install(scheme *runtime.Scheme) { utilruntime.Must(scheme.SetVersionPriority(v1alpha1.SchemeGroupVersion)) utilruntime.Must(v1beta1.AddToScheme(scheme)) utilruntime.Must(scheme.SetVersionPriority(v1beta1.SchemeGroupVersion)) + utilruntime.Must(v1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1.SchemeGroupVersion)) } diff --git a/staging/src/k8s.io/kubelet/pkg/apis/credentialprovider/v1/doc.go b/staging/src/k8s.io/kubelet/pkg/apis/credentialprovider/v1/doc.go new file mode 100644 index 00000000000..474a085ab92 --- /dev/null +++ b/staging/src/k8s.io/kubelet/pkg/apis/credentialprovider/v1/doc.go @@ -0,0 +1,22 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// +k8s:deepcopy-gen=package +// +k8s:conversion-gen=k8s.io/kubelet/pkg/apis/credentialprovider +// +k8s:defaulter-gen=TypeMeta +// +groupName=credentialprovider.kubelet.k8s.io + +package v1 // import "k8s.io/kubelet/pkg/apis/credentialprovider/v1" diff --git a/staging/src/k8s.io/kubelet/pkg/apis/credentialprovider/v1/register.go b/staging/src/k8s.io/kubelet/pkg/apis/credentialprovider/v1/register.go new file mode 100644 index 00000000000..0f8177bd8ca --- /dev/null +++ b/staging/src/k8s.io/kubelet/pkg/apis/credentialprovider/v1/register.go @@ -0,0 +1,46 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName is the group name use in this package +const GroupName = "credentialprovider.kubelet.k8s.io" + +// SchemeGroupVersion is group version used to register these objects +var ( + SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"} + localSchemeBuilder = &SchemeBuilder +) + +var ( + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + AddToScheme = SchemeBuilder.AddToScheme +) + +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &CredentialProviderRequest{}, + &CredentialProviderResponse{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/staging/src/k8s.io/kubelet/pkg/apis/credentialprovider/v1/types.go b/staging/src/k8s.io/kubelet/pkg/apis/credentialprovider/v1/types.go new file mode 100644 index 00000000000..3cce9cc428e --- /dev/null +++ b/staging/src/k8s.io/kubelet/pkg/apis/credentialprovider/v1/types.go @@ -0,0 +1,117 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// CredentialProviderRequest includes the image that the kubelet requires authentication for. +// Kubelet will pass this request object to the plugin via stdin. In general, plugins should +// prefer responding with the same apiVersion they were sent. +type CredentialProviderRequest struct { + metav1.TypeMeta `json:",inline"` + + // image is the container image that is being pulled as part of the + // credential provider plugin request. Plugins may optionally parse the image + // to extract any information required to fetch credentials. + Image string `json:"image"` +} + +type PluginCacheKeyType string + +const ( + // ImagePluginCacheKeyType means the kubelet will cache credentials on a per-image basis, + // using the image passed from the kubelet directly as the cache key. This includes + // the registry domain, port (if specified), and path but does not include tags or SHAs. + ImagePluginCacheKeyType PluginCacheKeyType = "Image" + // RegistryPluginCacheKeyType means the kubelet will cache credentials on a per-registry basis. + // The cache key will be based on the registry domain and port (if present) parsed from the requested image. + RegistryPluginCacheKeyType PluginCacheKeyType = "Registry" + // GlobalPluginCacheKeyType means the kubelet will cache credentials for all images that + // match for a given plugin. This cache key should only be returned by plugins that do not use + // the image input at all. + GlobalPluginCacheKeyType PluginCacheKeyType = "Global" +) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// CredentialProviderResponse holds credentials that the kubelet should use for the specified +// image provided in the original request. Kubelet will read the response from the plugin via stdout. +// This response should be set to the same apiVersion as CredentialProviderRequest. +type CredentialProviderResponse struct { + metav1.TypeMeta `json:",inline"` + + // cacheKeyType indiciates the type of caching key to use based on the image provided + // in the request. There are three valid values for the cache key type: Image, Registry, and + // Global. If an invalid value is specified, the response will NOT be used by the kubelet. + CacheKeyType PluginCacheKeyType `json:"cacheKeyType"` + + // cacheDuration indicates the duration the provided credentials should be cached for. + // The kubelet will use this field to set the in-memory cache duration for credentials + // in the AuthConfig. If null, the kubelet will use defaultCacheDuration provided in + // CredentialProviderConfig. If set to 0, the kubelet will not cache the provided AuthConfig. + // +optional + CacheDuration *metav1.Duration `json:"cacheDuration,omitempty"` + + // auth is a map containing authentication information passed into the kubelet. + // Each key is a match image string (more on this below). The corresponding authConfig value + // should be valid for all images that match against this key. A plugin should set + // this field to null if no valid credentials can be returned for the requested image. + // + // Each key in the map is a pattern which can optionally contain a port and a path. + // Globs can be used in the domain, but not in the port or the path. Globs are supported + // as subdomains like '*.k8s.io' or 'k8s.*.io', and top-level-domains such as 'k8s.*'. + // Matching partial subdomains like 'app*.k8s.io' is also supported. Each glob can only match + // a single subdomain segment, so *.io does not match *.k8s.io. + // + // The kubelet will match images against the key when all of the below are true: + // - Both contain the same number of domain parts and each part matches. + // - The URL path of an imageMatch must be a prefix of the target image URL path. + // - If the imageMatch contains a port, then the port must match in the image as well. + // + // When multiple keys are returned, the kubelet will traverse all keys in reverse order so that: + // - longer keys come before shorter keys with the same prefix + // - non-wildcard keys come before wildcard keys with the same prefix. + // + // For any given match, the kubelet will attempt an image pull with the provided credentials, + // stopping after the first successfully authenticated pull. + // + // Example keys: + // - 123456789.dkr.ecr.us-east-1.amazonaws.com + // - *.azurecr.io + // - gcr.io + // - *.*.registry.io + // - registry.io:8080/path + // +optional + Auth map[string]AuthConfig `json:"auth,omitempty"` +} + +// AuthConfig contains authentication information for a container registry. +// Only username/password based authentication is supported today, but more authentication +// mechanisms may be added in the future. +type AuthConfig struct { + // username is the username used for authenticating to the container registry + // An empty username is valid. + Username string `json:"username"` + + // password is the password used for authenticating to the container registry + // An empty password is valid. + Password string `json:"password"` +} diff --git a/staging/src/k8s.io/kubelet/pkg/apis/credentialprovider/v1/zz_generated.conversion.go b/staging/src/k8s.io/kubelet/pkg/apis/credentialprovider/v1/zz_generated.conversion.go new file mode 100644 index 00000000000..97922e9763c --- /dev/null +++ b/staging/src/k8s.io/kubelet/pkg/apis/credentialprovider/v1/zz_generated.conversion.go @@ -0,0 +1,137 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by conversion-gen. DO NOT EDIT. + +package v1 + +import ( + unsafe "unsafe" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + conversion "k8s.io/apimachinery/pkg/conversion" + runtime "k8s.io/apimachinery/pkg/runtime" + credentialprovider "k8s.io/kubelet/pkg/apis/credentialprovider" +) + +func init() { + localSchemeBuilder.Register(RegisterConversions) +} + +// RegisterConversions adds conversion functions to the given scheme. +// Public to allow building arbitrary schemes. +func RegisterConversions(s *runtime.Scheme) error { + if err := s.AddGeneratedConversionFunc((*AuthConfig)(nil), (*credentialprovider.AuthConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1_AuthConfig_To_credentialprovider_AuthConfig(a.(*AuthConfig), b.(*credentialprovider.AuthConfig), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*credentialprovider.AuthConfig)(nil), (*AuthConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_credentialprovider_AuthConfig_To_v1_AuthConfig(a.(*credentialprovider.AuthConfig), b.(*AuthConfig), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*CredentialProviderRequest)(nil), (*credentialprovider.CredentialProviderRequest)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1_CredentialProviderRequest_To_credentialprovider_CredentialProviderRequest(a.(*CredentialProviderRequest), b.(*credentialprovider.CredentialProviderRequest), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*credentialprovider.CredentialProviderRequest)(nil), (*CredentialProviderRequest)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_credentialprovider_CredentialProviderRequest_To_v1_CredentialProviderRequest(a.(*credentialprovider.CredentialProviderRequest), b.(*CredentialProviderRequest), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*CredentialProviderResponse)(nil), (*credentialprovider.CredentialProviderResponse)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1_CredentialProviderResponse_To_credentialprovider_CredentialProviderResponse(a.(*CredentialProviderResponse), b.(*credentialprovider.CredentialProviderResponse), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*credentialprovider.CredentialProviderResponse)(nil), (*CredentialProviderResponse)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_credentialprovider_CredentialProviderResponse_To_v1_CredentialProviderResponse(a.(*credentialprovider.CredentialProviderResponse), b.(*CredentialProviderResponse), scope) + }); err != nil { + return err + } + return nil +} + +func autoConvert_v1_AuthConfig_To_credentialprovider_AuthConfig(in *AuthConfig, out *credentialprovider.AuthConfig, s conversion.Scope) error { + out.Username = in.Username + out.Password = in.Password + return nil +} + +// Convert_v1_AuthConfig_To_credentialprovider_AuthConfig is an autogenerated conversion function. +func Convert_v1_AuthConfig_To_credentialprovider_AuthConfig(in *AuthConfig, out *credentialprovider.AuthConfig, s conversion.Scope) error { + return autoConvert_v1_AuthConfig_To_credentialprovider_AuthConfig(in, out, s) +} + +func autoConvert_credentialprovider_AuthConfig_To_v1_AuthConfig(in *credentialprovider.AuthConfig, out *AuthConfig, s conversion.Scope) error { + out.Username = in.Username + out.Password = in.Password + return nil +} + +// Convert_credentialprovider_AuthConfig_To_v1_AuthConfig is an autogenerated conversion function. +func Convert_credentialprovider_AuthConfig_To_v1_AuthConfig(in *credentialprovider.AuthConfig, out *AuthConfig, s conversion.Scope) error { + return autoConvert_credentialprovider_AuthConfig_To_v1_AuthConfig(in, out, s) +} + +func autoConvert_v1_CredentialProviderRequest_To_credentialprovider_CredentialProviderRequest(in *CredentialProviderRequest, out *credentialprovider.CredentialProviderRequest, s conversion.Scope) error { + out.Image = in.Image + return nil +} + +// Convert_v1_CredentialProviderRequest_To_credentialprovider_CredentialProviderRequest is an autogenerated conversion function. +func Convert_v1_CredentialProviderRequest_To_credentialprovider_CredentialProviderRequest(in *CredentialProviderRequest, out *credentialprovider.CredentialProviderRequest, s conversion.Scope) error { + return autoConvert_v1_CredentialProviderRequest_To_credentialprovider_CredentialProviderRequest(in, out, s) +} + +func autoConvert_credentialprovider_CredentialProviderRequest_To_v1_CredentialProviderRequest(in *credentialprovider.CredentialProviderRequest, out *CredentialProviderRequest, s conversion.Scope) error { + out.Image = in.Image + return nil +} + +// Convert_credentialprovider_CredentialProviderRequest_To_v1_CredentialProviderRequest is an autogenerated conversion function. +func Convert_credentialprovider_CredentialProviderRequest_To_v1_CredentialProviderRequest(in *credentialprovider.CredentialProviderRequest, out *CredentialProviderRequest, s conversion.Scope) error { + return autoConvert_credentialprovider_CredentialProviderRequest_To_v1_CredentialProviderRequest(in, out, s) +} + +func autoConvert_v1_CredentialProviderResponse_To_credentialprovider_CredentialProviderResponse(in *CredentialProviderResponse, out *credentialprovider.CredentialProviderResponse, s conversion.Scope) error { + out.CacheKeyType = credentialprovider.PluginCacheKeyType(in.CacheKeyType) + out.CacheDuration = (*metav1.Duration)(unsafe.Pointer(in.CacheDuration)) + out.Auth = *(*map[string]credentialprovider.AuthConfig)(unsafe.Pointer(&in.Auth)) + return nil +} + +// Convert_v1_CredentialProviderResponse_To_credentialprovider_CredentialProviderResponse is an autogenerated conversion function. +func Convert_v1_CredentialProviderResponse_To_credentialprovider_CredentialProviderResponse(in *CredentialProviderResponse, out *credentialprovider.CredentialProviderResponse, s conversion.Scope) error { + return autoConvert_v1_CredentialProviderResponse_To_credentialprovider_CredentialProviderResponse(in, out, s) +} + +func autoConvert_credentialprovider_CredentialProviderResponse_To_v1_CredentialProviderResponse(in *credentialprovider.CredentialProviderResponse, out *CredentialProviderResponse, s conversion.Scope) error { + out.CacheKeyType = PluginCacheKeyType(in.CacheKeyType) + out.CacheDuration = (*metav1.Duration)(unsafe.Pointer(in.CacheDuration)) + out.Auth = *(*map[string]AuthConfig)(unsafe.Pointer(&in.Auth)) + return nil +} + +// Convert_credentialprovider_CredentialProviderResponse_To_v1_CredentialProviderResponse is an autogenerated conversion function. +func Convert_credentialprovider_CredentialProviderResponse_To_v1_CredentialProviderResponse(in *credentialprovider.CredentialProviderResponse, out *CredentialProviderResponse, s conversion.Scope) error { + return autoConvert_credentialprovider_CredentialProviderResponse_To_v1_CredentialProviderResponse(in, out, s) +} diff --git a/staging/src/k8s.io/kubelet/pkg/apis/credentialprovider/v1/zz_generated.deepcopy.go b/staging/src/k8s.io/kubelet/pkg/apis/credentialprovider/v1/zz_generated.deepcopy.go new file mode 100644 index 00000000000..aa12d576747 --- /dev/null +++ b/staging/src/k8s.io/kubelet/pkg/apis/credentialprovider/v1/zz_generated.deepcopy.go @@ -0,0 +1,105 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthConfig) DeepCopyInto(out *AuthConfig) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthConfig. +func (in *AuthConfig) DeepCopy() *AuthConfig { + if in == nil { + return nil + } + out := new(AuthConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CredentialProviderRequest) DeepCopyInto(out *CredentialProviderRequest) { + *out = *in + out.TypeMeta = in.TypeMeta + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialProviderRequest. +func (in *CredentialProviderRequest) DeepCopy() *CredentialProviderRequest { + if in == nil { + return nil + } + out := new(CredentialProviderRequest) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *CredentialProviderRequest) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CredentialProviderResponse) DeepCopyInto(out *CredentialProviderResponse) { + *out = *in + out.TypeMeta = in.TypeMeta + if in.CacheDuration != nil { + in, out := &in.CacheDuration, &out.CacheDuration + *out = new(metav1.Duration) + **out = **in + } + if in.Auth != nil { + in, out := &in.Auth, &out.Auth + *out = make(map[string]AuthConfig, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialProviderResponse. +func (in *CredentialProviderResponse) DeepCopy() *CredentialProviderResponse { + if in == nil { + return nil + } + out := new(CredentialProviderResponse) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *CredentialProviderResponse) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} diff --git a/staging/src/k8s.io/kubelet/pkg/apis/credentialprovider/v1/zz_generated.defaults.go b/staging/src/k8s.io/kubelet/pkg/apis/credentialprovider/v1/zz_generated.defaults.go new file mode 100644 index 00000000000..dac177e93bd --- /dev/null +++ b/staging/src/k8s.io/kubelet/pkg/apis/credentialprovider/v1/zz_generated.defaults.go @@ -0,0 +1,33 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by defaulter-gen. DO NOT EDIT. + +package v1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// RegisterDefaults adds defaulters functions to the given scheme. +// Public to allow building arbitrary schemes. +// All generated defaulters are covering - they call all nested defaulters. +func RegisterDefaults(scheme *runtime.Scheme) error { + return nil +} diff --git a/test/e2e_node/plugins/gcp-credential-provider/main.go b/test/e2e_node/plugins/gcp-credential-provider/main.go index 543057d1e08..2f570e8681d 100644 --- a/test/e2e_node/plugins/gcp-credential-provider/main.go +++ b/test/e2e_node/plugins/gcp-credential-provider/main.go @@ -27,7 +27,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/klog/v2" - credentialproviderv1beta1 "k8s.io/kubelet/pkg/apis/credentialprovider/v1beta1" + credentialproviderv1 "k8s.io/kubelet/pkg/apis/credentialprovider/v1" ) const metadataTokenEndpoint = "http://metadata.google.internal./computeMetadata/v1/instance/service-accounts/default/token" @@ -51,7 +51,7 @@ func getCredentials(tokenEndpoint string, r io.Reader, w io.Writer) error { return err } - var authRequest credentialproviderv1beta1.CredentialProviderRequest + var authRequest credentialproviderv1.CredentialProviderRequest err = json.Unmarshal(data, &authRequest) if err != nil { return err @@ -62,12 +62,12 @@ func getCredentials(tokenEndpoint string, r io.Reader, w io.Writer) error { return err } - response := &credentialproviderv1beta1.CredentialProviderResponse{ + response := &credentialproviderv1.CredentialProviderResponse{ TypeMeta: metav1.TypeMeta{ Kind: "CredentialProviderResponse", - APIVersion: "credentialprovider.kubelet.k8s.io/v1beta1", + APIVersion: "credentialprovider.kubelet.k8s.io/v1", }, - CacheKeyType: credentialproviderv1beta1.RegistryPluginCacheKeyType, + CacheKeyType: credentialproviderv1.RegistryPluginCacheKeyType, Auth: auth, } diff --git a/test/e2e_node/plugins/gcp-credential-provider/main_test.go b/test/e2e_node/plugins/gcp-credential-provider/main_test.go index 684e92450fa..09966c76754 100644 --- a/test/e2e_node/plugins/gcp-credential-provider/main_test.go +++ b/test/e2e_node/plugins/gcp-credential-provider/main_test.go @@ -36,7 +36,7 @@ func Test_getCredentials(t *testing.T) { server := httptest.NewServer(&fakeTokenServer{token: "abc123"}) defer server.Close() - in := bytes.NewBuffer([]byte(`{"kind":"CredentialProviderRequest","apiVersion":"credentialprovider.kubelet.k8s.io/v1beta1","image":"gcr.io/foobar"}`)) + in := bytes.NewBuffer([]byte(`{"kind":"CredentialProviderRequest","apiVersion":"credentialprovider.kubelet.k8s.io/v1","image":"gcr.io/foobar"}`)) out := bytes.NewBuffer(nil) err := getCredentials(server.URL, in, out) @@ -44,7 +44,7 @@ func Test_getCredentials(t *testing.T) { t.Fatalf("unexpected error running getCredentials: %v", err) } - expected := `{"kind":"CredentialProviderResponse","apiVersion":"credentialprovider.kubelet.k8s.io/v1beta1","cacheKeyType":"Registry","auth":{"*.gcr.io":{"username":"_token","password":"abc123"},"*.pkg.dev":{"username":"_token","password":"abc123"},"container.cloud.google.com":{"username":"_token","password":"abc123"},"gcr.io":{"username":"_token","password":"abc123"}}} + expected := `{"kind":"CredentialProviderResponse","apiVersion":"credentialprovider.kubelet.k8s.io/v1","cacheKeyType":"Registry","auth":{"*.gcr.io":{"username":"_token","password":"abc123"},"*.pkg.dev":{"username":"_token","password":"abc123"},"container.cloud.google.com":{"username":"_token","password":"abc123"},"gcr.io":{"username":"_token","password":"abc123"}}} ` if out.String() != expected { diff --git a/test/e2e_node/plugins/gcp-credential-provider/provider.go b/test/e2e_node/plugins/gcp-credential-provider/provider.go index 59ff39febc2..3bbe9a04312 100644 --- a/test/e2e_node/plugins/gcp-credential-provider/provider.go +++ b/test/e2e_node/plugins/gcp-credential-provider/provider.go @@ -25,7 +25,7 @@ import ( "io/ioutil" "net/http" - credentialproviderv1beta1 "k8s.io/kubelet/pkg/apis/credentialprovider/v1beta1" + credentialproviderv1 "k8s.io/kubelet/pkg/apis/credentialprovider/v1" ) const ( @@ -59,8 +59,8 @@ type provider struct { tokenEndpoint string } -func (p *provider) Provide(image string) (map[string]credentialproviderv1beta1.AuthConfig, error) { - cfg := map[string]credentialproviderv1beta1.AuthConfig{} +func (p *provider) Provide(image string) (map[string]credentialproviderv1.AuthConfig, error) { + cfg := map[string]credentialproviderv1.AuthConfig{} tokenJSONBlob, err := readURL(p.tokenEndpoint, p.client) if err != nil { @@ -72,7 +72,7 @@ func (p *provider) Provide(image string) (map[string]credentialproviderv1beta1.A return cfg, err } - authConfig := credentialproviderv1beta1.AuthConfig{ + authConfig := credentialproviderv1.AuthConfig{ Username: "_token", Password: parsedBlob.AccessToken, } diff --git a/test/e2e_node/remote/utils.go b/test/e2e_node/remote/utils.go index 657ff8089a6..5cb5fc38ceb 100644 --- a/test/e2e_node/remote/utils.go +++ b/test/e2e_node/remote/utils.go @@ -49,10 +49,10 @@ const cniConfig = `{ ` const credentialProviderConfig = `kind: CredentialProviderConfig -apiVersion: kubelet.config.k8s.io/v1beta1 +apiVersion: kubelet.config.k8s.io/v1 providers: - name: gcp-credential-provider - apiVersion: credentialprovider.kubelet.k8s.io/v1beta1 + apiVersion: credentialprovider.kubelet.k8s.io/v1 matchImages: - "gcr.io" - "*.gcr.io" diff --git a/vendor/modules.txt b/vendor/modules.txt index 312a387cee5..a398484d606 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -2222,11 +2222,13 @@ k8s.io/kubectl/pkg/util/term k8s.io/kubectl/pkg/validation # k8s.io/kubelet v0.0.0 => ./staging/src/k8s.io/kubelet ## explicit; go 1.19 +k8s.io/kubelet/config/v1 k8s.io/kubelet/config/v1alpha1 k8s.io/kubelet/config/v1beta1 k8s.io/kubelet/pkg/apis k8s.io/kubelet/pkg/apis/credentialprovider k8s.io/kubelet/pkg/apis/credentialprovider/install +k8s.io/kubelet/pkg/apis/credentialprovider/v1 k8s.io/kubelet/pkg/apis/credentialprovider/v1alpha1 k8s.io/kubelet/pkg/apis/credentialprovider/v1beta1 k8s.io/kubelet/pkg/apis/deviceplugin/v1beta1