mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-07-18 04:54:54 +00:00
Merge pull request #132579 from stlaz/ensure-secret-images-beta
KEP-2535: move objects to beta, add storage version migration to filesystem cache
This commit is contained in:
238
pkg/generated/openapi/zz_generated.openapi.go
generated
238
pkg/generated/openapi/zz_generated.openapi.go
generated
@@ -1471,6 +1471,11 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
|
||||
kubeletconfigv1beta1.CredentialProvider{}.OpenAPIModelName(): schema_k8sio_kubelet_config_v1beta1_CredentialProvider(ref),
|
||||
kubeletconfigv1beta1.CredentialProviderConfig{}.OpenAPIModelName(): schema_k8sio_kubelet_config_v1beta1_CredentialProviderConfig(ref),
|
||||
kubeletconfigv1beta1.ExecEnvVar{}.OpenAPIModelName(): schema_k8sio_kubelet_config_v1beta1_ExecEnvVar(ref),
|
||||
kubeletconfigv1beta1.ImagePullCredentials{}.OpenAPIModelName(): schema_k8sio_kubelet_config_v1beta1_ImagePullCredentials(ref),
|
||||
kubeletconfigv1beta1.ImagePullIntent{}.OpenAPIModelName(): schema_k8sio_kubelet_config_v1beta1_ImagePullIntent(ref),
|
||||
kubeletconfigv1beta1.ImagePullSecret{}.OpenAPIModelName(): schema_k8sio_kubelet_config_v1beta1_ImagePullSecret(ref),
|
||||
kubeletconfigv1beta1.ImagePullServiceAccount{}.OpenAPIModelName(): schema_k8sio_kubelet_config_v1beta1_ImagePullServiceAccount(ref),
|
||||
kubeletconfigv1beta1.ImagePulledRecord{}.OpenAPIModelName(): schema_k8sio_kubelet_config_v1beta1_ImagePulledRecord(ref),
|
||||
kubeletconfigv1beta1.KubeletAnonymousAuthentication{}.OpenAPIModelName(): schema_k8sio_kubelet_config_v1beta1_KubeletAnonymousAuthentication(ref),
|
||||
kubeletconfigv1beta1.KubeletAuthentication{}.OpenAPIModelName(): schema_k8sio_kubelet_config_v1beta1_KubeletAuthentication(ref),
|
||||
kubeletconfigv1beta1.KubeletAuthorization{}.OpenAPIModelName(): schema_k8sio_kubelet_config_v1beta1_KubeletAuthorization(ref),
|
||||
@@ -71414,6 +71419,239 @@ func schema_k8sio_kubelet_config_v1beta1_ExecEnvVar(ref common.ReferenceCallback
|
||||
}
|
||||
}
|
||||
|
||||
func schema_k8sio_kubelet_config_v1beta1_ImagePullCredentials(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "ImagePullCredentials describe credentials that can be used to pull an image.",
|
||||
Type: []string{"object"},
|
||||
Properties: map[string]spec.Schema{
|
||||
"kubernetesSecrets": {
|
||||
VendorExtensible: spec.VendorExtensible{
|
||||
Extensions: spec.Extensions{
|
||||
"x-kubernetes-list-type": "set",
|
||||
},
|
||||
},
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "KubernetesSecretCoordinates is an index of coordinates of all the kubernetes secrets that were used to pull the image.",
|
||||
Type: []string{"array"},
|
||||
Items: &spec.SchemaOrArray{
|
||||
Schema: &spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Default: map[string]interface{}{},
|
||||
Ref: ref(kubeletconfigv1beta1.ImagePullSecret{}.OpenAPIModelName()),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"kubernetesServiceAccounts": {
|
||||
VendorExtensible: spec.VendorExtensible{
|
||||
Extensions: spec.Extensions{
|
||||
"x-kubernetes-list-type": "set",
|
||||
},
|
||||
},
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "KubernetesServiceAccounts is an index of coordinates of all the kubernetes service accounts that were used to pull the image.",
|
||||
Type: []string{"array"},
|
||||
Items: &spec.SchemaOrArray{
|
||||
Schema: &spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Default: map[string]interface{}{},
|
||||
Ref: ref(kubeletconfigv1beta1.ImagePullServiceAccount{}.OpenAPIModelName()),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"nodePodsAccessible": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "NodePodsAccessible is a flag denoting the pull credentials are accessible by all the pods on the node, or that no credentials are needed for the pull.\n\nIf true, it is mutually exclusive with the `kubernetesSecrets` field.",
|
||||
Type: []string{"boolean"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Dependencies: []string{
|
||||
kubeletconfigv1beta1.ImagePullSecret{}.OpenAPIModelName(), kubeletconfigv1beta1.ImagePullServiceAccount{}.OpenAPIModelName()},
|
||||
}
|
||||
}
|
||||
|
||||
func schema_k8sio_kubelet_config_v1beta1_ImagePullIntent(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "ImagePullIntent is a record of the kubelet attempting to pull an image.",
|
||||
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: "",
|
||||
},
|
||||
},
|
||||
"image": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Image is the image spec from a Container's `image` field. The filename is a SHA-256 hash of this value. This is to avoid filename-unsafe characters like ':' and '/'.",
|
||||
Default: "",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
Required: []string{"image"},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func schema_k8sio_kubelet_config_v1beta1_ImagePullSecret(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "ImagePullSecret is a representation of a Kubernetes secret object coordinates along with a credential hash of the pull secret credentials this object contains.",
|
||||
Type: []string{"object"},
|
||||
Properties: map[string]spec.Schema{
|
||||
"uid": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Default: "",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"namespace": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Default: "",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"name": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Default: "",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"credentialHash": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "CredentialHash is a SHA-256 retrieved by hashing the image pull credentials content of the secret specified by the UID/Namespace/Name coordinates.",
|
||||
Default: "",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
Required: []string{"uid", "namespace", "name", "credentialHash"},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func schema_k8sio_kubelet_config_v1beta1_ImagePullServiceAccount(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "ImagePullServiceAccount is a representation of a Kubernetes service account object coordinates for which the kubelet sent service account token to the credential provider plugin for image pull credentials.",
|
||||
Type: []string{"object"},
|
||||
Properties: map[string]spec.Schema{
|
||||
"uid": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Default: "",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"namespace": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Default: "",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"name": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Default: "",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
Required: []string{"uid", "namespace", "name"},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func schema_k8sio_kubelet_config_v1beta1_ImagePulledRecord(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "ImagePullRecord is a record of an image that was pulled by the kubelet.\n\nIf there are no records in the `kubernetesSecrets` field and both `nodeWideCredentials` and `anonymous` are `false`, credentials must be re-checked the next time an image represented by this record is being requested.",
|
||||
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: "",
|
||||
},
|
||||
},
|
||||
"lastUpdatedTime": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "LastUpdatedTime is the time of the last update to this record",
|
||||
Ref: ref(metav1.Time{}.OpenAPIModelName()),
|
||||
},
|
||||
},
|
||||
"imageRef": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "ImageRef is a reference to the image represented by this file as received from the CRI. The filename is a SHA-256 hash of this value. This is to avoid filename-unsafe characters like ':' and '/'.",
|
||||
Default: "",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"credentialMapping": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "CredentialMapping maps `image` to the set of credentials that it was previously pulled with. `image` in this case is the content of a pod's container `image` field that's got its tag/digest removed.\n\nExample:\n Container requests the `hello-world:latest@sha256:91fb4b041da273d5a3273b6d587d62d518300a6ad268b28628f74997b93171b2` image:\n \"credentialMapping\": {\n \"hello-world\": { \"nodePodsAccessible\": true }\n }",
|
||||
Type: []string{"object"},
|
||||
AdditionalProperties: &spec.SchemaOrBool{
|
||||
Allows: true,
|
||||
Schema: &spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Default: map[string]interface{}{},
|
||||
Ref: ref(kubeletconfigv1beta1.ImagePullCredentials{}.OpenAPIModelName()),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Required: []string{"lastUpdatedTime", "imageRef"},
|
||||
},
|
||||
},
|
||||
Dependencies: []string{
|
||||
metav1.Time{}.OpenAPIModelName(), kubeletconfigv1beta1.ImagePullCredentials{}.OpenAPIModelName()},
|
||||
}
|
||||
}
|
||||
|
||||
func schema_k8sio_kubelet_config_v1beta1_KubeletAnonymousAuthentication(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
|
||||
3
pkg/kubelet/apis/config/scheme/testdata/ImagePullIntent/after/v1beta1.yaml
vendored
Normal file
3
pkg/kubelet/apis/config/scheme/testdata/ImagePullIntent/after/v1beta1.yaml
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
apiVersion: kubelet.config.k8s.io/v1beta1
|
||||
image: ""
|
||||
kind: ImagePullIntent
|
||||
2
pkg/kubelet/apis/config/scheme/testdata/ImagePullIntent/before/v1beta1.yaml
vendored
Normal file
2
pkg/kubelet/apis/config/scheme/testdata/ImagePullIntent/before/v1beta1.yaml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
kind: ImagePullIntent
|
||||
apiVersion: kubelet.config.k8s.io/v1beta1
|
||||
3
pkg/kubelet/apis/config/scheme/testdata/ImagePullIntent/roundtrip/default/v1beta1.yaml
vendored
Normal file
3
pkg/kubelet/apis/config/scheme/testdata/ImagePullIntent/roundtrip/default/v1beta1.yaml
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
apiVersion: kubelet.config.k8s.io/v1beta1
|
||||
image: ""
|
||||
kind: ImagePullIntent
|
||||
4
pkg/kubelet/apis/config/scheme/testdata/ImagePulledRecord/after/v1beta1.yaml
vendored
Normal file
4
pkg/kubelet/apis/config/scheme/testdata/ImagePulledRecord/after/v1beta1.yaml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
apiVersion: kubelet.config.k8s.io/v1beta1
|
||||
imageRef: ""
|
||||
kind: ImagePulledRecord
|
||||
lastUpdatedTime: null
|
||||
2
pkg/kubelet/apis/config/scheme/testdata/ImagePulledRecord/before/v1beta1.yaml
vendored
Normal file
2
pkg/kubelet/apis/config/scheme/testdata/ImagePulledRecord/before/v1beta1.yaml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
kind: ImagePulledRecord
|
||||
apiVersion: kubelet.config.k8s.io/v1beta1
|
||||
4
pkg/kubelet/apis/config/scheme/testdata/ImagePulledRecord/roundtrip/default/v1beta1.yaml
vendored
Normal file
4
pkg/kubelet/apis/config/scheme/testdata/ImagePulledRecord/roundtrip/default/v1beta1.yaml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
apiVersion: kubelet.config.k8s.io/v1beta1
|
||||
imageRef: ""
|
||||
kind: ImagePulledRecord
|
||||
lastUpdatedTime: null
|
||||
@@ -887,7 +887,7 @@ type ImagePulledRecord struct {
|
||||
|
||||
// ImagePullCredentials describe credentials that can be used to pull an image.
|
||||
type ImagePullCredentials struct {
|
||||
// KuberneteSecretCoordinates is an index of coordinates of all the kubernetes
|
||||
// KubernetesSecretCoordinates is an index of coordinates of all the kubernetes
|
||||
// secrets that were used to pull the image.
|
||||
// +optional
|
||||
KubernetesSecrets []ImagePullSecret
|
||||
|
||||
@@ -75,6 +75,56 @@ func RegisterConversions(s *runtime.Scheme) error {
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*configv1beta1.ImagePullCredentials)(nil), (*config.ImagePullCredentials)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta1_ImagePullCredentials_To_config_ImagePullCredentials(a.(*configv1beta1.ImagePullCredentials), b.(*config.ImagePullCredentials), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*config.ImagePullCredentials)(nil), (*configv1beta1.ImagePullCredentials)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_config_ImagePullCredentials_To_v1beta1_ImagePullCredentials(a.(*config.ImagePullCredentials), b.(*configv1beta1.ImagePullCredentials), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*configv1beta1.ImagePullIntent)(nil), (*config.ImagePullIntent)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta1_ImagePullIntent_To_config_ImagePullIntent(a.(*configv1beta1.ImagePullIntent), b.(*config.ImagePullIntent), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*config.ImagePullIntent)(nil), (*configv1beta1.ImagePullIntent)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_config_ImagePullIntent_To_v1beta1_ImagePullIntent(a.(*config.ImagePullIntent), b.(*configv1beta1.ImagePullIntent), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*configv1beta1.ImagePullSecret)(nil), (*config.ImagePullSecret)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta1_ImagePullSecret_To_config_ImagePullSecret(a.(*configv1beta1.ImagePullSecret), b.(*config.ImagePullSecret), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*config.ImagePullSecret)(nil), (*configv1beta1.ImagePullSecret)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_config_ImagePullSecret_To_v1beta1_ImagePullSecret(a.(*config.ImagePullSecret), b.(*configv1beta1.ImagePullSecret), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*configv1beta1.ImagePullServiceAccount)(nil), (*config.ImagePullServiceAccount)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta1_ImagePullServiceAccount_To_config_ImagePullServiceAccount(a.(*configv1beta1.ImagePullServiceAccount), b.(*config.ImagePullServiceAccount), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*config.ImagePullServiceAccount)(nil), (*configv1beta1.ImagePullServiceAccount)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_config_ImagePullServiceAccount_To_v1beta1_ImagePullServiceAccount(a.(*config.ImagePullServiceAccount), b.(*configv1beta1.ImagePullServiceAccount), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*configv1beta1.ImagePulledRecord)(nil), (*config.ImagePulledRecord)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta1_ImagePulledRecord_To_config_ImagePulledRecord(a.(*configv1beta1.ImagePulledRecord), b.(*config.ImagePulledRecord), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*config.ImagePulledRecord)(nil), (*configv1beta1.ImagePulledRecord)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_config_ImagePulledRecord_To_v1beta1_ImagePulledRecord(a.(*config.ImagePulledRecord), b.(*configv1beta1.ImagePulledRecord), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*configv1beta1.KubeletAnonymousAuthentication)(nil), (*config.KubeletAnonymousAuthentication)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta1_KubeletAnonymousAuthentication_To_config_KubeletAnonymousAuthentication(a.(*configv1beta1.KubeletAnonymousAuthentication), b.(*config.KubeletAnonymousAuthentication), scope)
|
||||
}); err != nil {
|
||||
@@ -311,6 +361,124 @@ func Convert_config_ExecEnvVar_To_v1beta1_ExecEnvVar(in *config.ExecEnvVar, out
|
||||
return autoConvert_config_ExecEnvVar_To_v1beta1_ExecEnvVar(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_ImagePullCredentials_To_config_ImagePullCredentials(in *configv1beta1.ImagePullCredentials, out *config.ImagePullCredentials, s conversion.Scope) error {
|
||||
out.KubernetesSecrets = *(*[]config.ImagePullSecret)(unsafe.Pointer(&in.KubernetesSecrets))
|
||||
out.KubernetesServiceAccounts = *(*[]config.ImagePullServiceAccount)(unsafe.Pointer(&in.KubernetesServiceAccounts))
|
||||
out.NodePodsAccessible = in.NodePodsAccessible
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_ImagePullCredentials_To_config_ImagePullCredentials is an autogenerated conversion function.
|
||||
func Convert_v1beta1_ImagePullCredentials_To_config_ImagePullCredentials(in *configv1beta1.ImagePullCredentials, out *config.ImagePullCredentials, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_ImagePullCredentials_To_config_ImagePullCredentials(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_config_ImagePullCredentials_To_v1beta1_ImagePullCredentials(in *config.ImagePullCredentials, out *configv1beta1.ImagePullCredentials, s conversion.Scope) error {
|
||||
out.KubernetesSecrets = *(*[]configv1beta1.ImagePullSecret)(unsafe.Pointer(&in.KubernetesSecrets))
|
||||
out.KubernetesServiceAccounts = *(*[]configv1beta1.ImagePullServiceAccount)(unsafe.Pointer(&in.KubernetesServiceAccounts))
|
||||
out.NodePodsAccessible = in.NodePodsAccessible
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_config_ImagePullCredentials_To_v1beta1_ImagePullCredentials is an autogenerated conversion function.
|
||||
func Convert_config_ImagePullCredentials_To_v1beta1_ImagePullCredentials(in *config.ImagePullCredentials, out *configv1beta1.ImagePullCredentials, s conversion.Scope) error {
|
||||
return autoConvert_config_ImagePullCredentials_To_v1beta1_ImagePullCredentials(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_ImagePullIntent_To_config_ImagePullIntent(in *configv1beta1.ImagePullIntent, out *config.ImagePullIntent, s conversion.Scope) error {
|
||||
out.Image = in.Image
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_ImagePullIntent_To_config_ImagePullIntent is an autogenerated conversion function.
|
||||
func Convert_v1beta1_ImagePullIntent_To_config_ImagePullIntent(in *configv1beta1.ImagePullIntent, out *config.ImagePullIntent, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_ImagePullIntent_To_config_ImagePullIntent(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_config_ImagePullIntent_To_v1beta1_ImagePullIntent(in *config.ImagePullIntent, out *configv1beta1.ImagePullIntent, s conversion.Scope) error {
|
||||
out.Image = in.Image
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_config_ImagePullIntent_To_v1beta1_ImagePullIntent is an autogenerated conversion function.
|
||||
func Convert_config_ImagePullIntent_To_v1beta1_ImagePullIntent(in *config.ImagePullIntent, out *configv1beta1.ImagePullIntent, s conversion.Scope) error {
|
||||
return autoConvert_config_ImagePullIntent_To_v1beta1_ImagePullIntent(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_ImagePullSecret_To_config_ImagePullSecret(in *configv1beta1.ImagePullSecret, out *config.ImagePullSecret, s conversion.Scope) error {
|
||||
out.UID = in.UID
|
||||
out.Namespace = in.Namespace
|
||||
out.Name = in.Name
|
||||
out.CredentialHash = in.CredentialHash
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_ImagePullSecret_To_config_ImagePullSecret is an autogenerated conversion function.
|
||||
func Convert_v1beta1_ImagePullSecret_To_config_ImagePullSecret(in *configv1beta1.ImagePullSecret, out *config.ImagePullSecret, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_ImagePullSecret_To_config_ImagePullSecret(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_config_ImagePullSecret_To_v1beta1_ImagePullSecret(in *config.ImagePullSecret, out *configv1beta1.ImagePullSecret, s conversion.Scope) error {
|
||||
out.UID = in.UID
|
||||
out.Namespace = in.Namespace
|
||||
out.Name = in.Name
|
||||
out.CredentialHash = in.CredentialHash
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_config_ImagePullSecret_To_v1beta1_ImagePullSecret is an autogenerated conversion function.
|
||||
func Convert_config_ImagePullSecret_To_v1beta1_ImagePullSecret(in *config.ImagePullSecret, out *configv1beta1.ImagePullSecret, s conversion.Scope) error {
|
||||
return autoConvert_config_ImagePullSecret_To_v1beta1_ImagePullSecret(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_ImagePullServiceAccount_To_config_ImagePullServiceAccount(in *configv1beta1.ImagePullServiceAccount, out *config.ImagePullServiceAccount, s conversion.Scope) error {
|
||||
out.UID = in.UID
|
||||
out.Namespace = in.Namespace
|
||||
out.Name = in.Name
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_ImagePullServiceAccount_To_config_ImagePullServiceAccount is an autogenerated conversion function.
|
||||
func Convert_v1beta1_ImagePullServiceAccount_To_config_ImagePullServiceAccount(in *configv1beta1.ImagePullServiceAccount, out *config.ImagePullServiceAccount, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_ImagePullServiceAccount_To_config_ImagePullServiceAccount(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_config_ImagePullServiceAccount_To_v1beta1_ImagePullServiceAccount(in *config.ImagePullServiceAccount, out *configv1beta1.ImagePullServiceAccount, s conversion.Scope) error {
|
||||
out.UID = in.UID
|
||||
out.Namespace = in.Namespace
|
||||
out.Name = in.Name
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_config_ImagePullServiceAccount_To_v1beta1_ImagePullServiceAccount is an autogenerated conversion function.
|
||||
func Convert_config_ImagePullServiceAccount_To_v1beta1_ImagePullServiceAccount(in *config.ImagePullServiceAccount, out *configv1beta1.ImagePullServiceAccount, s conversion.Scope) error {
|
||||
return autoConvert_config_ImagePullServiceAccount_To_v1beta1_ImagePullServiceAccount(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_ImagePulledRecord_To_config_ImagePulledRecord(in *configv1beta1.ImagePulledRecord, out *config.ImagePulledRecord, s conversion.Scope) error {
|
||||
out.LastUpdatedTime = in.LastUpdatedTime
|
||||
out.ImageRef = in.ImageRef
|
||||
out.CredentialMapping = *(*map[string]config.ImagePullCredentials)(unsafe.Pointer(&in.CredentialMapping))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_ImagePulledRecord_To_config_ImagePulledRecord is an autogenerated conversion function.
|
||||
func Convert_v1beta1_ImagePulledRecord_To_config_ImagePulledRecord(in *configv1beta1.ImagePulledRecord, out *config.ImagePulledRecord, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_ImagePulledRecord_To_config_ImagePulledRecord(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_config_ImagePulledRecord_To_v1beta1_ImagePulledRecord(in *config.ImagePulledRecord, out *configv1beta1.ImagePulledRecord, s conversion.Scope) error {
|
||||
out.LastUpdatedTime = in.LastUpdatedTime
|
||||
out.ImageRef = in.ImageRef
|
||||
out.CredentialMapping = *(*map[string]configv1beta1.ImagePullCredentials)(unsafe.Pointer(&in.CredentialMapping))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_config_ImagePulledRecord_To_v1beta1_ImagePulledRecord is an autogenerated conversion function.
|
||||
func Convert_config_ImagePulledRecord_To_v1beta1_ImagePulledRecord(in *config.ImagePulledRecord, out *configv1beta1.ImagePulledRecord, s conversion.Scope) error {
|
||||
return autoConvert_config_ImagePulledRecord_To_v1beta1_ImagePulledRecord(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_KubeletAnonymousAuthentication_To_config_KubeletAnonymousAuthentication(in *configv1beta1.KubeletAnonymousAuthentication, out *config.KubeletAnonymousAuthentication, s conversion.Scope) error {
|
||||
if err := v1.Convert_Pointer_bool_To_bool(&in.Enabled, &out.Enabled, s); err != nil {
|
||||
return err
|
||||
|
||||
@@ -30,9 +30,11 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
kubeletconfigv1alpha1 "k8s.io/kubelet/config/v1alpha1"
|
||||
"k8s.io/klog/v2"
|
||||
kubeletconfigv1beta1 "k8s.io/kubelet/config/v1beta1"
|
||||
kubeletconfiginternal "k8s.io/kubernetes/pkg/kubelet/apis/config"
|
||||
kubeletconfigvint1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/config/v1alpha1"
|
||||
kubeletconfigint1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/config/v1alpha1"
|
||||
kubeletconfigint1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/config/v1beta1"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -40,6 +42,8 @@ const (
|
||||
tmpFilesSuffix = ".tmp"
|
||||
)
|
||||
|
||||
var encodeVersion = kubeletconfigv1beta1.SchemeGroupVersion
|
||||
|
||||
var _ PullRecordsAccessor = &fsPullRecordsAccessor{}
|
||||
|
||||
// fsPullRecordsAccessor uses the filesystem to read/write ImagePullIntent/ImagePulledRecord
|
||||
@@ -76,9 +80,46 @@ func NewFSPullRecordsAccessor(kubeletDir string) (PullRecordsAccessor, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
accessor.recordsVersionMigration()
|
||||
return NewMeteringRecordsAccessor(accessor, fsPullIntentsSize, fsPulledRecordsSize), nil
|
||||
}
|
||||
|
||||
func (f *fsPullRecordsAccessor) recordsVersionMigration() {
|
||||
err := processDirFiles(f.pullingDir,
|
||||
func(filePath string, fileContent []byte) error {
|
||||
intent, isCurrentVersion, err := decodeIntent(f.decoder, fileContent)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to decode ImagePullIntent from file %q: %w", filePath, err)
|
||||
}
|
||||
if !isCurrentVersion {
|
||||
if err := f.WriteImagePullIntent(intent.Image); err != nil {
|
||||
return fmt.Errorf("failed to migrate ImagePullIntent for image %q to the current version: %w", intent.Image, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
klog.ErrorS(err, "Error migrating image pull intents")
|
||||
}
|
||||
err = processDirFiles(f.pulledDir,
|
||||
func(filePath string, fileContent []byte) error {
|
||||
pullRecord, isCurrentVersion, err := decodePulledRecord(f.decoder, fileContent)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to decode ImagePulledRecord from file %q: %w", filePath, err)
|
||||
}
|
||||
if !isCurrentVersion {
|
||||
if err := f.WriteImagePulledRecord(pullRecord); err != nil {
|
||||
return fmt.Errorf("failed to migrate ImagePulledRecord for image ref %q to the current version: %w", pullRecord.ImageRef, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
klog.ErrorS(err, "Error migrating image pulled records")
|
||||
}
|
||||
}
|
||||
|
||||
func (f *fsPullRecordsAccessor) WriteImagePullIntent(image string) error {
|
||||
intent := kubeletconfiginternal.ImagePullIntent{
|
||||
Image: image,
|
||||
@@ -97,7 +138,7 @@ func (f *fsPullRecordsAccessor) ListImagePullIntents() ([]*kubeletconfiginternal
|
||||
// walk the pulling directory for any pull intent records
|
||||
err := processDirFiles(f.pullingDir,
|
||||
func(filePath string, fileContent []byte) error {
|
||||
intent, err := decodeIntent(f.decoder, fileContent)
|
||||
intent, _, err := decodeIntent(f.decoder, fileContent)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to deserialize content of file %q into ImagePullIntent: %w", filePath, err)
|
||||
}
|
||||
@@ -117,7 +158,7 @@ func (f *fsPullRecordsAccessor) ImagePullIntentExists(image string) (bool, error
|
||||
return false, err
|
||||
}
|
||||
|
||||
intent, err := decodeIntent(f.decoder, intentBytes)
|
||||
intent, _, err := decodeIntent(f.decoder, intentBytes)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -141,7 +182,7 @@ func (f *fsPullRecordsAccessor) GetImagePulledRecord(imageRef string) (*kubeletc
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
pulledRecord, err := decodePulledRecord(f.decoder, recordBytes)
|
||||
pulledRecord, _, err := decodePulledRecord(f.decoder, recordBytes)
|
||||
if err != nil {
|
||||
return nil, true, err
|
||||
}
|
||||
@@ -155,7 +196,7 @@ func (f *fsPullRecordsAccessor) ListImagePulledRecords() ([]*kubeletconfigintern
|
||||
var pullRecords []*kubeletconfiginternal.ImagePulledRecord
|
||||
err := processDirFiles(f.pulledDir,
|
||||
func(filePath string, fileContent []byte) error {
|
||||
pullRecord, err := decodePulledRecord(f.decoder, fileContent)
|
||||
pullRecord, _, err := decodePulledRecord(f.decoder, fileContent)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to deserialize content of file %q into ImagePulledRecord: %w", filePath, err)
|
||||
}
|
||||
@@ -311,10 +352,21 @@ func processDirFiles(dirName string, fileAction func(filePath string, fileConten
|
||||
// createKubeletCOnfigSchemeEncoderDecoder creates strict-encoding encoder and
|
||||
// decoder for the internal and alpha kubelet config APIs.
|
||||
func createKubeletConfigSchemeEncoderDecoder() (runtime.Encoder, runtime.Decoder, error) {
|
||||
codecs, info, err := getKubeletConfigSerializerInfo()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return codecs.EncoderForVersion(info.Serializer, encodeVersion), codecs.UniversalDecoder(), nil
|
||||
}
|
||||
|
||||
func getKubeletConfigSerializerInfo() (*serializer.CodecFactory, *runtime.SerializerInfo, error) {
|
||||
const mediaType = runtime.ContentTypeJSON
|
||||
|
||||
scheme := runtime.NewScheme()
|
||||
if err := kubeletconfigvint1alpha1.AddToScheme(scheme); err != nil {
|
||||
if err := kubeletconfigint1beta1.AddToScheme(scheme); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := kubeletconfigint1alpha1.AddToScheme(scheme); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := kubeletconfiginternal.AddToScheme(scheme); err != nil {
|
||||
@@ -328,33 +380,45 @@ func createKubeletConfigSchemeEncoderDecoder() (runtime.Encoder, runtime.Decoder
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("unable to locate encoder -- %q is not a supported media type", mediaType)
|
||||
}
|
||||
return codecs.EncoderForVersion(info.Serializer, kubeletconfigv1alpha1.SchemeGroupVersion), codecs.UniversalDecoder(), nil
|
||||
return &codecs, &info, nil
|
||||
}
|
||||
|
||||
func decodeIntent(d runtime.Decoder, objBytes []byte) (*kubeletconfiginternal.ImagePullIntent, error) {
|
||||
obj, _, err := d.Decode(objBytes, nil, nil)
|
||||
// decodeIntent decodes the image pull intent and converts it to the internal API version.
|
||||
// The decoder must be aware of the schemas available for the kubelet config API.
|
||||
//
|
||||
// The returned object is an internal representation of the image pull intent and a bool
|
||||
// that indicates whether the image pull intent appears in the latest known version of the kubelet config API.
|
||||
func decodeIntent(d runtime.Decoder, objBytes []byte) (*kubeletconfiginternal.ImagePullIntent, bool, error) {
|
||||
obj, gvk, err := d.Decode(objBytes, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
intentObj, ok := obj.(*kubeletconfiginternal.ImagePullIntent)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("failed to convert object to *ImagePullIntent: %T", obj)
|
||||
return nil, false, fmt.Errorf("failed to convert object to *ImagePullIntent: %T", obj)
|
||||
}
|
||||
|
||||
return intentObj, nil
|
||||
isLatestVersion := gvk.Version == encodeVersion.Version
|
||||
return intentObj, isLatestVersion, nil
|
||||
}
|
||||
|
||||
func decodePulledRecord(d runtime.Decoder, objBytes []byte) (*kubeletconfiginternal.ImagePulledRecord, error) {
|
||||
obj, _, err := d.Decode(objBytes, nil, nil)
|
||||
// decodePulledRecord decodes the pulled record and converts it to the internal API version.
|
||||
// The decoder must be aware of the schemas available for the kubelet config API.
|
||||
//
|
||||
// The returned object is an internal representation of the pulled record and a bool
|
||||
// that indicates whether the record appears in the latest known version of the kubelet config API.
|
||||
func decodePulledRecord(d runtime.Decoder, objBytes []byte) (*kubeletconfiginternal.ImagePulledRecord, bool, error) {
|
||||
obj, gvk, err := d.Decode(objBytes, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
pulledRecord, ok := obj.(*kubeletconfiginternal.ImagePulledRecord)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("failed to convert object to *ImagePulledRecord: %T", obj)
|
||||
return nil, false, fmt.Errorf("failed to convert object to *ImagePulledRecord: %T", obj)
|
||||
}
|
||||
|
||||
return pulledRecord, nil
|
||||
isLatestVersion := gvk.Version == encodeVersion.Version
|
||||
return pulledRecord, isLatestVersion, nil
|
||||
}
|
||||
|
||||
201
pkg/kubelet/images/pullmanager/fs_pullrecords_test.go
Normal file
201
pkg/kubelet/images/pullmanager/fs_pullrecords_test.go
Normal file
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
Copyright 2025 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 pullmanager
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
)
|
||||
|
||||
func TestNewFSPullRecordsAccessor(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
initRoot bool
|
||||
initIntents []string
|
||||
initPulled []string
|
||||
modIntent func(string) string
|
||||
modPulledRecord func(string) string
|
||||
wantErr bool // TODO: do I ever want an error?
|
||||
}{
|
||||
{
|
||||
name: "kubelet root dir does not exist",
|
||||
initRoot: false,
|
||||
},
|
||||
{
|
||||
name: "kubelet root dir exists",
|
||||
initRoot: true,
|
||||
},
|
||||
{
|
||||
name: "only alpha intents",
|
||||
initRoot: true,
|
||||
initIntents: []string{
|
||||
"sha256-6da3dced7eccc7ad0189517c31ec2235b50f730449d738d91525721f7e027fd4",
|
||||
"sha256-b6e1482bb6cb030924530b918e609fff30bbb07ab6845451d89deb823c3f72a9",
|
||||
},
|
||||
modIntent: func(intent string) string {
|
||||
return strings.Replace(intent, "kubelet.config.k8s.io/v1alpha1", "kubelet.config.k8s.io/v1beta1", 1)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "alpha and beta intents mixed",
|
||||
initRoot: true,
|
||||
initIntents: []string{
|
||||
"sha256-aef2af226629a35d5f3ef0fdbb29fdbebf038d0acd8850590e8c48e1e283aa56",
|
||||
"sha256-6da3dced7eccc7ad0189517c31ec2235b50f730449d738d91525721f7e027fd4",
|
||||
"sha256-ee81caca15454863449fb55a1d942904d56d5ed9f9b20a7cb3453944ea2c7e11",
|
||||
"sha256-b6e1482bb6cb030924530b918e609fff30bbb07ab6845451d89deb823c3f72a9",
|
||||
},
|
||||
modIntent: func(intent string) string {
|
||||
return strings.Replace(intent, "kubelet.config.k8s.io/v1alpha1", "kubelet.config.k8s.io/v1beta1", 1)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "only beta intents",
|
||||
initRoot: true,
|
||||
initIntents: []string{
|
||||
"sha256-aef2af226629a35d5f3ef0fdbb29fdbebf038d0acd8850590e8c48e1e283aa56",
|
||||
"sha256-ee81caca15454863449fb55a1d942904d56d5ed9f9b20a7cb3453944ea2c7e11",
|
||||
"sha256-f24acc752be18b93b0504c86312bbaf482c9efb0c45e925bbccb0a591cebd7af",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "only alpha pulled records",
|
||||
initRoot: true,
|
||||
initPulled: []string{
|
||||
"sha256-7045bdd498b0e4b3963d50f906793ffbd68dc98686ec46c5b499a0a640a560b2",
|
||||
"sha256-dd1dd8dc6a329b7e1c2e43951302b23a047cb20fd3e10090e4ce7e8396035405",
|
||||
},
|
||||
modPulledRecord: func(intent string) string {
|
||||
return strings.Replace(intent, "kubelet.config.k8s.io/v1alpha1", "kubelet.config.k8s.io/v1beta1", 1)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "alpha and beta pulled records mixed",
|
||||
initRoot: true,
|
||||
initPulled: []string{
|
||||
"sha256-7045bdd498b0e4b3963d50f906793ffbd68dc98686ec46c5b499a0a640a560b2",
|
||||
"sha256-38a8906435c4dd5f4258899d46621bfd8eea3ad6ff494ee3c2f17ef0321625bd",
|
||||
"sha256-dd1dd8dc6a329b7e1c2e43951302b23a047cb20fd3e10090e4ce7e8396035405",
|
||||
"sha256-a2eace2182b24cdbbb730798e47b10709b9ef5e0f0c1624a3bc06c8ca987727a",
|
||||
"sha256-f8778b6393eaf39315e767a58cbeacf2c4b270d94b4d6926ee993d9e49444991",
|
||||
},
|
||||
modPulledRecord: func(intent string) string {
|
||||
return strings.Replace(intent, "kubelet.config.k8s.io/v1alpha1", "kubelet.config.k8s.io/v1beta1", 1)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "only beta pulled records",
|
||||
initRoot: true,
|
||||
initPulled: []string{
|
||||
"sha256-38a8906435c4dd5f4258899d46621bfd8eea3ad6ff494ee3c2f17ef0321625bd",
|
||||
"sha256-a2eace2182b24cdbbb730798e47b10709b9ef5e0f0c1624a3bc06c8ca987727a",
|
||||
"sha256-f8778b6393eaf39315e767a58cbeacf2c4b270d94b4d6926ee993d9e49444991",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "everything altogether",
|
||||
initRoot: true,
|
||||
initIntents: []string{
|
||||
"sha256-aef2af226629a35d5f3ef0fdbb29fdbebf038d0acd8850590e8c48e1e283aa56",
|
||||
"sha256-6da3dced7eccc7ad0189517c31ec2235b50f730449d738d91525721f7e027fd4",
|
||||
"sha256-ee81caca15454863449fb55a1d942904d56d5ed9f9b20a7cb3453944ea2c7e11",
|
||||
"sha256-b6e1482bb6cb030924530b918e609fff30bbb07ab6845451d89deb823c3f72a9",
|
||||
},
|
||||
modIntent: func(intent string) string {
|
||||
return strings.Replace(intent, "kubelet.config.k8s.io/v1alpha1", "kubelet.config.k8s.io/v1beta1", 1)
|
||||
},
|
||||
initPulled: []string{
|
||||
"sha256-7045bdd498b0e4b3963d50f906793ffbd68dc98686ec46c5b499a0a640a560b2",
|
||||
"sha256-38a8906435c4dd5f4258899d46621bfd8eea3ad6ff494ee3c2f17ef0321625bd",
|
||||
"sha256-dd1dd8dc6a329b7e1c2e43951302b23a047cb20fd3e10090e4ce7e8396035405",
|
||||
"sha256-a2eace2182b24cdbbb730798e47b10709b9ef5e0f0c1624a3bc06c8ca987727a",
|
||||
"sha256-f8778b6393eaf39315e767a58cbeacf2c4b270d94b4d6926ee993d9e49444991",
|
||||
},
|
||||
modPulledRecord: func(intent string) string {
|
||||
return strings.Replace(intent, "kubelet.config.k8s.io/v1alpha1", "kubelet.config.k8s.io/v1beta1", 1)
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
kubeletDir := t.TempDir()
|
||||
if !tt.initRoot {
|
||||
kubeletDir = filepath.Join(kubeletDir, "does-not-exist", "level2dir")
|
||||
}
|
||||
|
||||
intentsDir := filepath.Join(kubeletDir, "image_manager", "pulling")
|
||||
pulledRecordsDir := filepath.Join(kubeletDir, "image_manager", "pulled")
|
||||
|
||||
expectedIntents := teeTestData(t, intentsDir, "pulling", tt.initIntents)
|
||||
if tt.modIntent != nil {
|
||||
for i := range expectedIntents {
|
||||
expectedIntents[i] = tt.modIntent(expectedIntents[i])
|
||||
}
|
||||
}
|
||||
pulledRecordBytes := teeTestData(t, pulledRecordsDir, "pulled", tt.initPulled)
|
||||
if tt.modPulledRecord != nil {
|
||||
for i := range pulledRecordBytes {
|
||||
pulledRecordBytes[i] = tt.modPulledRecord(pulledRecordBytes[i])
|
||||
}
|
||||
}
|
||||
|
||||
_, err := NewFSPullRecordsAccessor(kubeletDir)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("NewFSPullRecordsAccessor() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
|
||||
for _, dir := range []string{
|
||||
"image_manager",
|
||||
filepath.Join("image_manager", "pulling"),
|
||||
filepath.Join("image_manager", "pulled"),
|
||||
} {
|
||||
if info, err := os.Stat(filepath.Join(kubeletDir, dir)); err != nil {
|
||||
t.Errorf("error encountered accessing %q: %v", dir, err)
|
||||
} else if !info.IsDir() {
|
||||
t.Errorf("%q is not a directory", dir)
|
||||
}
|
||||
}
|
||||
|
||||
for intent, expectedContent := range expectedIntents {
|
||||
filePath := filepath.Join(intentsDir, intent)
|
||||
testFileContentMatch(t, filePath, expectedContent)
|
||||
}
|
||||
|
||||
for pulled, expectedContent := range pulledRecordBytes {
|
||||
filePath := filepath.Join(pulledRecordsDir, pulled)
|
||||
testFileContentMatch(t, filePath, expectedContent)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func testFileContentMatch(t *testing.T, filePath string, expectedContent string) {
|
||||
t.Helper()
|
||||
fileContent, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to read file %q: %v", filePath, err)
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(expectedContent, string(fileContent)); diff != "" {
|
||||
t.Errorf("file contents of %q do not match the expectation: %s", filePath, diff)
|
||||
}
|
||||
}
|
||||
@@ -758,8 +758,8 @@ func TestFileBasedImagePullManager_MustAttemptImagePull(t *testing.T) {
|
||||
pullingDir := filepath.Join(testDir, "pulling")
|
||||
pulledDir := filepath.Join(testDir, "pulled")
|
||||
|
||||
copyTestData(t, pullingDir, "pulling", tt.pullingFiles)
|
||||
copyTestData(t, pulledDir, "pulled", tt.pulledFiles)
|
||||
_ = teeTestData(t, pullingDir, "pulling", tt.pullingFiles)
|
||||
_ = teeTestData(t, pulledDir, "pulled", tt.pulledFiles)
|
||||
|
||||
fsRecordAccessor := &testWriteCountingFSPullRecordsAccessor{
|
||||
fsPullRecordsAccessor: fsPullRecordsAccessor{
|
||||
@@ -1157,8 +1157,8 @@ func TestFileBasedImagePullManager_RecordImagePulled(t *testing.T) {
|
||||
pullingDir := filepath.Join(testDir, "pulling")
|
||||
pulledDir := filepath.Join(testDir, "pulled")
|
||||
|
||||
copyTestData(t, pullingDir, "pulling", tt.existingPulling)
|
||||
copyTestData(t, pulledDir, "pulled", tt.existingPulled)
|
||||
_ = teeTestData(t, pullingDir, "pulling", tt.existingPulling)
|
||||
_ = teeTestData(t, pulledDir, "pulled", tt.existingPulled)
|
||||
|
||||
fsRecordAccessor := &fsPullRecordsAccessor{
|
||||
pullingDir: pullingDir,
|
||||
@@ -1193,7 +1193,7 @@ func TestFileBasedImagePullManager_RecordImagePulled(t *testing.T) {
|
||||
t.Fatalf("failed to read the expected image pulled record: %v", err)
|
||||
}
|
||||
|
||||
got, err := decodePulledRecord(decoder, pulledBytes)
|
||||
got, _, err := decodePulledRecord(decoder, pulledBytes)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to deserialize the image pulled record: %v", err)
|
||||
}
|
||||
@@ -1332,8 +1332,8 @@ func TestFileBasedImagePullManager_initialize(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
copyTestData(t, pullingDir, "pulling", tt.existingIntents)
|
||||
copyTestData(t, pulledDir, "pulled", tt.existingPulledRecords)
|
||||
_ = teeTestData(t, pullingDir, "pulling", tt.existingIntents)
|
||||
_ = teeTestData(t, pulledDir, "pulled", tt.existingPulledRecords)
|
||||
|
||||
fsRecordAccessor := &fsPullRecordsAccessor{
|
||||
pullingDir: pullingDir,
|
||||
@@ -1449,7 +1449,7 @@ func TestFileBasedImagePullManager_PruneUnknownRecords(t *testing.T) {
|
||||
t.Fatalf("failed to create testing dir %q: %v", pulledDir, err)
|
||||
}
|
||||
|
||||
copyTestData(t, pulledDir, "pulled", tt.pulledFiles)
|
||||
_ = teeTestData(t, pulledDir, "pulled", tt.pulledFiles)
|
||||
|
||||
fsRecordAccessor := &fsPullRecordsAccessor{
|
||||
pulledDir: pulledDir,
|
||||
@@ -1487,7 +1487,9 @@ func TestFileBasedImagePullManager_PruneUnknownRecords(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func copyTestData(t *testing.T, dstDir string, testdataDir string, src []string) {
|
||||
func teeTestData(t *testing.T, dstDir string, testdataDir string, src []string) map[string]string {
|
||||
t.Helper()
|
||||
ret := make(map[string]string, len(src))
|
||||
for _, f := range src {
|
||||
testBytes, err := os.ReadFile(filepath.Join("testdata", testdataDir, f))
|
||||
if err != nil {
|
||||
@@ -1496,7 +1498,9 @@ func copyTestData(t *testing.T, dstDir string, testdataDir string, src []string)
|
||||
if err := writeFile(dstDir, f, testBytes); err != nil {
|
||||
t.Fatalf("failed to write test data: %v", err)
|
||||
}
|
||||
ret[f] = string(testBytes)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func withImageRecord(r *kubeletconfiginternal.ImagePulledRecord, image string, record kubeletconfiginternal.ImagePullCredentials) *kubeletconfiginternal.ImagePulledRecord {
|
||||
|
||||
@@ -193,7 +193,7 @@ func TestMustAttemptPullMetrics(t *testing.T) {
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
copyTestData(t, pulledDir, "pulled", []string{
|
||||
teeTestData(t, pulledDir, "pulled", []string{
|
||||
"sha256-e766e4624f9bc4d3847d6c5b470d9d5362cc8d0c250bd9572daf95278e044263",
|
||||
"sha256-a2eace2182b24cdbbb730798e47b10709b9ef5e0f0c1624a3bc06c8ca987727a",
|
||||
"sha256-f4058727984875eb66ddbf289f7013096d4cbaa167e591fbcb2e447e36391c1f",
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"kind":"ImagePulledRecord","apiVersion":"kubelet.config.k8s.io/v1alpha1","lastUpdatedTime":"2024-10-21T12:26:40Z","imageRef":"test-brokenhash","credentialMapping":{"docker.io/testing/test":{"kubernetesSecrets":[{"uid":"testsecretuid","namespace":"default","name":"pull-secret","credentialHash":""}]}}}
|
||||
{"kind":"ImagePulledRecord","apiVersion":"kubelet.config.k8s.io/v1beta1","lastUpdatedTime":"2024-10-21T12:26:40Z","imageRef":"test-brokenhash","credentialMapping":{"docker.io/testing/test":{"kubernetesSecrets":[{"uid":"testsecretuid","namespace":"default","name":"pull-secret","credentialHash":""}]}}}
|
||||
@@ -0,0 +1 @@
|
||||
{"kind":"ImagePulledRecord","apiVersion":"kubelet.config.k8s.io/v1alpha1","lastUpdatedTime":"2024-10-21T12:26:40Z","imageRef":"testemptycredmapping-alpha"}
|
||||
@@ -1 +1 @@
|
||||
{"kind":"ImagePulledRecord","apiVersion":"kubelet.config.k8s.io/v1alpha1","lastUpdatedTime":"2024-10-21T12:26:40Z","imageRef":"testimage-anonpull","credentialMapping":{"docker.io/testing/test":{"nodePodsAccessible":true}}}
|
||||
{"kind":"ImagePulledRecord","apiVersion":"kubelet.config.k8s.io/v1beta1","lastUpdatedTime":"2024-10-21T12:26:40Z","imageRef":"testimage-anonpull","credentialMapping":{"docker.io/testing/test":{"nodePodsAccessible":true}}}
|
||||
@@ -1 +1 @@
|
||||
{"kind":"ImagePulledRecord","apiVersion":"kubelet.config.k8s.io/v1alpha1","lastUpdatedTime":"2024-10-21T12:26:40Z","imageRef":"testimageref","credentialMapping":{"docker.io/testing/test":{"kubernetesSecrets":[{"uid":"testsecretuid","namespace":"default","name":"pull-secret","credentialHash":"testsecrethash"}]}}}
|
||||
{"kind":"ImagePulledRecord","apiVersion":"kubelet.config.k8s.io/v1beta1","lastUpdatedTime":"2024-10-21T12:26:40Z","imageRef":"testimageref","credentialMapping":{"docker.io/testing/test":{"kubernetesSecrets":[{"uid":"testsecretuid","namespace":"default","name":"pull-secret","credentialHash":"testsecrethash"}]}}}
|
||||
@@ -0,0 +1 @@
|
||||
{"kind":"ImagePulledRecord","apiVersion":"kubelet.config.k8s.io/v1alpha1","lastUpdatedTime":"2025-06-21T12:26:40Z","imageRef":"testimage-anonpull-alpha","credentialMapping":{"docker.io/testing/test":{"nodePodsAccessible":true}}}
|
||||
@@ -1 +1 @@
|
||||
{"kind":"ImagePulledRecord","apiVersion":"kubelet.config.k8s.io/v1alpha1","lastUpdatedTime":"2024-10-21T12:26:40Z","imageRef":"testemptycredmapping"}
|
||||
{"kind":"ImagePulledRecord","apiVersion":"kubelet.config.k8s.io/v1beta1","lastUpdatedTime":"2024-10-21T12:26:40Z","imageRef":"testemptycredmapping"}
|
||||
@@ -0,0 +1 @@
|
||||
{"kind":"ImagePullIntent","apiVersion":"kubelet.config.k8s.io/v1alpha1","image":"docker.io/testing/test-alpha:latest"}
|
||||
@@ -1 +1 @@
|
||||
{"kind":"ImagePullIntent","apiVersion":"kubelet.config.k8s.io/v1alpha1","image":"docker.io/testing/test:latest"}
|
||||
{"kind":"ImagePullIntent","apiVersion":"kubelet.config.k8s.io/v1beta1","image":"docker.io/testing/test:latest"}
|
||||
@@ -0,0 +1 @@
|
||||
{"kind":"ImagePullIntent","apiVersion":"kubelet.config.k8s.io/v1alpha1","image":"repo.repo/test/alphatest:v1"}
|
||||
@@ -1 +1 @@
|
||||
{"kind":"ImagePullIntent","apiVersion":"kubelet.config.k8s.io/v1alpha1","image":"repo.repo/test/test:v1"}
|
||||
{"kind":"ImagePullIntent","apiVersion":"kubelet.config.k8s.io/v1beta1","image":"repo.repo/test/test:v1"}
|
||||
@@ -1 +1 @@
|
||||
{"kind":"ImagePullIntent","apiVersion":"kubelet.config.k8s.io/v1alpha1","image":"docker.io/testing/test:something"}
|
||||
{"kind":"ImagePullIntent","apiVersion":"kubelet.config.k8s.io/v1beta1","image":"docker.io/testing/test:something"}
|
||||
@@ -147,7 +147,7 @@ type ImagePullCredentials struct {
|
||||
// secrets that were used to pull the image.
|
||||
// +optional
|
||||
// +listType=set
|
||||
KubernetesSecrets []ImagePullSecret `json:"kubernetesSecrets"`
|
||||
KubernetesSecrets []ImagePullSecret `json:"kubernetesSecrets,omitempty"`
|
||||
|
||||
// KubernetesServiceAccounts is an index of coordinates of all the kubernetes
|
||||
// service accounts that were used to pull the image.
|
||||
|
||||
@@ -40,6 +40,8 @@ func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
&KubeletConfiguration{},
|
||||
&SerializedNodeConfigSource{},
|
||||
&CredentialProviderConfig{},
|
||||
&ImagePullIntent{},
|
||||
&ImagePulledRecord{},
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1135,3 +1135,89 @@ type UserNamespaces struct {
|
||||
// +optional
|
||||
IDsPerPod *int64 `json:"idsPerPod,omitempty"`
|
||||
}
|
||||
|
||||
// ImagePullIntent is a record of the kubelet attempting to pull an image.
|
||||
//
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
type ImagePullIntent struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
|
||||
// Image is the image spec from a Container's `image` field.
|
||||
// The filename is a SHA-256 hash of this value. This is to avoid filename-unsafe
|
||||
// characters like ':' and '/'.
|
||||
Image string `json:"image"`
|
||||
}
|
||||
|
||||
// ImagePullRecord is a record of an image that was pulled by the kubelet.
|
||||
//
|
||||
// If there are no records in the `kubernetesSecrets` field and both `nodeWideCredentials`
|
||||
// and `anonymous` are `false`, credentials must be re-checked the next time an
|
||||
// image represented by this record is being requested.
|
||||
//
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
type ImagePulledRecord struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
|
||||
// LastUpdatedTime is the time of the last update to this record
|
||||
LastUpdatedTime metav1.Time `json:"lastUpdatedTime"`
|
||||
|
||||
// ImageRef is a reference to the image represented by this file as received
|
||||
// from the CRI.
|
||||
// The filename is a SHA-256 hash of this value. This is to avoid filename-unsafe
|
||||
// characters like ':' and '/'.
|
||||
ImageRef string `json:"imageRef"`
|
||||
|
||||
// CredentialMapping maps `image` to the set of credentials that it was
|
||||
// previously pulled with.
|
||||
// `image` in this case is the content of a pod's container `image` field that's
|
||||
// got its tag/digest removed.
|
||||
//
|
||||
// Example:
|
||||
// Container requests the `hello-world:latest@sha256:91fb4b041da273d5a3273b6d587d62d518300a6ad268b28628f74997b93171b2` image:
|
||||
// "credentialMapping": {
|
||||
// "hello-world": { "nodePodsAccessible": true }
|
||||
// }
|
||||
CredentialMapping map[string]ImagePullCredentials `json:"credentialMapping,omitempty"`
|
||||
}
|
||||
|
||||
// ImagePullCredentials describe credentials that can be used to pull an image.
|
||||
type ImagePullCredentials struct {
|
||||
// KubernetesSecretCoordinates is an index of coordinates of all the kubernetes
|
||||
// secrets that were used to pull the image.
|
||||
// +optional
|
||||
// +listType=set
|
||||
KubernetesSecrets []ImagePullSecret `json:"kubernetesSecrets,omitempty"`
|
||||
|
||||
// KubernetesServiceAccounts is an index of coordinates of all the kubernetes
|
||||
// service accounts that were used to pull the image.
|
||||
// +optional
|
||||
// +listType=set
|
||||
KubernetesServiceAccounts []ImagePullServiceAccount `json:"kubernetesServiceAccounts,omitempty"`
|
||||
|
||||
// NodePodsAccessible is a flag denoting the pull credentials are accessible
|
||||
// by all the pods on the node, or that no credentials are needed for the pull.
|
||||
//
|
||||
// If true, it is mutually exclusive with the `kubernetesSecrets` field.
|
||||
// +optional
|
||||
NodePodsAccessible bool `json:"nodePodsAccessible,omitempty"`
|
||||
}
|
||||
|
||||
// ImagePullSecret is a representation of a Kubernetes secret object coordinates along
|
||||
// with a credential hash of the pull secret credentials this object contains.
|
||||
type ImagePullSecret struct {
|
||||
UID string `json:"uid"`
|
||||
Namespace string `json:"namespace"`
|
||||
Name string `json:"name"`
|
||||
|
||||
// CredentialHash is a SHA-256 retrieved by hashing the image pull credentials
|
||||
// content of the secret specified by the UID/Namespace/Name coordinates.
|
||||
CredentialHash string `json:"credentialHash"`
|
||||
}
|
||||
|
||||
// ImagePullServiceAccount is a representation of a Kubernetes service account object coordinates
|
||||
// for which the kubelet sent service account token to the credential provider plugin for image pull credentials.
|
||||
type ImagePullServiceAccount struct {
|
||||
UID string `json:"uid"`
|
||||
Namespace string `json:"namespace"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
@@ -133,6 +133,122 @@ func (in *ExecEnvVar) DeepCopy() *ExecEnvVar {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ImagePullCredentials) DeepCopyInto(out *ImagePullCredentials) {
|
||||
*out = *in
|
||||
if in.KubernetesSecrets != nil {
|
||||
in, out := &in.KubernetesSecrets, &out.KubernetesSecrets
|
||||
*out = make([]ImagePullSecret, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.KubernetesServiceAccounts != nil {
|
||||
in, out := &in.KubernetesServiceAccounts, &out.KubernetesServiceAccounts
|
||||
*out = make([]ImagePullServiceAccount, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImagePullCredentials.
|
||||
func (in *ImagePullCredentials) DeepCopy() *ImagePullCredentials {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ImagePullCredentials)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ImagePullIntent) DeepCopyInto(out *ImagePullIntent) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImagePullIntent.
|
||||
func (in *ImagePullIntent) DeepCopy() *ImagePullIntent {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ImagePullIntent)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *ImagePullIntent) 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 *ImagePullSecret) DeepCopyInto(out *ImagePullSecret) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImagePullSecret.
|
||||
func (in *ImagePullSecret) DeepCopy() *ImagePullSecret {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ImagePullSecret)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ImagePullServiceAccount) DeepCopyInto(out *ImagePullServiceAccount) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImagePullServiceAccount.
|
||||
func (in *ImagePullServiceAccount) DeepCopy() *ImagePullServiceAccount {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ImagePullServiceAccount)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ImagePulledRecord) DeepCopyInto(out *ImagePulledRecord) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.LastUpdatedTime.DeepCopyInto(&out.LastUpdatedTime)
|
||||
if in.CredentialMapping != nil {
|
||||
in, out := &in.CredentialMapping, &out.CredentialMapping
|
||||
*out = make(map[string]ImagePullCredentials, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = *val.DeepCopy()
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImagePulledRecord.
|
||||
func (in *ImagePulledRecord) DeepCopy() *ImagePulledRecord {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ImagePulledRecord)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *ImagePulledRecord) 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 *KubeletAnonymousAuthentication) DeepCopyInto(out *KubeletAnonymousAuthentication) {
|
||||
*out = *in
|
||||
|
||||
@@ -41,6 +41,31 @@ func (in ExecEnvVar) OpenAPIModelName() string {
|
||||
return "io.k8s.kubelet.config.v1beta1.ExecEnvVar"
|
||||
}
|
||||
|
||||
// OpenAPIModelName returns the OpenAPI model name for this type.
|
||||
func (in ImagePullCredentials) OpenAPIModelName() string {
|
||||
return "io.k8s.kubelet.config.v1beta1.ImagePullCredentials"
|
||||
}
|
||||
|
||||
// OpenAPIModelName returns the OpenAPI model name for this type.
|
||||
func (in ImagePullIntent) OpenAPIModelName() string {
|
||||
return "io.k8s.kubelet.config.v1beta1.ImagePullIntent"
|
||||
}
|
||||
|
||||
// OpenAPIModelName returns the OpenAPI model name for this type.
|
||||
func (in ImagePullSecret) OpenAPIModelName() string {
|
||||
return "io.k8s.kubelet.config.v1beta1.ImagePullSecret"
|
||||
}
|
||||
|
||||
// OpenAPIModelName returns the OpenAPI model name for this type.
|
||||
func (in ImagePullServiceAccount) OpenAPIModelName() string {
|
||||
return "io.k8s.kubelet.config.v1beta1.ImagePullServiceAccount"
|
||||
}
|
||||
|
||||
// OpenAPIModelName returns the OpenAPI model name for this type.
|
||||
func (in ImagePulledRecord) OpenAPIModelName() string {
|
||||
return "io.k8s.kubelet.config.v1beta1.ImagePulledRecord"
|
||||
}
|
||||
|
||||
// OpenAPIModelName returns the OpenAPI model name for this type.
|
||||
func (in KubeletAnonymousAuthentication) OpenAPIModelName() string {
|
||||
return "io.k8s.kubelet.config.v1beta1.KubeletAnonymousAuthentication"
|
||||
|
||||
Reference in New Issue
Block a user