package cmd import ( "fmt" "os" "strings" "time" "github.com/Pingu-Studio/MaidnCLI/internal/k8s" "github.com/Pingu-Studio/MaidnCLI/internal/ui" "github.com/Pingu-Studio/MaidnCLI/internal/utils" "github.com/Pingu-Studio/MaidnCLI/internal/vault" "github.com/spf13/cobra" ) var vaultCmd = &cobra.Command{ Use: "vault", Short: "Manage Vault secrets for CI/CD.", } func init() { rootCmd.AddCommand(vaultCmd) vaultCmd.AddCommand(createDockerSecretCmd) vaultCmd.AddCommand(createGhcrSecretCmd) vaultCmd.AddCommand(createGithubSecretCmd) } var createDockerSecretCmd = &cobra.Command{ Use: "create-docker-secret", Short: "Creates a secret in Vault for Docker Hub and applies it to Kubernetes.", Run: runCreateDockerSecret, } var createGhcrSecretCmd = &cobra.Command{ Use: "create-ghcr-secret", Short: "Creates secrets in Vault for GHCR.", Run: runCreateGhcrSecret, } var createGithubSecretCmd = &cobra.Command{ Use: "create-github-secret", Short: "Creates a GitHub authentication secret in Vault.", Run: runCreateGithubSecret, } func runCreateDockerSecret(cmd *cobra.Command, args []string) { if err := k8s.CheckExternalSecretCRD(); err != nil { fmt.Printf("[ERROR] Prerequisite check failed: %v\n", err) os.Exit(1) } vm, err := vault.NewVaultManager() if err != nil { fmt.Printf("[ERROR] Failed to initialize Vault manager: %v\n", err) os.Exit(1) } username, password, err := ui.GetUserInputForDockerHub() if err != nil { fmt.Printf("[ERROR] %v\n", err) os.Exit(1) } dockerConfigJSON, err := vault.CreateDockerConfig(vault.DockerHubRegistry, username, password) if err != nil { fmt.Printf("[ERROR] Failed to create Docker config: %v\n", err) os.Exit(1) } secretData := map[string]string{vault.DockerConfigJSONKey: dockerConfigJSON} if err := vm.StoreSecret(vault.DockerHubSecretPath, secretData); err != nil { fmt.Printf("[ERROR] Failed to store Docker Hub secret in Vault: %v\n", err) os.Exit(1) } // First attempt to create the secret err = k8s.CreateDockerHubExternalSecret() if err == nil { // Success on the first try return } // If it failed, check for the specific cache error if strings.Contains(err.Error(), "no matches for kind") { // Handle the cache error interactively cacheCleared := utils.HandleKubectlCacheError(err) // If the user agreed and the cache was cleared, retry the operation if cacheCleared { fmt.Println("\n[INFO] Retrying to apply the ExternalSecret after clearing cache...") time.Sleep(1 * time.Second) // Give the system a moment to breathe err = k8s.CreateDockerHubExternalSecret() if err == nil { fmt.Println("[SUCCESS] ExternalSecret applied successfully on the second attempt.") return } } } // If we reach here, either the error was not the cache issue, or the retry failed. fmt.Printf("\n[ERROR] Operation failed. The secret is saved in Vault, but the ExternalSecret could not be applied to Kubernetes.\n") fmt.Printf("Final error: %v\n", err) os.Exit(1) } func runCreateGhcrSecret(cmd *cobra.Command, args []string) { if err := k8s.CheckExternalSecretCRD(); err != nil { fmt.Printf("[ERROR] Prerequisite check failed: %v\n", err) os.Exit(1) } vm, err := vault.NewVaultManager() if err != nil { fmt.Printf("[ERROR] Failed to initialize Vault manager: %v\n", err) os.Exit(1) } username, registryToken, orgToken, err := ui.GetUserInputForGhcr() if err != nil { fmt.Printf("[ERROR] %v\n", err) os.Exit(1) } dockerConfigJSON, err := vault.CreateDockerConfig(vault.GhcrRegistry, username, registryToken) if err != nil { fmt.Printf("[ERROR] Failed to create Docker config for GHCR: %v\n", err) os.Exit(1) } dockerSecretData := map[string]string{vault.DockerConfigJSONKey: dockerConfigJSON} if err := vm.StoreSecret(vault.GhcrSecretPath, dockerSecretData); err != nil { fmt.Printf("[ERROR] Failed to store GHCR secret in Vault: %v\n", err) os.Exit(1) } orgSecretData := map[string]string{vault.OrgManagementPATKey: orgToken} if err := vm.StoreSecret(vault.OrgManagementSecretPath, orgSecretData); err != nil { fmt.Printf("[ERROR] Failed to store organization management PAT in Vault: %v\n", err) os.Exit(1) } err = k8s.CreateGhcrExternalSecret() if err == nil { return } if strings.Contains(err.Error(), "no matches for kind") { cacheCleared := utils.HandleKubectlCacheError(err) if cacheCleared { fmt.Println("\n[INFO] Retrying to apply the ExternalSecret after clearing cache...") time.Sleep(1 * time.Second) err = k8s.CreateGhcrExternalSecret() if err == nil { fmt.Println("[SUCCESS] ExternalSecret applied successfully on the second attempt.") return } } } fmt.Printf("\n[ERROR] Operation failed. The secrets are saved in Vault, but the ExternalSecret for GHCR could not be applied to Kubernetes.\n") fmt.Printf("Final error: %v\n", err) os.Exit(1) } func runCreateGithubSecret(cmd *cobra.Command, args []string) { vm, err := vault.NewVaultManager() if err != nil { fmt.Printf("[ERROR] Failed to initialize Vault manager: %v\n", err) os.Exit(1) } username, token, err := ui.GetUserInputForGithubAuth() if err != nil { fmt.Printf("[ERROR] %v\n", err) os.Exit(1) } secretData := map[string]string{"username": username, "password": token} if err := vm.StoreSecret(vault.GithubAuthSecretPath, secretData); err != nil { fmt.Printf("[ERROR] Failed to store GitHub auth secret in Vault: %v\n", err) os.Exit(1) } }