mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-25 04:33:26 +00:00
Merge pull request #123372 from carlory/fix-kubeadm-494
kubeadm certs check-expiration support json/yaml output
This commit is contained in:
commit
ec58e1f2fc
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user