Merge pull request #123372 from carlory/fix-kubeadm-494
kubeadm certs check-expiration support json/yaml output
This commit is contained in:
		@@ -39,6 +39,7 @@ func addKnownTypes(scheme *runtime.Scheme) error {
 | 
			
		||||
		&BootstrapToken{},
 | 
			
		||||
		&Images{},
 | 
			
		||||
		&UpgradePlan{},
 | 
			
		||||
		&CertificateExpirationInfo{},
 | 
			
		||||
	)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -25,6 +25,7 @@ import (
 | 
			
		||||
 | 
			
		||||
	"k8s.io/kubernetes/cmd/kubeadm/app/apis/output"
 | 
			
		||||
	"k8s.io/kubernetes/cmd/kubeadm/app/apis/output/v1alpha2"
 | 
			
		||||
	"k8s.io/kubernetes/cmd/kubeadm/app/apis/output/v1alpha3"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Scheme is the runtime.Scheme to which all kubeadm api types are registered.
 | 
			
		||||
@@ -42,5 +43,6 @@ func init() {
 | 
			
		||||
func AddToScheme(scheme *runtime.Scheme) {
 | 
			
		||||
	utilruntime.Must(output.AddToScheme(scheme))
 | 
			
		||||
	utilruntime.Must(v1alpha2.AddToScheme(scheme))
 | 
			
		||||
	utilruntime.Must(scheme.SetVersionPriority(v1alpha2.SchemeGroupVersion))
 | 
			
		||||
	utilruntime.Must(v1alpha3.AddToScheme(scheme))
 | 
			
		||||
	utilruntime.Must(scheme.SetVersionPriority(v1alpha3.SchemeGroupVersion, v1alpha2.SchemeGroupVersion))
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -82,3 +82,38 @@ type UpgradePlan struct {
 | 
			
		||||
 | 
			
		||||
	ConfigVersions []ComponentConfigVersionState
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Certificate represents information for a certificate or a certificate authority when using the check-expiration command.
 | 
			
		||||
type Certificate struct {
 | 
			
		||||
	// Name of the certificate.
 | 
			
		||||
	Name string
 | 
			
		||||
 | 
			
		||||
	// ExpirationDate defines certificate expiration date in UTC following the RFC3339 format.
 | 
			
		||||
	ExpirationDate metav1.Time
 | 
			
		||||
 | 
			
		||||
	// ResidualTimeSeconds represents the duration in seconds relative to the residual time before expiration.
 | 
			
		||||
	ResidualTimeSeconds int64
 | 
			
		||||
 | 
			
		||||
	// ExternallyManaged defines if the certificate is externally managed.
 | 
			
		||||
	ExternallyManaged bool
 | 
			
		||||
 | 
			
		||||
	// CAName represents the name of the CA that signed the certificate.
 | 
			
		||||
	// This field is empty for self-signed, root CA certificates.
 | 
			
		||||
	CAName string
 | 
			
		||||
 | 
			
		||||
	// Missing represents if the certificate is missing.
 | 
			
		||||
	Missing bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 | 
			
		||||
 | 
			
		||||
// CertificateExpirationInfo represents information for the output produced by 'kubeadm certs check-expiration'.
 | 
			
		||||
type CertificateExpirationInfo struct {
 | 
			
		||||
	metav1.TypeMeta
 | 
			
		||||
 | 
			
		||||
	// Certificates holds a list of certificates to show expiration information for.
 | 
			
		||||
	Certificates []Certificate
 | 
			
		||||
 | 
			
		||||
	// CertificateAuthorities holds a list of certificate authorities to show expiration information for.
 | 
			
		||||
	CertificateAuthorities []Certificate
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -23,4 +23,5 @@ limitations under the License.
 | 
			
		||||
// The purpose of the kubeadm structured output is to have a well
 | 
			
		||||
// defined versioned output format that other software that uses
 | 
			
		||||
// kubeadm for cluster deployments can use and rely on.
 | 
			
		||||
// DEPRECATED: this API will be removed in a future release. Please use v1alpha3.
 | 
			
		||||
package v1alpha2 // import "k8s.io/kubernetes/cmd/kubeadm/app/apis/output/v1alpha2"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										30
									
								
								cmd/kubeadm/app/apis/output/v1alpha3/doc.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								cmd/kubeadm/app/apis/output/v1alpha3/doc.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
/*
 | 
			
		||||
Copyright 2024 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.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
// +groupName=output.kubeadm.k8s.io
 | 
			
		||||
// +k8s:deepcopy-gen=package
 | 
			
		||||
// +k8s:conversion-gen=k8s.io/kubernetes/cmd/kubeadm/app/apis/output
 | 
			
		||||
 | 
			
		||||
// Package v1alpha3 defines the v1alpha3 version of the kubeadm data structures
 | 
			
		||||
// related to structured output
 | 
			
		||||
// The purpose of the kubeadm structured output is to have a well
 | 
			
		||||
// defined versioned output format that other software that uses
 | 
			
		||||
// kubeadm for cluster deployments can use and rely on.
 | 
			
		||||
//
 | 
			
		||||
// Changes since v1alpha2:
 | 
			
		||||
//   - Added support for outputting certificate expiration information for "kubeadm certs check-expiration"
 | 
			
		||||
//     with the CertificateExpirationInfo structure.
 | 
			
		||||
package v1alpha3 // import "k8s.io/kubernetes/cmd/kubeadm/app/apis/output/v1alpha3"
 | 
			
		||||
							
								
								
									
										55
									
								
								cmd/kubeadm/app/apis/output/v1alpha3/register.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								cmd/kubeadm/app/apis/output/v1alpha3/register.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,55 @@
 | 
			
		||||
/*
 | 
			
		||||
Copyright 2024 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 v1alpha3
 | 
			
		||||
 | 
			
		||||
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 = "output.kubeadm.k8s.io"
 | 
			
		||||
 | 
			
		||||
// SchemeGroupVersion is group version used to register these objects
 | 
			
		||||
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha3"}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// SchemeBuilder points to a list of functions added to Scheme.
 | 
			
		||||
	SchemeBuilder      runtime.SchemeBuilder
 | 
			
		||||
	localSchemeBuilder = &SchemeBuilder
 | 
			
		||||
	// AddToScheme applies all the stored functions to the scheme.
 | 
			
		||||
	AddToScheme = localSchemeBuilder.AddToScheme
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	// We only register manually written functions here. The registration of the
 | 
			
		||||
	// generated functions takes place in the generated files. The separation
 | 
			
		||||
	// makes the code compile even when the generated files are missing.
 | 
			
		||||
	localSchemeBuilder.Register(addKnownTypes)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func addKnownTypes(scheme *runtime.Scheme) error {
 | 
			
		||||
	scheme.AddKnownTypes(SchemeGroupVersion,
 | 
			
		||||
		&BootstrapToken{},
 | 
			
		||||
		&Images{},
 | 
			
		||||
		&UpgradePlan{},
 | 
			
		||||
		&CertificateExpirationInfo{},
 | 
			
		||||
	)
 | 
			
		||||
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										119
									
								
								cmd/kubeadm/app/apis/output/v1alpha3/types.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								cmd/kubeadm/app/apis/output/v1alpha3/types.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,119 @@
 | 
			
		||||
/*
 | 
			
		||||
Copyright 2024 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 v1alpha3
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
			
		||||
 | 
			
		||||
	bootstraptokenv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/bootstraptoken/v1"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 | 
			
		||||
 | 
			
		||||
// BootstrapToken represents information for the bootstrap token output produced by kubeadm
 | 
			
		||||
type BootstrapToken struct {
 | 
			
		||||
	metav1.TypeMeta `json:",inline"`
 | 
			
		||||
 | 
			
		||||
	bootstraptokenv1.BootstrapToken
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 | 
			
		||||
 | 
			
		||||
// Images represents information for the output produced by 'kubeadm config images list'
 | 
			
		||||
type Images struct {
 | 
			
		||||
	metav1.TypeMeta `json:",inline"`
 | 
			
		||||
 | 
			
		||||
	Images []string `json:"images"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 | 
			
		||||
 | 
			
		||||
// ComponentUpgradePlan represents information about upgrade plan for one component
 | 
			
		||||
type ComponentUpgradePlan struct {
 | 
			
		||||
	metav1.TypeMeta
 | 
			
		||||
 | 
			
		||||
	Name           string `json:"name"`
 | 
			
		||||
	CurrentVersion string `json:"currentVersion"`
 | 
			
		||||
	NewVersion     string `json:"newVersion"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ComponentConfigVersionState describes the current and desired version of a component config
 | 
			
		||||
type ComponentConfigVersionState struct {
 | 
			
		||||
	// Group points to the Kubernetes API group that covers the config
 | 
			
		||||
	Group string `json:"group"`
 | 
			
		||||
 | 
			
		||||
	// CurrentVersion is the currently active component config version
 | 
			
		||||
	// NOTE: This can be empty in case the config was not found on the cluster or it was unsupported
 | 
			
		||||
	// kubeadm generated version
 | 
			
		||||
	CurrentVersion string `json:"currentVersion"`
 | 
			
		||||
 | 
			
		||||
	// PreferredVersion is the component config version that is currently preferred by kubeadm for use.
 | 
			
		||||
	// NOTE: As of today, this is the only version supported by kubeadm.
 | 
			
		||||
	PreferredVersion string `json:"preferredVersion"`
 | 
			
		||||
 | 
			
		||||
	// ManualUpgradeRequired indicates if users need to manually upgrade their component config versions. This happens if
 | 
			
		||||
	// the CurrentVersion of the config is user supplied (or modified) and no longer supported. Users should upgrade
 | 
			
		||||
	// their component configs to PreferredVersion or any other supported component config version.
 | 
			
		||||
	ManualUpgradeRequired bool `json:"manualUpgradeRequired"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 | 
			
		||||
 | 
			
		||||
// UpgradePlan represents information about upgrade plan for the output
 | 
			
		||||
// produced by 'kubeadm upgrade plan'
 | 
			
		||||
type UpgradePlan struct {
 | 
			
		||||
	metav1.TypeMeta
 | 
			
		||||
 | 
			
		||||
	Components []ComponentUpgradePlan `json:"components"`
 | 
			
		||||
 | 
			
		||||
	ConfigVersions []ComponentConfigVersionState `json:"configVersions"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Certificate represents information for a certificate or a certificate authority when using the check-expiration command.
 | 
			
		||||
type Certificate struct {
 | 
			
		||||
	// Name of the certificate.
 | 
			
		||||
	Name string `json:"name"`
 | 
			
		||||
 | 
			
		||||
	// ExpirationDate defines certificate expiration date in UTC following the RFC3339 format.
 | 
			
		||||
	ExpirationDate metav1.Time `json:"expirationDate"`
 | 
			
		||||
 | 
			
		||||
	// ResidualTimeSeconds represents the duration in seconds relative to the residual time before expiration.
 | 
			
		||||
	ResidualTimeSeconds int64 `json:"residualTime"`
 | 
			
		||||
 | 
			
		||||
	// ExternallyManaged defines if the certificate is externally managed.
 | 
			
		||||
	ExternallyManaged bool `json:"externallyManaged"`
 | 
			
		||||
 | 
			
		||||
	// CAName represents the name of the CA that signed the certificate.
 | 
			
		||||
	// This field is empty for self-signed, root CA certificates.
 | 
			
		||||
	CAName string `json:"caName,omitempty"`
 | 
			
		||||
 | 
			
		||||
	// Missing represents if the certificate is missing.
 | 
			
		||||
	Missing bool `json:"missing"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 | 
			
		||||
 | 
			
		||||
// CertificateExpirationInfo represents information for the output produced by 'kubeadm certs check-expiration'.
 | 
			
		||||
type CertificateExpirationInfo struct {
 | 
			
		||||
	metav1.TypeMeta
 | 
			
		||||
 | 
			
		||||
	// Certificates holds a list of certificates to show expiration information for.
 | 
			
		||||
	Certificates []Certificate `json:"certificates"`
 | 
			
		||||
 | 
			
		||||
	// CertificateAuthorities holds a list of certificate authorities to show expiration information for.
 | 
			
		||||
	CertificateAuthorities []Certificate `json:"certificateAuthorities"`
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										274
									
								
								cmd/kubeadm/app/apis/output/v1alpha3/zz_generated.conversion.go
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										274
									
								
								cmd/kubeadm/app/apis/output/v1alpha3/zz_generated.conversion.go
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,274 @@
 | 
			
		||||
//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 v1alpha3
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	unsafe "unsafe"
 | 
			
		||||
 | 
			
		||||
	conversion "k8s.io/apimachinery/pkg/conversion"
 | 
			
		||||
	runtime "k8s.io/apimachinery/pkg/runtime"
 | 
			
		||||
	output "k8s.io/kubernetes/cmd/kubeadm/app/apis/output"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
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((*BootstrapToken)(nil), (*output.BootstrapToken)(nil), func(a, b interface{}, scope conversion.Scope) error {
 | 
			
		||||
		return Convert_v1alpha3_BootstrapToken_To_output_BootstrapToken(a.(*BootstrapToken), b.(*output.BootstrapToken), scope)
 | 
			
		||||
	}); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if err := s.AddGeneratedConversionFunc((*output.BootstrapToken)(nil), (*BootstrapToken)(nil), func(a, b interface{}, scope conversion.Scope) error {
 | 
			
		||||
		return Convert_output_BootstrapToken_To_v1alpha3_BootstrapToken(a.(*output.BootstrapToken), b.(*BootstrapToken), scope)
 | 
			
		||||
	}); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if err := s.AddGeneratedConversionFunc((*Certificate)(nil), (*output.Certificate)(nil), func(a, b interface{}, scope conversion.Scope) error {
 | 
			
		||||
		return Convert_v1alpha3_Certificate_To_output_Certificate(a.(*Certificate), b.(*output.Certificate), scope)
 | 
			
		||||
	}); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if err := s.AddGeneratedConversionFunc((*output.Certificate)(nil), (*Certificate)(nil), func(a, b interface{}, scope conversion.Scope) error {
 | 
			
		||||
		return Convert_output_Certificate_To_v1alpha3_Certificate(a.(*output.Certificate), b.(*Certificate), scope)
 | 
			
		||||
	}); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if err := s.AddGeneratedConversionFunc((*CertificateExpirationInfo)(nil), (*output.CertificateExpirationInfo)(nil), func(a, b interface{}, scope conversion.Scope) error {
 | 
			
		||||
		return Convert_v1alpha3_CertificateExpirationInfo_To_output_CertificateExpirationInfo(a.(*CertificateExpirationInfo), b.(*output.CertificateExpirationInfo), scope)
 | 
			
		||||
	}); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if err := s.AddGeneratedConversionFunc((*output.CertificateExpirationInfo)(nil), (*CertificateExpirationInfo)(nil), func(a, b interface{}, scope conversion.Scope) error {
 | 
			
		||||
		return Convert_output_CertificateExpirationInfo_To_v1alpha3_CertificateExpirationInfo(a.(*output.CertificateExpirationInfo), b.(*CertificateExpirationInfo), scope)
 | 
			
		||||
	}); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if err := s.AddGeneratedConversionFunc((*ComponentConfigVersionState)(nil), (*output.ComponentConfigVersionState)(nil), func(a, b interface{}, scope conversion.Scope) error {
 | 
			
		||||
		return Convert_v1alpha3_ComponentConfigVersionState_To_output_ComponentConfigVersionState(a.(*ComponentConfigVersionState), b.(*output.ComponentConfigVersionState), scope)
 | 
			
		||||
	}); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if err := s.AddGeneratedConversionFunc((*output.ComponentConfigVersionState)(nil), (*ComponentConfigVersionState)(nil), func(a, b interface{}, scope conversion.Scope) error {
 | 
			
		||||
		return Convert_output_ComponentConfigVersionState_To_v1alpha3_ComponentConfigVersionState(a.(*output.ComponentConfigVersionState), b.(*ComponentConfigVersionState), scope)
 | 
			
		||||
	}); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if err := s.AddGeneratedConversionFunc((*ComponentUpgradePlan)(nil), (*output.ComponentUpgradePlan)(nil), func(a, b interface{}, scope conversion.Scope) error {
 | 
			
		||||
		return Convert_v1alpha3_ComponentUpgradePlan_To_output_ComponentUpgradePlan(a.(*ComponentUpgradePlan), b.(*output.ComponentUpgradePlan), scope)
 | 
			
		||||
	}); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if err := s.AddGeneratedConversionFunc((*output.ComponentUpgradePlan)(nil), (*ComponentUpgradePlan)(nil), func(a, b interface{}, scope conversion.Scope) error {
 | 
			
		||||
		return Convert_output_ComponentUpgradePlan_To_v1alpha3_ComponentUpgradePlan(a.(*output.ComponentUpgradePlan), b.(*ComponentUpgradePlan), scope)
 | 
			
		||||
	}); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if err := s.AddGeneratedConversionFunc((*Images)(nil), (*output.Images)(nil), func(a, b interface{}, scope conversion.Scope) error {
 | 
			
		||||
		return Convert_v1alpha3_Images_To_output_Images(a.(*Images), b.(*output.Images), scope)
 | 
			
		||||
	}); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if err := s.AddGeneratedConversionFunc((*output.Images)(nil), (*Images)(nil), func(a, b interface{}, scope conversion.Scope) error {
 | 
			
		||||
		return Convert_output_Images_To_v1alpha3_Images(a.(*output.Images), b.(*Images), scope)
 | 
			
		||||
	}); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if err := s.AddGeneratedConversionFunc((*UpgradePlan)(nil), (*output.UpgradePlan)(nil), func(a, b interface{}, scope conversion.Scope) error {
 | 
			
		||||
		return Convert_v1alpha3_UpgradePlan_To_output_UpgradePlan(a.(*UpgradePlan), b.(*output.UpgradePlan), scope)
 | 
			
		||||
	}); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if err := s.AddGeneratedConversionFunc((*output.UpgradePlan)(nil), (*UpgradePlan)(nil), func(a, b interface{}, scope conversion.Scope) error {
 | 
			
		||||
		return Convert_output_UpgradePlan_To_v1alpha3_UpgradePlan(a.(*output.UpgradePlan), b.(*UpgradePlan), scope)
 | 
			
		||||
	}); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func autoConvert_v1alpha3_BootstrapToken_To_output_BootstrapToken(in *BootstrapToken, out *output.BootstrapToken, s conversion.Scope) error {
 | 
			
		||||
	out.BootstrapToken = in.BootstrapToken
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Convert_v1alpha3_BootstrapToken_To_output_BootstrapToken is an autogenerated conversion function.
 | 
			
		||||
func Convert_v1alpha3_BootstrapToken_To_output_BootstrapToken(in *BootstrapToken, out *output.BootstrapToken, s conversion.Scope) error {
 | 
			
		||||
	return autoConvert_v1alpha3_BootstrapToken_To_output_BootstrapToken(in, out, s)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func autoConvert_output_BootstrapToken_To_v1alpha3_BootstrapToken(in *output.BootstrapToken, out *BootstrapToken, s conversion.Scope) error {
 | 
			
		||||
	out.BootstrapToken = in.BootstrapToken
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Convert_output_BootstrapToken_To_v1alpha3_BootstrapToken is an autogenerated conversion function.
 | 
			
		||||
func Convert_output_BootstrapToken_To_v1alpha3_BootstrapToken(in *output.BootstrapToken, out *BootstrapToken, s conversion.Scope) error {
 | 
			
		||||
	return autoConvert_output_BootstrapToken_To_v1alpha3_BootstrapToken(in, out, s)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func autoConvert_v1alpha3_Certificate_To_output_Certificate(in *Certificate, out *output.Certificate, s conversion.Scope) error {
 | 
			
		||||
	out.Name = in.Name
 | 
			
		||||
	out.ExpirationDate = in.ExpirationDate
 | 
			
		||||
	out.ResidualTimeSeconds = in.ResidualTimeSeconds
 | 
			
		||||
	out.ExternallyManaged = in.ExternallyManaged
 | 
			
		||||
	out.CAName = in.CAName
 | 
			
		||||
	out.Missing = in.Missing
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Convert_v1alpha3_Certificate_To_output_Certificate is an autogenerated conversion function.
 | 
			
		||||
func Convert_v1alpha3_Certificate_To_output_Certificate(in *Certificate, out *output.Certificate, s conversion.Scope) error {
 | 
			
		||||
	return autoConvert_v1alpha3_Certificate_To_output_Certificate(in, out, s)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func autoConvert_output_Certificate_To_v1alpha3_Certificate(in *output.Certificate, out *Certificate, s conversion.Scope) error {
 | 
			
		||||
	out.Name = in.Name
 | 
			
		||||
	out.ExpirationDate = in.ExpirationDate
 | 
			
		||||
	out.ResidualTimeSeconds = in.ResidualTimeSeconds
 | 
			
		||||
	out.ExternallyManaged = in.ExternallyManaged
 | 
			
		||||
	out.CAName = in.CAName
 | 
			
		||||
	out.Missing = in.Missing
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Convert_output_Certificate_To_v1alpha3_Certificate is an autogenerated conversion function.
 | 
			
		||||
func Convert_output_Certificate_To_v1alpha3_Certificate(in *output.Certificate, out *Certificate, s conversion.Scope) error {
 | 
			
		||||
	return autoConvert_output_Certificate_To_v1alpha3_Certificate(in, out, s)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func autoConvert_v1alpha3_CertificateExpirationInfo_To_output_CertificateExpirationInfo(in *CertificateExpirationInfo, out *output.CertificateExpirationInfo, s conversion.Scope) error {
 | 
			
		||||
	out.Certificates = *(*[]output.Certificate)(unsafe.Pointer(&in.Certificates))
 | 
			
		||||
	out.CertificateAuthorities = *(*[]output.Certificate)(unsafe.Pointer(&in.CertificateAuthorities))
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Convert_v1alpha3_CertificateExpirationInfo_To_output_CertificateExpirationInfo is an autogenerated conversion function.
 | 
			
		||||
func Convert_v1alpha3_CertificateExpirationInfo_To_output_CertificateExpirationInfo(in *CertificateExpirationInfo, out *output.CertificateExpirationInfo, s conversion.Scope) error {
 | 
			
		||||
	return autoConvert_v1alpha3_CertificateExpirationInfo_To_output_CertificateExpirationInfo(in, out, s)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func autoConvert_output_CertificateExpirationInfo_To_v1alpha3_CertificateExpirationInfo(in *output.CertificateExpirationInfo, out *CertificateExpirationInfo, s conversion.Scope) error {
 | 
			
		||||
	out.Certificates = *(*[]Certificate)(unsafe.Pointer(&in.Certificates))
 | 
			
		||||
	out.CertificateAuthorities = *(*[]Certificate)(unsafe.Pointer(&in.CertificateAuthorities))
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Convert_output_CertificateExpirationInfo_To_v1alpha3_CertificateExpirationInfo is an autogenerated conversion function.
 | 
			
		||||
func Convert_output_CertificateExpirationInfo_To_v1alpha3_CertificateExpirationInfo(in *output.CertificateExpirationInfo, out *CertificateExpirationInfo, s conversion.Scope) error {
 | 
			
		||||
	return autoConvert_output_CertificateExpirationInfo_To_v1alpha3_CertificateExpirationInfo(in, out, s)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func autoConvert_v1alpha3_ComponentConfigVersionState_To_output_ComponentConfigVersionState(in *ComponentConfigVersionState, out *output.ComponentConfigVersionState, s conversion.Scope) error {
 | 
			
		||||
	out.Group = in.Group
 | 
			
		||||
	out.CurrentVersion = in.CurrentVersion
 | 
			
		||||
	out.PreferredVersion = in.PreferredVersion
 | 
			
		||||
	out.ManualUpgradeRequired = in.ManualUpgradeRequired
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Convert_v1alpha3_ComponentConfigVersionState_To_output_ComponentConfigVersionState is an autogenerated conversion function.
 | 
			
		||||
func Convert_v1alpha3_ComponentConfigVersionState_To_output_ComponentConfigVersionState(in *ComponentConfigVersionState, out *output.ComponentConfigVersionState, s conversion.Scope) error {
 | 
			
		||||
	return autoConvert_v1alpha3_ComponentConfigVersionState_To_output_ComponentConfigVersionState(in, out, s)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func autoConvert_output_ComponentConfigVersionState_To_v1alpha3_ComponentConfigVersionState(in *output.ComponentConfigVersionState, out *ComponentConfigVersionState, s conversion.Scope) error {
 | 
			
		||||
	out.Group = in.Group
 | 
			
		||||
	out.CurrentVersion = in.CurrentVersion
 | 
			
		||||
	out.PreferredVersion = in.PreferredVersion
 | 
			
		||||
	out.ManualUpgradeRequired = in.ManualUpgradeRequired
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Convert_output_ComponentConfigVersionState_To_v1alpha3_ComponentConfigVersionState is an autogenerated conversion function.
 | 
			
		||||
func Convert_output_ComponentConfigVersionState_To_v1alpha3_ComponentConfigVersionState(in *output.ComponentConfigVersionState, out *ComponentConfigVersionState, s conversion.Scope) error {
 | 
			
		||||
	return autoConvert_output_ComponentConfigVersionState_To_v1alpha3_ComponentConfigVersionState(in, out, s)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func autoConvert_v1alpha3_ComponentUpgradePlan_To_output_ComponentUpgradePlan(in *ComponentUpgradePlan, out *output.ComponentUpgradePlan, s conversion.Scope) error {
 | 
			
		||||
	out.Name = in.Name
 | 
			
		||||
	out.CurrentVersion = in.CurrentVersion
 | 
			
		||||
	out.NewVersion = in.NewVersion
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Convert_v1alpha3_ComponentUpgradePlan_To_output_ComponentUpgradePlan is an autogenerated conversion function.
 | 
			
		||||
func Convert_v1alpha3_ComponentUpgradePlan_To_output_ComponentUpgradePlan(in *ComponentUpgradePlan, out *output.ComponentUpgradePlan, s conversion.Scope) error {
 | 
			
		||||
	return autoConvert_v1alpha3_ComponentUpgradePlan_To_output_ComponentUpgradePlan(in, out, s)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func autoConvert_output_ComponentUpgradePlan_To_v1alpha3_ComponentUpgradePlan(in *output.ComponentUpgradePlan, out *ComponentUpgradePlan, s conversion.Scope) error {
 | 
			
		||||
	out.Name = in.Name
 | 
			
		||||
	out.CurrentVersion = in.CurrentVersion
 | 
			
		||||
	out.NewVersion = in.NewVersion
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Convert_output_ComponentUpgradePlan_To_v1alpha3_ComponentUpgradePlan is an autogenerated conversion function.
 | 
			
		||||
func Convert_output_ComponentUpgradePlan_To_v1alpha3_ComponentUpgradePlan(in *output.ComponentUpgradePlan, out *ComponentUpgradePlan, s conversion.Scope) error {
 | 
			
		||||
	return autoConvert_output_ComponentUpgradePlan_To_v1alpha3_ComponentUpgradePlan(in, out, s)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func autoConvert_v1alpha3_Images_To_output_Images(in *Images, out *output.Images, s conversion.Scope) error {
 | 
			
		||||
	out.Images = *(*[]string)(unsafe.Pointer(&in.Images))
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Convert_v1alpha3_Images_To_output_Images is an autogenerated conversion function.
 | 
			
		||||
func Convert_v1alpha3_Images_To_output_Images(in *Images, out *output.Images, s conversion.Scope) error {
 | 
			
		||||
	return autoConvert_v1alpha3_Images_To_output_Images(in, out, s)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func autoConvert_output_Images_To_v1alpha3_Images(in *output.Images, out *Images, s conversion.Scope) error {
 | 
			
		||||
	out.Images = *(*[]string)(unsafe.Pointer(&in.Images))
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Convert_output_Images_To_v1alpha3_Images is an autogenerated conversion function.
 | 
			
		||||
func Convert_output_Images_To_v1alpha3_Images(in *output.Images, out *Images, s conversion.Scope) error {
 | 
			
		||||
	return autoConvert_output_Images_To_v1alpha3_Images(in, out, s)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func autoConvert_v1alpha3_UpgradePlan_To_output_UpgradePlan(in *UpgradePlan, out *output.UpgradePlan, s conversion.Scope) error {
 | 
			
		||||
	out.Components = *(*[]output.ComponentUpgradePlan)(unsafe.Pointer(&in.Components))
 | 
			
		||||
	out.ConfigVersions = *(*[]output.ComponentConfigVersionState)(unsafe.Pointer(&in.ConfigVersions))
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Convert_v1alpha3_UpgradePlan_To_output_UpgradePlan is an autogenerated conversion function.
 | 
			
		||||
func Convert_v1alpha3_UpgradePlan_To_output_UpgradePlan(in *UpgradePlan, out *output.UpgradePlan, s conversion.Scope) error {
 | 
			
		||||
	return autoConvert_v1alpha3_UpgradePlan_To_output_UpgradePlan(in, out, s)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func autoConvert_output_UpgradePlan_To_v1alpha3_UpgradePlan(in *output.UpgradePlan, out *UpgradePlan, s conversion.Scope) error {
 | 
			
		||||
	out.Components = *(*[]ComponentUpgradePlan)(unsafe.Pointer(&in.Components))
 | 
			
		||||
	out.ConfigVersions = *(*[]ComponentConfigVersionState)(unsafe.Pointer(&in.ConfigVersions))
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Convert_output_UpgradePlan_To_v1alpha3_UpgradePlan is an autogenerated conversion function.
 | 
			
		||||
func Convert_output_UpgradePlan_To_v1alpha3_UpgradePlan(in *output.UpgradePlan, out *UpgradePlan, s conversion.Scope) error {
 | 
			
		||||
	return autoConvert_output_UpgradePlan_To_v1alpha3_UpgradePlan(in, out, s)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										214
									
								
								cmd/kubeadm/app/apis/output/v1alpha3/zz_generated.deepcopy.go
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										214
									
								
								cmd/kubeadm/app/apis/output/v1alpha3/zz_generated.deepcopy.go
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,214 @@
 | 
			
		||||
//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 v1alpha3
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	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 *BootstrapToken) DeepCopyInto(out *BootstrapToken) {
 | 
			
		||||
	*out = *in
 | 
			
		||||
	out.TypeMeta = in.TypeMeta
 | 
			
		||||
	in.BootstrapToken.DeepCopyInto(&out.BootstrapToken)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BootstrapToken.
 | 
			
		||||
func (in *BootstrapToken) DeepCopy() *BootstrapToken {
 | 
			
		||||
	if in == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	out := new(BootstrapToken)
 | 
			
		||||
	in.DeepCopyInto(out)
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
 | 
			
		||||
func (in *BootstrapToken) 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 *Certificate) DeepCopyInto(out *Certificate) {
 | 
			
		||||
	*out = *in
 | 
			
		||||
	in.ExpirationDate.DeepCopyInto(&out.ExpirationDate)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Certificate.
 | 
			
		||||
func (in *Certificate) DeepCopy() *Certificate {
 | 
			
		||||
	if in == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	out := new(Certificate)
 | 
			
		||||
	in.DeepCopyInto(out)
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
			
		||||
func (in *CertificateExpirationInfo) DeepCopyInto(out *CertificateExpirationInfo) {
 | 
			
		||||
	*out = *in
 | 
			
		||||
	out.TypeMeta = in.TypeMeta
 | 
			
		||||
	if in.Certificates != nil {
 | 
			
		||||
		in, out := &in.Certificates, &out.Certificates
 | 
			
		||||
		*out = make([]Certificate, len(*in))
 | 
			
		||||
		for i := range *in {
 | 
			
		||||
			(*in)[i].DeepCopyInto(&(*out)[i])
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if in.CertificateAuthorities != nil {
 | 
			
		||||
		in, out := &in.CertificateAuthorities, &out.CertificateAuthorities
 | 
			
		||||
		*out = make([]Certificate, len(*in))
 | 
			
		||||
		for i := range *in {
 | 
			
		||||
			(*in)[i].DeepCopyInto(&(*out)[i])
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CertificateExpirationInfo.
 | 
			
		||||
func (in *CertificateExpirationInfo) DeepCopy() *CertificateExpirationInfo {
 | 
			
		||||
	if in == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	out := new(CertificateExpirationInfo)
 | 
			
		||||
	in.DeepCopyInto(out)
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
 | 
			
		||||
func (in *CertificateExpirationInfo) 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 *ComponentConfigVersionState) DeepCopyInto(out *ComponentConfigVersionState) {
 | 
			
		||||
	*out = *in
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentConfigVersionState.
 | 
			
		||||
func (in *ComponentConfigVersionState) DeepCopy() *ComponentConfigVersionState {
 | 
			
		||||
	if in == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	out := new(ComponentConfigVersionState)
 | 
			
		||||
	in.DeepCopyInto(out)
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
			
		||||
func (in *ComponentUpgradePlan) DeepCopyInto(out *ComponentUpgradePlan) {
 | 
			
		||||
	*out = *in
 | 
			
		||||
	out.TypeMeta = in.TypeMeta
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentUpgradePlan.
 | 
			
		||||
func (in *ComponentUpgradePlan) DeepCopy() *ComponentUpgradePlan {
 | 
			
		||||
	if in == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	out := new(ComponentUpgradePlan)
 | 
			
		||||
	in.DeepCopyInto(out)
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
 | 
			
		||||
func (in *ComponentUpgradePlan) 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 *Images) DeepCopyInto(out *Images) {
 | 
			
		||||
	*out = *in
 | 
			
		||||
	out.TypeMeta = in.TypeMeta
 | 
			
		||||
	if in.Images != nil {
 | 
			
		||||
		in, out := &in.Images, &out.Images
 | 
			
		||||
		*out = make([]string, len(*in))
 | 
			
		||||
		copy(*out, *in)
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Images.
 | 
			
		||||
func (in *Images) DeepCopy() *Images {
 | 
			
		||||
	if in == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	out := new(Images)
 | 
			
		||||
	in.DeepCopyInto(out)
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
 | 
			
		||||
func (in *Images) 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 *UpgradePlan) DeepCopyInto(out *UpgradePlan) {
 | 
			
		||||
	*out = *in
 | 
			
		||||
	out.TypeMeta = in.TypeMeta
 | 
			
		||||
	if in.Components != nil {
 | 
			
		||||
		in, out := &in.Components, &out.Components
 | 
			
		||||
		*out = make([]ComponentUpgradePlan, len(*in))
 | 
			
		||||
		copy(*out, *in)
 | 
			
		||||
	}
 | 
			
		||||
	if in.ConfigVersions != nil {
 | 
			
		||||
		in, out := &in.ConfigVersions, &out.ConfigVersions
 | 
			
		||||
		*out = make([]ComponentConfigVersionState, len(*in))
 | 
			
		||||
		copy(*out, *in)
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpgradePlan.
 | 
			
		||||
func (in *UpgradePlan) DeepCopy() *UpgradePlan {
 | 
			
		||||
	if in == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	out := new(UpgradePlan)
 | 
			
		||||
	in.DeepCopyInto(out)
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
 | 
			
		||||
func (in *UpgradePlan) DeepCopyObject() runtime.Object {
 | 
			
		||||
	if c := in.DeepCopy(); c != nil {
 | 
			
		||||
		return c
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										56
									
								
								cmd/kubeadm/app/apis/output/zz_generated.deepcopy.go
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										56
									
								
								cmd/kubeadm/app/apis/output/zz_generated.deepcopy.go
									
									
									
										generated
									
									
									
								
							@@ -51,6 +51,62 @@ func (in *BootstrapToken) DeepCopyObject() runtime.Object {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
			
		||||
func (in *Certificate) DeepCopyInto(out *Certificate) {
 | 
			
		||||
	*out = *in
 | 
			
		||||
	in.ExpirationDate.DeepCopyInto(&out.ExpirationDate)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Certificate.
 | 
			
		||||
func (in *Certificate) DeepCopy() *Certificate {
 | 
			
		||||
	if in == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	out := new(Certificate)
 | 
			
		||||
	in.DeepCopyInto(out)
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
			
		||||
func (in *CertificateExpirationInfo) DeepCopyInto(out *CertificateExpirationInfo) {
 | 
			
		||||
	*out = *in
 | 
			
		||||
	out.TypeMeta = in.TypeMeta
 | 
			
		||||
	if in.Certificates != nil {
 | 
			
		||||
		in, out := &in.Certificates, &out.Certificates
 | 
			
		||||
		*out = make([]Certificate, len(*in))
 | 
			
		||||
		for i := range *in {
 | 
			
		||||
			(*in)[i].DeepCopyInto(&(*out)[i])
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if in.CertificateAuthorities != nil {
 | 
			
		||||
		in, out := &in.CertificateAuthorities, &out.CertificateAuthorities
 | 
			
		||||
		*out = make([]Certificate, len(*in))
 | 
			
		||||
		for i := range *in {
 | 
			
		||||
			(*in)[i].DeepCopyInto(&(*out)[i])
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CertificateExpirationInfo.
 | 
			
		||||
func (in *CertificateExpirationInfo) DeepCopy() *CertificateExpirationInfo {
 | 
			
		||||
	if in == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	out := new(CertificateExpirationInfo)
 | 
			
		||||
	in.DeepCopyInto(out)
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
 | 
			
		||||
func (in *CertificateExpirationInfo) 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 *ComponentConfigVersionState) DeepCopyInto(out *ComponentConfigVersionState) {
 | 
			
		||||
	*out = *in
 | 
			
		||||
 
 | 
			
		||||
@@ -20,17 +20,25 @@ import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"text/tabwriter"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/lithammer/dedent"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
	"github.com/spf13/pflag"
 | 
			
		||||
 | 
			
		||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/runtime"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/util/duration"
 | 
			
		||||
	"k8s.io/cli-runtime/pkg/genericclioptions"
 | 
			
		||||
	"k8s.io/client-go/kubernetes"
 | 
			
		||||
	"k8s.io/klog/v2"
 | 
			
		||||
 | 
			
		||||
	kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
 | 
			
		||||
	kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
 | 
			
		||||
	kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
 | 
			
		||||
	outputapischeme "k8s.io/kubernetes/cmd/kubeadm/app/apis/output/scheme"
 | 
			
		||||
	outputapiv1alpha3 "k8s.io/kubernetes/cmd/kubeadm/app/apis/output/v1alpha3"
 | 
			
		||||
	"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
 | 
			
		||||
	cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
 | 
			
		||||
	kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
 | 
			
		||||
@@ -40,6 +48,7 @@ import (
 | 
			
		||||
	kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
 | 
			
		||||
	configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
 | 
			
		||||
	kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
 | 
			
		||||
	"k8s.io/kubernetes/cmd/kubeadm/app/util/output"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
@@ -252,7 +261,8 @@ func getRenewSubCommands(out io.Writer, kdir string) []*cobra.Command {
 | 
			
		||||
		renewalFunc := func(handler *renewal.CertificateRenewHandler) func() error {
 | 
			
		||||
			return func() error {
 | 
			
		||||
				// Get cluster configuration (from --config, kubeadm-config ConfigMap, or default as a fallback)
 | 
			
		||||
				internalcfg, err := getInternalCfg(flags.cfgPath, flags.kubeconfigPath, flags.cfg, out, "renew")
 | 
			
		||||
				client, _ := kubeconfigutil.ClientSetFromFile(flags.kubeconfigPath)
 | 
			
		||||
				internalcfg, err := getInternalCfg(flags.cfgPath, client, flags.cfg, &output.TextPrinter{}, "renew")
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
@@ -272,7 +282,8 @@ func getRenewSubCommands(out io.Writer, kdir string) []*cobra.Command {
 | 
			
		||||
		Long:  allLongDesc,
 | 
			
		||||
		RunE: func(*cobra.Command, []string) error {
 | 
			
		||||
			// Get cluster configuration (from --config, kubeadm-config ConfigMap, or default as a fallback)
 | 
			
		||||
			internalcfg, err := getInternalCfg(flags.cfgPath, flags.kubeconfigPath, flags.cfg, out, "renew")
 | 
			
		||||
			client, _ := kubeconfigutil.ClientSetFromFile(flags.kubeconfigPath)
 | 
			
		||||
			internalcfg, err := getInternalCfg(flags.cfgPath, client, flags.cfg, &output.TextPrinter{}, "renew")
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
@@ -332,27 +343,24 @@ func renewCert(kdir string, internalcfg *kubeadmapi.InitConfiguration, handler *
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getInternalCfg(cfgPath string, kubeconfigPath string, cfg kubeadmapiv1.ClusterConfiguration, out io.Writer, logPrefix string) (*kubeadmapi.InitConfiguration, error) {
 | 
			
		||||
func getInternalCfg(cfgPath string, client kubernetes.Interface, cfg kubeadmapiv1.ClusterConfiguration, printer output.Printer, logPrefix string) (*kubeadmapi.InitConfiguration, error) {
 | 
			
		||||
	// In case the user is not providing a custom config, try to get current config from the cluster.
 | 
			
		||||
	// NB. this operation should not block, because we want to allow certificate renewal also in case of not-working clusters
 | 
			
		||||
	if cfgPath == "" {
 | 
			
		||||
		client, err := kubeconfigutil.ClientSetFromFile(kubeconfigPath)
 | 
			
		||||
	if cfgPath == "" && client != nil {
 | 
			
		||||
		internalcfg, err := configutil.FetchInitConfigurationFromCluster(client, printer, logPrefix, false, false)
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			internalcfg, err := configutil.FetchInitConfigurationFromCluster(client, nil, logPrefix, false, false)
 | 
			
		||||
			if err == nil {
 | 
			
		||||
				fmt.Println() // add empty line to separate the FetchInitConfigurationFromCluster output from the command output
 | 
			
		||||
				// certificate renewal or expiration checking doesn't depend on a running cluster, which means the CertificatesDir
 | 
			
		||||
				// could be set to a value other than the default value or the value fetched from the cluster.
 | 
			
		||||
				// cfg.CertificatesDir could be empty if the default value is set to empty (not true today).
 | 
			
		||||
				if len(cfg.CertificatesDir) != 0 {
 | 
			
		||||
					klog.V(1).Infof("Overriding the cluster certificate directory with the value from command line flag --%s: %s", options.CertificatesDir, cfg.CertificatesDir)
 | 
			
		||||
					internalcfg.ClusterConfiguration.CertificatesDir = cfg.CertificatesDir
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				return internalcfg, nil
 | 
			
		||||
			printer.Println() // add empty line to separate the FetchInitConfigurationFromCluster output from the command output
 | 
			
		||||
			// certificate renewal or expiration checking doesn't depend on a running cluster, which means the CertificatesDir
 | 
			
		||||
			// could be set to a value other than the default value or the value fetched from the cluster.
 | 
			
		||||
			// cfg.CertificatesDir could be empty if the default value is set to empty (not true today).
 | 
			
		||||
			if len(cfg.CertificatesDir) != 0 {
 | 
			
		||||
				klog.V(1).Infof("Overriding the cluster certificate directory with the value from command line flag --%s: %s", options.CertificatesDir, cfg.CertificatesDir)
 | 
			
		||||
				internalcfg.ClusterConfiguration.CertificatesDir = cfg.CertificatesDir
 | 
			
		||||
			}
 | 
			
		||||
			fmt.Printf("[%s] Error reading configuration from the Cluster. Falling back to default configuration\n\n", logPrefix)
 | 
			
		||||
 | 
			
		||||
			return internalcfg, nil
 | 
			
		||||
		}
 | 
			
		||||
		printer.Printf("[%s] Error reading configuration from the Cluster. Falling back to default configuration\n\n", logPrefix)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Read config from --config if provided. Otherwise, use the default configuration
 | 
			
		||||
@@ -361,6 +369,60 @@ func getInternalCfg(cfgPath string, kubeconfigPath string, cfg kubeadmapiv1.Clus
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// fetchCertificateExpirationInfo returns the certificate expiration info for the given renewal manager
 | 
			
		||||
func fetchCertificateExpirationInfo(rm *renewal.Manager) (*outputapiv1alpha3.CertificateExpirationInfo, error) {
 | 
			
		||||
	info := &outputapiv1alpha3.CertificateExpirationInfo{}
 | 
			
		||||
 | 
			
		||||
	for _, handler := range rm.Certificates() {
 | 
			
		||||
		if ok, _ := rm.CertificateExists(handler.Name); ok {
 | 
			
		||||
			e, err := rm.GetCertificateExpirationInfo(handler.Name)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			info.Certificates = append(info.Certificates, outputapiv1alpha3.Certificate{
 | 
			
		||||
				Name:                e.Name,
 | 
			
		||||
				ExpirationDate:      metav1.Time{Time: e.ExpirationDate},
 | 
			
		||||
				ResidualTimeSeconds: int64(e.ResidualTime() / time.Second),
 | 
			
		||||
				CAName:              handler.CAName,
 | 
			
		||||
				ExternallyManaged:   e.ExternallyManaged,
 | 
			
		||||
			})
 | 
			
		||||
		} else {
 | 
			
		||||
			// the certificate does not exist (for any reason)
 | 
			
		||||
			info.Certificates = append(info.Certificates, outputapiv1alpha3.Certificate{
 | 
			
		||||
				Name:    handler.Name,
 | 
			
		||||
				Missing: true,
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, handler := range rm.CAs() {
 | 
			
		||||
		if ok, _ := rm.CAExists(handler.Name); ok {
 | 
			
		||||
			e, err := rm.GetCAExpirationInfo(handler.Name)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			info.CertificateAuthorities = append(info.CertificateAuthorities, outputapiv1alpha3.Certificate{
 | 
			
		||||
				Name:                e.Name,
 | 
			
		||||
				ExpirationDate:      metav1.Time{Time: e.ExpirationDate},
 | 
			
		||||
				ResidualTimeSeconds: int64(e.ResidualTime() / time.Second),
 | 
			
		||||
				ExternallyManaged:   e.ExternallyManaged,
 | 
			
		||||
			})
 | 
			
		||||
		} else {
 | 
			
		||||
			// the CA does not exist (for any reason)
 | 
			
		||||
			info.CertificateAuthorities = append(info.CertificateAuthorities, outputapiv1alpha3.Certificate{
 | 
			
		||||
				Name:    handler.Name,
 | 
			
		||||
				Missing: true,
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return info, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// clientSetFromFile is a variable that holds the function to create a clientset from a kubeconfig file.
 | 
			
		||||
// It is used for testing purposes.
 | 
			
		||||
var clientSetFromFile = kubeconfigutil.ClientSetFromFile
 | 
			
		||||
 | 
			
		||||
// newCmdCertsExpiration creates a new `cert check-expiration` command.
 | 
			
		||||
func newCmdCertsExpiration(out io.Writer, kdir string) *cobra.Command {
 | 
			
		||||
	flags := &expirationFlags{
 | 
			
		||||
@@ -373,13 +435,21 @@ func newCmdCertsExpiration(out io.Writer, kdir string) *cobra.Command {
 | 
			
		||||
	// Default values for the cobra help text
 | 
			
		||||
	kubeadmscheme.Scheme.Default(&flags.cfg)
 | 
			
		||||
 | 
			
		||||
	outputFlags := output.NewOutputFlags(&certTextPrintFlags{}).WithTypeSetter(outputapischeme.Scheme).WithDefaultOutput(output.TextOutput)
 | 
			
		||||
 | 
			
		||||
	cmd := &cobra.Command{
 | 
			
		||||
		Use:   "check-expiration",
 | 
			
		||||
		Short: "Check certificates expiration for a Kubernetes cluster",
 | 
			
		||||
		Long:  expirationLongDesc,
 | 
			
		||||
		RunE: func(cmd *cobra.Command, args []string) error {
 | 
			
		||||
			printer, err := outputFlags.ToPrinter()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return errors.Wrap(err, "could not construct output printer")
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Get cluster configuration (from --config, kubeadm-config ConfigMap, or default as a fallback)
 | 
			
		||||
			internalcfg, err := getInternalCfg(flags.cfgPath, flags.kubeconfigPath, flags.cfg, out, "check-expiration")
 | 
			
		||||
			client, _ := clientSetFromFile(flags.kubeconfigPath)
 | 
			
		||||
			internalcfg, err := getInternalCfg(flags.cfgPath, client, flags.cfg, printer, "check-expiration")
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
@@ -390,73 +460,16 @@ func newCmdCertsExpiration(out io.Writer, kdir string) *cobra.Command {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Get all the certificate expiration info
 | 
			
		||||
			yesNo := func(b bool) string {
 | 
			
		||||
				if b {
 | 
			
		||||
					return "yes"
 | 
			
		||||
				}
 | 
			
		||||
				return "no"
 | 
			
		||||
			info, err := fetchCertificateExpirationInfo(rm)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			w := tabwriter.NewWriter(out, 10, 4, 3, ' ', 0)
 | 
			
		||||
			fmt.Fprintln(w, "CERTIFICATE\tEXPIRES\tRESIDUAL TIME\tCERTIFICATE AUTHORITY\tEXTERNALLY MANAGED")
 | 
			
		||||
			for _, handler := range rm.Certificates() {
 | 
			
		||||
				if ok, _ := rm.CertificateExists(handler.Name); ok {
 | 
			
		||||
					e, err := rm.GetCertificateExpirationInfo(handler.Name)
 | 
			
		||||
					if err != nil {
 | 
			
		||||
						return err
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					s := fmt.Sprintf("%s\t%s\t%s\t%s\t%-8v",
 | 
			
		||||
						e.Name,
 | 
			
		||||
						e.ExpirationDate.Format("Jan 02, 2006 15:04 MST"),
 | 
			
		||||
						duration.ShortHumanDuration(e.ResidualTime()),
 | 
			
		||||
						handler.CAName,
 | 
			
		||||
						yesNo(e.ExternallyManaged),
 | 
			
		||||
					)
 | 
			
		||||
 | 
			
		||||
					fmt.Fprintln(w, s)
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				// the certificate does not exist (for any reason)
 | 
			
		||||
				s := fmt.Sprintf("!MISSING! %s\t\t\t\t",
 | 
			
		||||
					handler.Name,
 | 
			
		||||
				)
 | 
			
		||||
				fmt.Fprintln(w, s)
 | 
			
		||||
			}
 | 
			
		||||
			fmt.Fprintln(w)
 | 
			
		||||
			fmt.Fprintln(w, "CERTIFICATE AUTHORITY\tEXPIRES\tRESIDUAL TIME\tEXTERNALLY MANAGED")
 | 
			
		||||
			for _, handler := range rm.CAs() {
 | 
			
		||||
				if ok, _ := rm.CAExists(handler.Name); ok {
 | 
			
		||||
					e, err := rm.GetCAExpirationInfo(handler.Name)
 | 
			
		||||
					if err != nil {
 | 
			
		||||
						return err
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					s := fmt.Sprintf("%s\t%s\t%s\t%-8v",
 | 
			
		||||
						e.Name,
 | 
			
		||||
						e.ExpirationDate.Format("Jan 02, 2006 15:04 MST"),
 | 
			
		||||
						duration.ShortHumanDuration(e.ResidualTime()),
 | 
			
		||||
						yesNo(e.ExternallyManaged),
 | 
			
		||||
					)
 | 
			
		||||
 | 
			
		||||
					fmt.Fprintln(w, s)
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				// the CA does not exist (for any reason)
 | 
			
		||||
				s := fmt.Sprintf("!MISSING! %s\t\t\t",
 | 
			
		||||
					handler.Name,
 | 
			
		||||
				)
 | 
			
		||||
				fmt.Fprintln(w, s)
 | 
			
		||||
			}
 | 
			
		||||
			w.Flush()
 | 
			
		||||
			return nil
 | 
			
		||||
			return printer.PrintObj(info, out)
 | 
			
		||||
		},
 | 
			
		||||
		Args: cobra.NoArgs,
 | 
			
		||||
	}
 | 
			
		||||
	addExpirationFlags(cmd, flags)
 | 
			
		||||
 | 
			
		||||
	outputFlags.AddFlags(cmd)
 | 
			
		||||
	return cmd
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -471,3 +484,72 @@ func addExpirationFlags(cmd *cobra.Command, flags *expirationFlags) {
 | 
			
		||||
	options.AddCertificateDirFlag(cmd.Flags(), &flags.cfg.CertificatesDir)
 | 
			
		||||
	options.AddKubeConfigFlag(cmd.Flags(), &flags.kubeconfigPath)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// certsTextPrinter prints all certificates in a text form
 | 
			
		||||
type certTextPrinter struct {
 | 
			
		||||
	output.TextPrinter
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PrintObj is an implementation of ResourcePrinter.PrintObj for plain text output
 | 
			
		||||
func (p *certTextPrinter) PrintObj(obj runtime.Object, writer io.Writer) error {
 | 
			
		||||
	info, ok := obj.(*outputapiv1alpha3.CertificateExpirationInfo)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return errors.New("unexpected type")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	yesNo := func(b bool) string {
 | 
			
		||||
		if b {
 | 
			
		||||
			return "yes"
 | 
			
		||||
		}
 | 
			
		||||
		return "no"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tabw := tabwriter.NewWriter(writer, 10, 4, 3, ' ', 0)
 | 
			
		||||
	fmt.Fprintln(tabw, "CERTIFICATE\tEXPIRES\tRESIDUAL TIME\tCERTIFICATE AUTHORITY\tEXTERNALLY MANAGED")
 | 
			
		||||
	for _, cert := range info.Certificates {
 | 
			
		||||
		if cert.Missing {
 | 
			
		||||
			s := fmt.Sprintf("!MISSING! %s\t\t\t\t", cert.Name)
 | 
			
		||||
			fmt.Fprintln(tabw, s)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		s := fmt.Sprintf("%s\t%s\t%s\t%s\t%-8v",
 | 
			
		||||
			cert.Name,
 | 
			
		||||
			cert.ExpirationDate.Format("Jan 02, 2006 15:04 MST"),
 | 
			
		||||
			duration.ShortHumanDuration(time.Duration(cert.ResidualTimeSeconds)*time.Second),
 | 
			
		||||
			cert.CAName,
 | 
			
		||||
			yesNo(cert.ExternallyManaged),
 | 
			
		||||
		)
 | 
			
		||||
		fmt.Fprintln(tabw, s)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fmt.Fprintln(tabw)
 | 
			
		||||
	fmt.Fprintln(tabw, "CERTIFICATE AUTHORITY\tEXPIRES\tRESIDUAL TIME\tEXTERNALLY MANAGED")
 | 
			
		||||
	for _, ca := range info.CertificateAuthorities {
 | 
			
		||||
		if ca.Missing {
 | 
			
		||||
			s := fmt.Sprintf("!MISSING! %s\t\t\t", ca.Name)
 | 
			
		||||
			fmt.Fprintln(tabw, s)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		s := fmt.Sprintf("%s\t%s\t%s\t%-8v",
 | 
			
		||||
			ca.Name,
 | 
			
		||||
			ca.ExpirationDate.Format("Jan 02, 2006 15:04 MST"),
 | 
			
		||||
			duration.ShortHumanDuration(time.Duration(ca.ResidualTimeSeconds)*time.Second),
 | 
			
		||||
			yesNo(ca.ExternallyManaged),
 | 
			
		||||
		)
 | 
			
		||||
		fmt.Fprintln(tabw, s)
 | 
			
		||||
	}
 | 
			
		||||
	return tabw.Flush()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// certTextPrintFlags provides flags necessary for printing
 | 
			
		||||
type certTextPrintFlags struct{}
 | 
			
		||||
 | 
			
		||||
// ToPrinter returns a kubeadm printer for the text output format
 | 
			
		||||
func (tpf *certTextPrintFlags) ToPrinter(outputFormat string) (output.Printer, error) {
 | 
			
		||||
	if outputFormat == output.TextOutput {
 | 
			
		||||
		return &certTextPrinter{}, nil
 | 
			
		||||
	}
 | 
			
		||||
	return nil, genericclioptions.NoCompatiblePrinterError{OutputFormat: &outputFormat, AllowedFormats: []string{output.TextOutput}}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -20,8 +20,10 @@ limitations under the License.
 | 
			
		||||
package cmd
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"crypto"
 | 
			
		||||
	"crypto/x509"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
@@ -30,18 +32,27 @@ import (
 | 
			
		||||
	"testing"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/lithammer/dedent"
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
	"github.com/spf13/pflag"
 | 
			
		||||
	"github.com/stretchr/testify/assert"
 | 
			
		||||
	"github.com/stretchr/testify/require"
 | 
			
		||||
 | 
			
		||||
	v1 "k8s.io/api/core/v1"
 | 
			
		||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/runtime"
 | 
			
		||||
	"k8s.io/client-go/kubernetes"
 | 
			
		||||
	fakeclientset "k8s.io/client-go/kubernetes/fake"
 | 
			
		||||
	clientgotesting "k8s.io/client-go/testing"
 | 
			
		||||
	"k8s.io/client-go/tools/clientcmd"
 | 
			
		||||
 | 
			
		||||
	kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
 | 
			
		||||
	kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
 | 
			
		||||
	outputapiv1alpha3 "k8s.io/kubernetes/cmd/kubeadm/app/apis/output/v1alpha3"
 | 
			
		||||
	kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
 | 
			
		||||
	certsphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
 | 
			
		||||
	kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
 | 
			
		||||
	kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
 | 
			
		||||
	"k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil"
 | 
			
		||||
	testutil "k8s.io/kubernetes/cmd/kubeadm/test"
 | 
			
		||||
	cmdtestutil "k8s.io/kubernetes/cmd/kubeadm/test/cmd"
 | 
			
		||||
@@ -482,3 +493,223 @@ kubernetesVersion: %s`,
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestRunCmdCertsExpiration(t *testing.T) {
 | 
			
		||||
	kdir := testutil.SetupTempDir(t)
 | 
			
		||||
	defer func() {
 | 
			
		||||
		if err := os.RemoveAll(kdir); err != nil {
 | 
			
		||||
			t.Fatalf("Failed to teardown: %s", err)
 | 
			
		||||
		}
 | 
			
		||||
		clientSetFromFile = kubeconfigutil.ClientSetFromFile
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	cfg := testutil.GetDefaultInternalConfig(t)
 | 
			
		||||
	cfg.CertificatesDir = kdir
 | 
			
		||||
 | 
			
		||||
	// Generate all the CA
 | 
			
		||||
	caCerts := map[string]*x509.Certificate{}
 | 
			
		||||
	caKeys := map[string]crypto.Signer{}
 | 
			
		||||
	for _, ca := range []*certsphase.KubeadmCert{
 | 
			
		||||
		certsphase.KubeadmCertRootCA(),
 | 
			
		||||
		certsphase.KubeadmCertFrontProxyCA(),
 | 
			
		||||
		certsphase.KubeadmCertEtcdCA(),
 | 
			
		||||
	} {
 | 
			
		||||
		caCert, caKey, err := ca.CreateAsCA(cfg)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Fatalf("couldn't write out CA %s: %v", ca.Name, err)
 | 
			
		||||
		}
 | 
			
		||||
		caCerts[ca.Name] = caCert
 | 
			
		||||
		caKeys[ca.Name] = caKey
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Generate all the signed certificates
 | 
			
		||||
	kubeadmCerts := []*certsphase.KubeadmCert{
 | 
			
		||||
		certsphase.KubeadmCertAPIServer(),
 | 
			
		||||
		certsphase.KubeadmCertKubeletClient(),
 | 
			
		||||
		certsphase.KubeadmCertFrontProxyClient(),
 | 
			
		||||
		certsphase.KubeadmCertEtcdAPIClient(),
 | 
			
		||||
		certsphase.KubeadmCertEtcdServer(),
 | 
			
		||||
		certsphase.KubeadmCertEtcdPeer(),
 | 
			
		||||
		certsphase.KubeadmCertEtcdHealthcheck(),
 | 
			
		||||
	}
 | 
			
		||||
	for _, cert := range kubeadmCerts {
 | 
			
		||||
		caCert := caCerts[cert.CAName]
 | 
			
		||||
		caKey := caKeys[cert.CAName]
 | 
			
		||||
		if err := cert.CreateFromCA(cfg, caCert, caKey); err != nil {
 | 
			
		||||
			t.Fatalf("couldn't write certificate %s: %v", cert.Name, err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Generate all the kubeconfig files with embedded certs
 | 
			
		||||
	kubeConfigs := []string{
 | 
			
		||||
		kubeadmconstants.AdminKubeConfigFileName,
 | 
			
		||||
		kubeadmconstants.SuperAdminKubeConfigFileName,
 | 
			
		||||
		kubeadmconstants.SchedulerKubeConfigFileName,
 | 
			
		||||
		kubeadmconstants.ControllerManagerKubeConfigFileName,
 | 
			
		||||
	}
 | 
			
		||||
	for _, kubeConfig := range kubeConfigs {
 | 
			
		||||
		if err := kubeconfigphase.CreateKubeConfigFile(kubeConfig, kdir, cfg); err != nil {
 | 
			
		||||
			t.Fatalf("couldn't create kubeconfig %q: %v", kubeConfig, err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// A minimal kubeadm config with just enough values to avoid triggering
 | 
			
		||||
	// auto-detection of config values at runtime.
 | 
			
		||||
	var kubeadmConfig = fmt.Sprintf(`
 | 
			
		||||
apiVersion: %[1]s
 | 
			
		||||
kind: ClusterConfiguration
 | 
			
		||||
certificatesDir: %s
 | 
			
		||||
kubernetesVersion: %s`,
 | 
			
		||||
		kubeadmapiv1.SchemeGroupVersion.String(),
 | 
			
		||||
		cfg.CertificatesDir,
 | 
			
		||||
		kubeadmconstants.MinimumControlPlaneVersion.String())
 | 
			
		||||
 | 
			
		||||
	// Write the minimal kubeadm config to a file
 | 
			
		||||
	customConfigPath := kdir + "/kubeadm.conf"
 | 
			
		||||
	f, err := os.Create(customConfigPath)
 | 
			
		||||
	require.NoError(t, err)
 | 
			
		||||
	_, err = f.Write([]byte(kubeadmConfig))
 | 
			
		||||
	require.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
	// fakeClientSetFromFile returns a fake clientset with kubeadm config map
 | 
			
		||||
	var fakeClientSetFromFile = func(_ string) (kubernetes.Interface, error) {
 | 
			
		||||
		client := fakeclientset.NewSimpleClientset()
 | 
			
		||||
		client.PrependReactor("get", "configmaps", func(action clientgotesting.Action) (bool, runtime.Object, error) {
 | 
			
		||||
			getAction := action.(clientgotesting.GetAction)
 | 
			
		||||
			if getAction.GetNamespace() == metav1.NamespaceSystem && getAction.GetName() == kubeadmconstants.KubeadmConfigConfigMap {
 | 
			
		||||
				cm := &v1.ConfigMap{
 | 
			
		||||
					ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
						Name:      kubeadmconstants.KubeadmConfigConfigMap,
 | 
			
		||||
						Namespace: metav1.NamespaceSystem,
 | 
			
		||||
					},
 | 
			
		||||
					Data: map[string]string{
 | 
			
		||||
						kubeadmconstants.ClusterConfigurationConfigMapKey: dedent.Dedent(kubeadmConfig),
 | 
			
		||||
					},
 | 
			
		||||
				}
 | 
			
		||||
				return true, cm, nil
 | 
			
		||||
			}
 | 
			
		||||
			// Return an empty config map for kubelet and kube-proxy components.
 | 
			
		||||
			return true, &v1.ConfigMap{}, nil
 | 
			
		||||
		})
 | 
			
		||||
		return client, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Select a certificate used to simulate a missing certificate file
 | 
			
		||||
	brokenCertName := kubeadmconstants.APIServerCertAndKeyBaseName
 | 
			
		||||
	brokenCertPath, _ := pkiutil.PathsForCertAndKey(cfg.CertificatesDir, brokenCertName)
 | 
			
		||||
 | 
			
		||||
	type testCase struct {
 | 
			
		||||
		name           string
 | 
			
		||||
		config         string
 | 
			
		||||
		output         string
 | 
			
		||||
		brokenCertName string
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var runTestCase = func(t *testing.T, tc testCase) {
 | 
			
		||||
		var output bytes.Buffer
 | 
			
		||||
		cmd := newCmdCertsExpiration(&output, kdir)
 | 
			
		||||
		args := []string{
 | 
			
		||||
			fmt.Sprintf("--cert-dir=%s", cfg.CertificatesDir),
 | 
			
		||||
		}
 | 
			
		||||
		if tc.config != "" {
 | 
			
		||||
			args = append(args, fmt.Sprintf("--config=%s", tc.config))
 | 
			
		||||
		} else {
 | 
			
		||||
			clientSetFromFile = fakeClientSetFromFile
 | 
			
		||||
			defer func() {
 | 
			
		||||
				clientSetFromFile = kubeconfigutil.ClientSetFromFile
 | 
			
		||||
			}()
 | 
			
		||||
		}
 | 
			
		||||
		if tc.output != "" {
 | 
			
		||||
			args = append(args, fmt.Sprintf("-o=%s", tc.output))
 | 
			
		||||
		}
 | 
			
		||||
		cmd.SetArgs(args)
 | 
			
		||||
		require.NoError(t, cmd.Execute())
 | 
			
		||||
 | 
			
		||||
		switch tc.output {
 | 
			
		||||
		case "json":
 | 
			
		||||
			var info outputapiv1alpha3.CertificateExpirationInfo
 | 
			
		||||
			require.NoError(t, json.Unmarshal(output.Bytes(), &info))
 | 
			
		||||
			assert.Len(t, info.Certificates, len(kubeadmCerts)+len(kubeConfigs))
 | 
			
		||||
			assert.Len(t, info.CertificateAuthorities, len(caCerts))
 | 
			
		||||
			for _, cert := range info.Certificates {
 | 
			
		||||
				if tc.brokenCertName == cert.Name {
 | 
			
		||||
					assert.True(t, cert.Missing, "expected certificate to be missing")
 | 
			
		||||
				} else {
 | 
			
		||||
					assert.False(t, cert.Missing, "expected certificate to be present")
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		default:
 | 
			
		||||
			outputStr := output.String()
 | 
			
		||||
			if tc.brokenCertName != "" {
 | 
			
		||||
				assert.Contains(t, outputStr, "!MISSING!")
 | 
			
		||||
			} else {
 | 
			
		||||
				assert.NotContains(t, outputStr, "!MISSING!")
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			var lines []string
 | 
			
		||||
			for _, line := range strings.SplitAfter(outputStr, "\n") {
 | 
			
		||||
				if strings.TrimSpace(line) != "" {
 | 
			
		||||
					lines = append(lines, line)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			// 2 lines for the column headers.
 | 
			
		||||
			expectedLineCount := len(caCerts) + len(kubeadmCerts) + len(kubeConfigs) + 2
 | 
			
		||||
			assert.Lenf(t, lines, expectedLineCount, "expected %d non-blank lines in output", expectedLineCount)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	testCases := []testCase{
 | 
			
		||||
		{
 | 
			
		||||
			name:   "fetch kubeadm config from file and print columns and no missing certs",
 | 
			
		||||
			config: customConfigPath,
 | 
			
		||||
			output: "",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:   "fetch kubeadm config from server and print columns and no missing certs",
 | 
			
		||||
			output: "",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:   "fetch kubeadm config from file and print json and no missing certs",
 | 
			
		||||
			config: customConfigPath,
 | 
			
		||||
			output: "json",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:   "fetch kubeadm config from server and print json and no missing certs",
 | 
			
		||||
			output: "json",
 | 
			
		||||
		},
 | 
			
		||||
		// all broken cases must be at the end of the list.
 | 
			
		||||
		{
 | 
			
		||||
			name:           "fetch kubeadm config from file and print columns and missing certs",
 | 
			
		||||
			config:         customConfigPath,
 | 
			
		||||
			output:         "",
 | 
			
		||||
			brokenCertName: brokenCertName,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:           "fetch kubeadm config from server and print columns and missing certs",
 | 
			
		||||
			output:         "",
 | 
			
		||||
			brokenCertName: brokenCertName,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:           "fetch kubeadm config from file and print json and missing certs",
 | 
			
		||||
			config:         customConfigPath,
 | 
			
		||||
			output:         "json",
 | 
			
		||||
			brokenCertName: brokenCertName,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:           "fetch kubeadm config from server and print json and missing certs",
 | 
			
		||||
			output:         "json",
 | 
			
		||||
			brokenCertName: brokenCertName,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, tc := range testCases {
 | 
			
		||||
		tc := tc
 | 
			
		||||
		t.Run(tc.name, func(t *testing.T) {
 | 
			
		||||
			if tc.brokenCertName != "" {
 | 
			
		||||
				// remove the file to simulate a missing certificate
 | 
			
		||||
				_ = os.Remove(brokenCertPath)
 | 
			
		||||
			}
 | 
			
		||||
			runTestCase(t, tc)
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -115,7 +115,7 @@ func runDiff(flags *diffFlags, args []string) error {
 | 
			
		||||
			SkipCRIDetect: true,
 | 
			
		||||
		})
 | 
			
		||||
	} else {
 | 
			
		||||
		var client *client.Clientset
 | 
			
		||||
		var client client.Interface
 | 
			
		||||
		client, err = kubeconfigutil.ClientSetFromFile(flags.kubeConfigPath)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return errors.Wrapf(err, "couldn't create a Kubernetes client from file %q", flags.kubeConfigPath)
 | 
			
		||||
 
 | 
			
		||||
@@ -70,7 +70,7 @@ func CreateWithToken(serverURL, clusterName, userName string, caCert []byte, tok
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ClientSetFromFile returns a ready-to-use client from a kubeconfig file
 | 
			
		||||
func ClientSetFromFile(path string) (*clientset.Clientset, error) {
 | 
			
		||||
func ClientSetFromFile(path string) (clientset.Interface, error) {
 | 
			
		||||
	config, err := clientcmd.LoadFromFile(path)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrap(err, "failed to load admin kubeconfig")
 | 
			
		||||
@@ -79,7 +79,7 @@ func ClientSetFromFile(path string) (*clientset.Clientset, error) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToClientSet converts a KubeConfig object to a client
 | 
			
		||||
func ToClientSet(config *clientcmdapi.Config) (*clientset.Clientset, error) {
 | 
			
		||||
func ToClientSet(config *clientcmdapi.Config) (clientset.Interface, error) {
 | 
			
		||||
	overrides := clientcmd.ConfigOverrides{Timeout: "10s"}
 | 
			
		||||
	clientConfig, err := clientcmd.NewDefaultClientConfig(*config, &overrides).ClientConfig()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user