diff --git a/clustertool/pkg/kubectlcmds/apply.go b/clustertool/pkg/kubectlcmds/apply.go index aab9dfa0716..9b7b598453a 100644 --- a/clustertool/pkg/kubectlcmds/apply.go +++ b/clustertool/pkg/kubectlcmds/apply.go @@ -11,6 +11,7 @@ import ( "github.com/go-logr/logr" "github.com/go-logr/zapr" + "github.com/rs/zerolog/log" "github.com/truecharts/public/clustertool/pkg/helper" "go.uber.org/zap" "go.uber.org/zap/zapcore" @@ -26,24 +27,31 @@ import ( // getKubeClient initializes and returns a controller-runtime client.Client func getKubeClient() (client.Client, error) { + log.Trace().Msg("Initializing Kubernetes client") + // Load kubeconfig from the default location kubeconfig := filepath.Join(homedir.HomeDir(), ".kube", "config") config, err := clientcmd.BuildConfigFromFlags("", kubeconfig) if err != nil { + log.Error().Err(err).Msg("Failed to load kubeconfig") return nil, fmt.Errorf("failed to load kubeconfig: %v", err) } // Create a controller-runtime client c, err := client.New(config, client.Options{}) if err != nil { + log.Error().Err(err).Msg("Failed to create Kubernetes client") return nil, fmt.Errorf("failed to create Kubernetes client: %v", err) } + log.Debug().Msg("Successfully initialized Kubernetes client") return c, nil } // setupLogger initializes a logger that writes to a buffer and returns both func setupLogger() (logr.Logger, *bytes.Buffer, error) { + log.Debug().Msg("Setting up logger") + // Create a buffer to capture logs var buf bytes.Buffer @@ -65,19 +73,23 @@ func setupLogger() (logr.Logger, *bytes.Buffer, error) { zapLogger := zap.New(core) // Wrap zap logger with zapr to get a logr.Logger interface - log := zapr.NewLogger(zapLogger) + logr := zapr.NewLogger(zapLogger) - return log, &buf, nil + log.Debug().Msg("Logger setup completed") + return logr, &buf, nil } // applyYAML applies the given YAML data to the Kubernetes cluster using the provided client and logger -func applyYAML(k8sClient client.Client, yamlData []byte, log logr.Logger) error { +func applyYAML(k8sClient client.Client, yamlData []byte, logr logr.Logger) error { + log.Trace().Msg("Applying YAML data to the Kubernetes cluster") + // Parse the YAML into KIO nodes reader := kio.ByteReader{ Reader: bytes.NewReader(yamlData), } nodes, err := reader.Read() if err != nil { + log.Error().Err(err).Msg("Failed to parse YAML") return fmt.Errorf("failed to parse YAML: %v", err) } @@ -85,57 +97,72 @@ func applyYAML(k8sClient client.Client, yamlData []byte, log logr.Logger) error for _, node := range nodes { obj := &unstructured.Unstructured{} if err := yaml.Unmarshal([]byte(node.MustString()), obj); err != nil { + log.Error().Err(err).Msg("Failed to unmarshal node") return fmt.Errorf("failed to unmarshal node: %v", err) } if err := k8sClient.Patch(context.TODO(), obj, client.Apply, client.FieldOwner("kustomize-controller")); err != nil { + log.Error().Err(err).Msg("Failed to apply object") return fmt.Errorf("failed to apply object: %v", err) } - log.Info("Successfully applied object", "object", obj.GetName(), "kind", obj.GetKind(), "namespace", obj.GetNamespace()) + log.Info().Msgf("Successfully applied object: %s of kind: %s in namespace: %s", obj.GetName(), obj.GetKind(), obj.GetNamespace()) } + log.Debug().Msg("YAML application completed") return nil } // filterLogOutput filters the log data by removing strings that match any of the provided regex patterns func filterLogOutput(logData string) (string, error) { + log.Trace().Msg("Filtering log output") + filteredLog := logData for _, pattern := range helper.KubeFilterStr { re, err := regexp.Compile(pattern) if err != nil { + log.Error().Err(err).Msgf("Invalid regex pattern '%s'", pattern) return "", fmt.Errorf("invalid regex pattern '%s': %v", pattern, err) } filteredLog = re.ReplaceAllString(filteredLog, "") } + + log.Debug().Msg("Log output filtering completed") return filteredLog, nil } // KubectlApply applies a YAML file to the Kubernetes cluster and filters the logs func KubectlApply(ctx context.Context, filePath string) error { + log.Trace().Msgf("Applying YAML file at path: %s", filePath) + // Check if the file exists if _, err := os.Stat(filePath); os.IsNotExist(err) { + log.Error().Err(err).Msgf("File does not exist: %s", filePath) return fmt.Errorf("file does not exist: %s", filePath) } // Read the YAML file yamlData, err := ioutil.ReadFile(filePath) if err != nil { + log.Error().Err(err).Msg("Failed to read YAML file") return fmt.Errorf("failed to read YAML file: %v", err) } // Initialize logger and buffer - log, buf, err := setupLogger() + logr, buf, err := setupLogger() if err != nil { + log.Error().Err(err).Msg("Failed to set up logger") return fmt.Errorf("failed to set up logger: %v", err) } // Initialize Kubernetes client k8sClient, err := getKubeClient() if err != nil { + log.Error().Err(err).Msg("Failed to initialize Kubernetes client") return err } // Apply the YAML to the cluster - if err := applyYAML(k8sClient, yamlData, log); err != nil { + if err := applyYAML(k8sClient, yamlData, logr); err != nil { + log.Error().Err(err).Msg("Failed to apply YAML") return fmt.Errorf("failed to apply YAML: %v", err) } @@ -145,25 +172,31 @@ func KubectlApply(ctx context.Context, filePath string) error { // Filter the logs filteredLog, err := filterLogOutput(logOutput) if err != nil { + log.Error().Err(err).Msg("Failed to filter logs") return fmt.Errorf("failed to filter logs: %v", err) } // Output filtered logs fmt.Println(filteredLog) + log.Info().Msg("KubectlApply operation completed") return nil } // KubectlApplyKustomize applies a kustomize directory or file to the Kubernetes cluster and filters the logs func KubectlApplyKustomize(ctx context.Context, filePath string) error { + log.Trace().Msgf("Applying Kustomize directory or file at path: %s", filePath) + // Check if the path exists if _, err := os.Stat(filePath); os.IsNotExist(err) { + log.Error().Err(err).Msgf("Path does not exist: %s", filePath) return fmt.Errorf("path does not exist: %s", filePath) } // Determine if the path is a directory or a file fileInfo, err := os.Stat(filePath) if err != nil { + log.Error().Err(err).Msg("Failed to stat path") return fmt.Errorf("failed to stat path: %v", err) } @@ -171,9 +204,11 @@ func KubectlApplyKustomize(ctx context.Context, filePath string) error { if fileInfo.IsDir() { // If it's a directory, use it as the kustomize path kustomizePath = filePath + log.Debug().Msgf("Using directory as kustomize path: %s", kustomizePath) } else { // If it's a file, use its directory as the kustomize path kustomizePath = filepath.Dir(filePath) + log.Debug().Msgf("Using file's directory as kustomize path: %s", kustomizePath) } // Process kustomize to get the YAML output @@ -181,30 +216,35 @@ func KubectlApplyKustomize(ctx context.Context, filePath string) error { k := krusty.MakeKustomizer(krusty.MakeDefaultOptions()) resMap, err := k.Run(fSys, kustomizePath) if err != nil { + log.Error().Err(err).Msg("Failed to run kustomize") return fmt.Errorf("failed to run kustomize: %v", err) } - // Convert ResMap to YAML - output, err := resMap.AsYaml() + // Get the YAML output from the resMap + yamlData, err := resMap.AsYaml() if err != nil { - return fmt.Errorf("failed to convert ResMap to YAML: %v", err) + log.Error().Err(err).Msg("Failed to convert kustomize output to YAML") + return fmt.Errorf("failed to convert kustomize output to YAML: %v", err) } // Initialize logger and buffer - log, buf, err := setupLogger() + logr, buf, err := setupLogger() if err != nil { + log.Error().Err(err).Msg("Failed to set up logger") return fmt.Errorf("failed to set up logger: %v", err) } // Initialize Kubernetes client k8sClient, err := getKubeClient() if err != nil { + log.Error().Err(err).Msg("Failed to initialize Kubernetes client") return err } // Apply the YAML to the cluster - if err := applyYAML(k8sClient, output, log); err != nil { - return fmt.Errorf("failed to apply YAML: %v", err) + if err := applyYAML(k8sClient, yamlData, logr); err != nil { + log.Error().Err(err).Msg("Failed to apply YAML from kustomize") + return fmt.Errorf("failed to apply YAML from kustomize: %v", err) } // Get log output from buffer @@ -213,11 +253,13 @@ func KubectlApplyKustomize(ctx context.Context, filePath string) error { // Filter the logs filteredLog, err := filterLogOutput(logOutput) if err != nil { + log.Error().Err(err).Msg("Failed to filter logs") return fmt.Errorf("failed to filter logs: %v", err) } // Output filtered logs fmt.Println(filteredLog) + log.Info().Msg("KubectlApplyKustomize operation completed") return nil }