fix json output when fetch kubeadm config from server

This commit is contained in:
carlory
2024-02-21 18:21:33 +08:00
parent 43ba0bd53b
commit 98437cb4be
3 changed files with 32 additions and 27 deletions

View File

@@ -29,6 +29,7 @@ import (
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/duration" "k8s.io/apimachinery/pkg/util/duration"
"k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/client-go/kubernetes"
"k8s.io/klog/v2" "k8s.io/klog/v2"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -259,7 +260,8 @@ func getRenewSubCommands(out io.Writer, kdir string) []*cobra.Command {
renewalFunc := func(handler *renewal.CertificateRenewHandler) func() error { renewalFunc := func(handler *renewal.CertificateRenewHandler) func() error {
return func() error { return func() error {
// Get cluster configuration (from --config, kubeadm-config ConfigMap, or default as a fallback) // 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 { if err != nil {
return err return err
} }
@@ -279,7 +281,8 @@ func getRenewSubCommands(out io.Writer, kdir string) []*cobra.Command {
Long: allLongDesc, Long: allLongDesc,
RunE: func(*cobra.Command, []string) error { RunE: func(*cobra.Command, []string) error {
// Get cluster configuration (from --config, kubeadm-config ConfigMap, or default as a fallback) // 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 { if err != nil {
return err return err
} }
@@ -339,27 +342,24 @@ func renewCert(kdir string, internalcfg *kubeadmapi.InitConfiguration, handler *
return nil 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. // 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 // NB. this operation should not block, because we want to allow certificate renewal also in case of not-working clusters
if cfgPath == "" { if cfgPath == "" && client != nil {
client, err := kubeconfigutil.ClientSetFromFile(kubeconfigPath) internalcfg, err := configutil.FetchInitConfigurationFromCluster(client, printer, logPrefix, false, false)
if err == nil { if err == nil {
internalcfg, err := configutil.FetchInitConfigurationFromCluster(client, nil, logPrefix, false, false) printer.Println() // add empty line to separate the FetchInitConfigurationFromCluster output from the command output
if err == nil { // certificate renewal or expiration checking doesn't depend on a running cluster, which means the CertificatesDir
fmt.Println() // add empty line to separate the FetchInitConfigurationFromCluster output from the command output // could be set to a value other than the default value or the value fetched from the cluster.
// certificate renewal or expiration checking doesn't depend on a running cluster, which means the CertificatesDir // cfg.CertificatesDir could be empty if the default value is set to empty (not true today).
// could be set to a value other than the default value or the value fetched from the cluster. if len(cfg.CertificatesDir) != 0 {
// cfg.CertificatesDir could be empty if the default value is set to empty (not true today). klog.V(1).Infof("Overriding the cluster certificate directory with the value from command line flag --%s: %s", options.CertificatesDir, cfg.CertificatesDir)
if len(cfg.CertificatesDir) != 0 { internalcfg.ClusterConfiguration.CertificatesDir = cfg.CertificatesDir
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
} }
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 // Read config from --config if provided. Otherwise, use the default configuration
@@ -418,6 +418,10 @@ func fetchCertificateExpirationInfo(rm *renewal.Manager) (*outputapiv1alpha3.Cer
return info, nil 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. // newCmdCertsExpiration creates a new `cert check-expiration` command.
func newCmdCertsExpiration(out io.Writer, kdir string) *cobra.Command { func newCmdCertsExpiration(out io.Writer, kdir string) *cobra.Command {
flags := &expirationFlags{ flags := &expirationFlags{
@@ -437,8 +441,14 @@ func newCmdCertsExpiration(out io.Writer, kdir string) *cobra.Command {
Short: "Check certificates expiration for a Kubernetes cluster", Short: "Check certificates expiration for a Kubernetes cluster",
Long: expirationLongDesc, Long: expirationLongDesc,
RunE: func(cmd *cobra.Command, args []string) error { 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) // 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 { if err != nil {
return err return err
} }
@@ -453,11 +463,6 @@ func newCmdCertsExpiration(out io.Writer, kdir string) *cobra.Command {
if err != nil { if err != nil {
return err return err
} }
printer, err := outputFlags.ToPrinter()
if err != nil {
return errors.Wrap(err, "could not construct output printer")
}
return printer.PrintObj(info, out) return printer.PrintObj(info, out)
}, },
Args: cobra.NoArgs, Args: cobra.NoArgs,

View File

@@ -115,7 +115,7 @@ func runDiff(flags *diffFlags, args []string) error {
SkipCRIDetect: true, SkipCRIDetect: true,
}) })
} else { } else {
var client *client.Clientset var client client.Interface
client, err = kubeconfigutil.ClientSetFromFile(flags.kubeConfigPath) client, err = kubeconfigutil.ClientSetFromFile(flags.kubeConfigPath)
if err != nil { if err != nil {
return errors.Wrapf(err, "couldn't create a Kubernetes client from file %q", flags.kubeConfigPath) return errors.Wrapf(err, "couldn't create a Kubernetes client from file %q", flags.kubeConfigPath)

View File

@@ -70,7 +70,7 @@ func CreateWithToken(serverURL, clusterName, userName string, caCert []byte, tok
} }
// ClientSetFromFile returns a ready-to-use client from a kubeconfig file // 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) config, err := clientcmd.LoadFromFile(path)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "failed to load admin kubeconfig") 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 // 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"} overrides := clientcmd.ConfigOverrides{Timeout: "10s"}
clientConfig, err := clientcmd.NewDefaultClientConfig(*config, &overrides).ClientConfig() clientConfig, err := clientcmd.NewDefaultClientConfig(*config, &overrides).ClientConfig()
if err != nil { if err != nil {