diff --git a/cmd/argocdSync.go b/cmd/argocdSync.go index 797806803..38d19605a 100644 --- a/cmd/argocdSync.go +++ b/cmd/argocdSync.go @@ -1,9 +1,10 @@ package cmd import ( - "github.com/kubefirst/kubefirst/internal/argocd" "log" + "github.com/kubefirst/kubefirst/internal/argocd" + "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -20,10 +21,12 @@ This application is a tool to generate the needed files to quickly create a Cobra application.`, Run: func(cmd *cobra.Command, args []string) { - dryRun, err := cmd.Flags().GetBool("dry-run") - if err != nil { - log.Panic(err) - } + // dryRun, err := cmd.Flags().GetBool("dry-run") + // if err != nil { + // log.Panic(err) + // } + + dryRun := false log.Println("dry run enabled:", dryRun) diff --git a/cmd/checktools.go b/cmd/checktools.go index 7592ae4ad..1b2319d53 100644 --- a/cmd/checktools.go +++ b/cmd/checktools.go @@ -2,6 +2,7 @@ package cmd import ( "fmt" + "github.com/kubefirst/kubefirst/configs" "github.com/kubefirst/kubefirst/pkg" "github.com/spf13/cobra" @@ -27,13 +28,13 @@ var checktoolsCmd = &cobra.Command{ fmt.Printf("-> helm version:\n\t%s\n\t%s\n", helmVersion, helmStdErr) if errKubectl != nil { - fmt.Println("failed to call kubectlVersionCmd.Run(): %v", errKubectl) + fmt.Printf("failed to call kubectlVersionCmd.Run(): %v", errKubectl) } if errHelm != nil { - fmt.Println("failed to call helmVersionCmd.Run(): %v", errHelm) + fmt.Printf("failed to call helmVersionCmd.Run(): %v", errHelm) } if errTerraform != nil { - fmt.Println("failed to call terraformVersionCmd.Run(): %v", errTerraform) + fmt.Printf("failed to call terraformVersionCmd.Run(): %v", errTerraform) } }, diff --git a/cmd/create.go b/cmd/create.go index 28cd03cb8..fbc6959f9 100644 --- a/cmd/create.go +++ b/cmd/create.go @@ -12,15 +12,19 @@ import ( "github.com/kubefirst/kubefirst/internal/argocd" "github.com/kubefirst/kubefirst/internal/gitlab" "github.com/kubefirst/kubefirst/internal/helm" + "github.com/kubefirst/kubefirst/internal/k8s" "github.com/kubefirst/kubefirst/internal/progressPrinter" + "github.com/kubefirst/kubefirst/internal/reports" "github.com/kubefirst/kubefirst/internal/softserve" "github.com/kubefirst/kubefirst/internal/terraform" "github.com/kubefirst/kubefirst/internal/vault" + "github.com/kubefirst/kubefirst/pkg" "github.com/spf13/cobra" "github.com/spf13/viper" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/tools/clientcmd" ) - // createCmd represents the create command var createCmd = &cobra.Command{ Use: "create", @@ -81,8 +85,8 @@ to quickly create a Cobra application.`, defer kPortForwardSoftServe.Process.Signal(syscall.SIGTERM) if err != nil { // If it doesn't error, we kinda don't care much. - log.Println("Commad Execution STDOUT: %s", kPortForwardSoftServeOutb.String()) - log.Println("Commad Execution STDERR: %s", kPortForwardSoftServeErrb.String()) + log.Printf("Commad Execution STDOUT: %s", kPortForwardSoftServeOutb.String()) + log.Printf("Commad Execution STDERR: %s", kPortForwardSoftServeErrb.String()) log.Panicf("error: failed to port-forward to soft-serve %s", err) } time.Sleep(20 * time.Second) @@ -101,22 +105,22 @@ to quickly create a Cobra application.`, waitArgoCDToBeReady(dryRun) informUser("ArgoCD Ready") progressPrinter.IncrementTracker("step-argo", 1) - if !dryRun { - var kPortForwardArgocdOutb, kPortForwardArgocdErrb bytes.Buffer - kPortForwardArgocd := exec.Command(config.KubectlClientPath, "--kubeconfig", config.KubeConfigPath, "-n", "argocd", "port-forward", "svc/argocd-server", "8080:80") - kPortForwardArgocd.Stdout = &kPortForwardArgocdOutb - kPortForwardArgocd.Stderr = &kPortForwardArgocdErrb - err = kPortForwardArgocd.Start() - defer kPortForwardArgocd.Process.Signal(syscall.SIGTERM) - if err != nil { - log.Println("Commad Execution STDOUT: %s", kPortForwardArgocdOutb.String()) - log.Println("Commad Execution STDERR: %s", kPortForwardArgocdErrb.String()) - log.Panicf("error: failed to port-forward to argocd in main thread %s", err) - } - log.Println("sleeping for 45 seconds, hurry up jared") - time.Sleep(45 * time.Second) + var kPortForwardArgocdOutb, kPortForwardArgocdErrb bytes.Buffer + kPortForwardArgocd := exec.Command(config.KubectlClientPath, "--kubeconfig", config.KubeConfigPath, "-n", "argocd", "port-forward", "svc/argocd-server", "8080:80") + kPortForwardArgocd.Stdout = &kPortForwardArgocdOutb + kPortForwardArgocd.Stderr = &kPortForwardArgocdErrb + err = kPortForwardArgocd.Start() + defer kPortForwardArgocd.Process.Signal(syscall.SIGTERM) + if err != nil { + log.Printf("Commad Execution STDOUT: %s", kPortForwardArgocdOutb.String()) + log.Printf("Commad Execution STDERR: %s", kPortForwardArgocdErrb.String()) + log.Panicf("error: failed to port-forward to argocd in main thread %s", err) } + + // log.Println("sleeping for 45 seconds, hurry up jared") + // time.Sleep(45 * time.Second) + informUser(fmt.Sprintf("ArgoCD available at %s", viper.GetString("argocd.local.service"))) progressPrinter.IncrementTracker("step-argo", 1) @@ -128,6 +132,13 @@ to quickly create a Cobra application.`, token := argocd.GetArgocdAuthToken(dryRun) progressPrinter.IncrementTracker("step-argo", 1) + _, _, err = pkg.ExecShellReturnStrings(config.KubectlClientPath, "--kubeconfig", config.KubeConfigPath, "-n", "argocd", "apply", "-f", fmt.Sprintf("%s/gitops/components/helpers/registry.yaml", config.K1FolderPath)) + if err != nil { + log.Panicf("failed to call execute kubectl apply of argocd patch to adopt gitlab: %s", err) + } + time.Sleep(45 * time.Second) + //TODO: ensure argocd is in a good heathy state before syncing the registry application + informUser("Syncing the registry application") argocd.SyncArgocdApplication(dryRun, "registry", token) progressPrinter.IncrementTracker("step-argo", 1) @@ -135,8 +146,8 @@ to quickly create a Cobra application.`, // todo, need to stall until the registry has synced, then get to ui asap //! skip this if syncing from argocd and not helm installing - log.Printf("sleeping for 30 seconds, hurry up jared sign into argocd %s", viper.GetString("argocd.admin.password")) - time.Sleep(30 * time.Second) + // log.Printf("sleeping for 30 seconds, hurry up jared sign into argocd %s", viper.GetString("argocd.admin.password")) + // time.Sleep(30 * time.Second) //! //* we need to stop here and wait for the vault namespace to exist and the vault pod to be ready @@ -159,8 +170,8 @@ to quickly create a Cobra application.`, log.Panicf("error: failed to port-forward to vault in main thread %s", err) } } - loopUntilPodIsReady() - initializeVaultAndAutoUnseal() + loopUntilPodIsReady(dryRun) + initializeVaultAndAutoUnseal(dryRun) informUser(fmt.Sprintf("Vault available at %s", viper.GetString("vault.local.service"))) progressPrinter.IncrementTracker("step-gitlab", 1) @@ -180,8 +191,8 @@ to quickly create a Cobra application.`, defer kPortForwardGitlab.Process.Signal(syscall.SIGTERM) if err != nil { // If it doesn't error, we kinda don't care much. - log.Println("Commad Execution STDOUT: %s", kPortForwardGitlabOutb.String()) - log.Println("Commad Execution STDERR: %s", kPortForwardGitlabErrb.String()) + log.Printf("Commad Execution STDOUT: %s", kPortForwardGitlabOutb.String()) + log.Printf("Commad Execution STDERR: %s", kPortForwardGitlabErrb.String()) log.Panicf("error: failed to port-forward to gitlab in main thread %s", err) } } @@ -199,75 +210,146 @@ to quickly create a Cobra application.`, gitlab.GitlabKeyUpload(dryRun) informUser("Gitlab ready") progressPrinter.IncrementTracker("step-gitlab", 1) + } + if !skipVault { + + progressPrinter.AddTracker("step-vault", "Configure Vault", 4) + informUser("waiting for vault unseal") + /** + + */ + waitVaultToBeRunning(dryRun) + informUser("Vault running") + progressPrinter.IncrementTracker("step-vault", 1) + + waitForVaultUnseal(dryRun, config) + informUser("Vault unseal") + progressPrinter.IncrementTracker("step-vault", 1) + + log.Println("configuring vault") + vault.ConfigureVault(dryRun) + informUser("Vault configured") + progressPrinter.IncrementTracker("step-vault", 1) + + log.Println("creating vault configured secret") + createVaultConfiguredSecret(dryRun, config) + informUser("Vault secret created") + progressPrinter.IncrementTracker("step-vault", 1) + } - if !skipVault { - - progressPrinter.AddTracker("step-vault", "Configure Vault", 4) - informUser("waiting for vault unseal") - /** - - */ - waitVaultToBeRunning(dryRun) - informUser("Vault running") - progressPrinter.IncrementTracker("step-vault", 1) - - waitForVaultUnseal(dryRun, config) - informUser("Vault unseal") - progressPrinter.IncrementTracker("step-vault", 1) + if !viper.GetBool("gitlab.oidc-created") { + progressPrinter.AddTracker("step-post-gitlab", "Finalize Gitlab updates", 5) + vault.AddGitlabOidcApplications(dryRun) + informUser("Added Gitlab OIDC") + progressPrinter.IncrementTracker("step-post-gitlab", 1) - log.Println("configuring vault") - vault.ConfigureVault(dryRun) - informUser("Vault configured") - progressPrinter.IncrementTracker("step-vault", 1) + informUser("Waiting for Gitlab dns to propagate before continuing") + gitlab.AwaitHost("gitlab", dryRun) + progressPrinter.IncrementTracker("step-post-gitlab", 1) - log.Println("creating vault configured secret") - createVaultConfiguredSecret(dryRun, config) - informUser("Vault secret created") - progressPrinter.IncrementTracker("step-vault", 1) + informUser("Pushing gitops repo to origin gitlab") + // refactor: sounds like a new functions, should PushGitOpsToGitLab be renamed/update signature? + viper.Set("gitlab.oidc-created", true) + viper.WriteConfig() + } + if !viper.GetBool("gitlab.gitops-pushed") { + gitlab.PushGitRepo(dryRun, config, "gitlab", "gitops") // todo: need to handle if this was already pushed, errors on failure) + progressPrinter.IncrementTracker("step-post-gitlab", 1) + // todo: keep one of the two git push functions, they're similar, but not exactly the same + //gitlab.PushGitOpsToGitLab(dryRun) + viper.Set("gitlab.gitops-pushed", true) + viper.WriteConfig() + } + if !dryRun && !viper.GetBool("argocd.oidc-patched") { + cfg := configs.ReadConfig() + config, err := clientcmd.BuildConfigFromFlags("", cfg.KubeConfigPath) + if err != nil { + panic(err.Error()) + } + clientset, err := kubernetes.NewForConfig(config) + if err != nil { + panic(err.Error()) } - if !viper.GetBool("gitlab.oidc-created") { - progressPrinter.AddTracker("step-post-gitlab", "Finalize Gitlab updates", 5) - vault.AddGitlabOidcApplications(dryRun) - informUser("Added Gitlab OIDC") - progressPrinter.IncrementTracker("step-post-gitlab", 1) - - informUser("Waiting for Gitlab dns to propagate before continuing") - gitlab.AwaitGitlab(dryRun) - progressPrinter.IncrementTracker("step-post-gitlab", 1) + argocdSecretClient = clientset.CoreV1().Secrets("argocd") + patchSecret(argocdSecretClient, "argocd-secret", "oidc.gitlab.clientSecret", viper.GetString("gitlab.oidc.argocd.secret")) - informUser("Pushing gitops repo to origin gitlab") - // refactor: sounds like a new functions, should PushGitOpsToGitLab be renamed/update signature? - viper.Set("gitlab.oidc-created", true) - viper.WriteConfig() - } - if !viper.GetBool("gitlab.gitops-pushed") { - gitlab.PushGitRepo(dryRun, config, "gitlab", "gitops") // todo: need to handle if this was already pushed, errors on failure) - progressPrinter.IncrementTracker("step-post-gitlab", 1) - // todo: keep one of the two git push functions, they're similar, but not exactly the same - //gitlab.PushGitOpsToGitLab(dryRun) - viper.Set("gitlab.gitops-pushed", true) - viper.WriteConfig() + argocdPodClient := clientset.CoreV1().Pods("argocd") + argocdPodName := k8s.GetPodNameByLabel(argocdPodClient, "app.kubernetes.io/name=argocd-server") + k8s.DeletePodByName(argocdPodClient, argocdPodName) + viper.Set("argocd.oidc-patched", true) + viper.WriteConfig() + } + if !viper.GetBool("gitlab.metaphor-pushed") { + informUser("Pushing metaphor repo to origin gitlab") + gitlab.PushGitRepo(dryRun, config, "gitlab", "metaphor") + progressPrinter.IncrementTracker("step-post-gitlab", 1) + // todo: keep one of the two git push functions, they're similar, but not exactly the same + //gitlab.PushGitOpsToGitLab(dryRun) + viper.Set("gitlab.metaphor-pushed", true) + viper.WriteConfig() + } + if !viper.GetBool("gitlab.registered") { + // informUser("Getting ArgoCD auth token") + // token := argocd.GetArgocdAuthToken(dryRun) + // progressPrinter.IncrementTracker("step-post-gitlab", 1) + + // informUser("Detaching the registry application from softserve") + // argocd.DeleteArgocdApplicationNoCascade(dryRun, "registry", token) + // progressPrinter.IncrementTracker("step-post-gitlab", 1) + + informUser("Adding the registry application registered against gitlab") + gitlab.ChangeRegistryToGitLab(dryRun) + progressPrinter.IncrementTracker("step-post-gitlab", 1) + // todo triage / force apply the contents adjusting + // todo kind: Application .repoURL: + + // informUser("Waiting for argocd host to resolve") + // gitlab.AwaitHost("argocd", dryRun) + cfg := configs.ReadConfig() + config, err := clientcmd.BuildConfigFromFlags("", cfg.KubeConfigPath) + if err != nil { + panic(err.Error()) } - if !viper.GetBool("gitlab.metaphor-pushed") { - informUser("Pushing metaphor repo to origin gitlab") - gitlab.PushGitRepo(dryRun, config, "gitlab", "metaphor") - progressPrinter.IncrementTracker("step-post-gitlab", 1) - // todo: keep one of the two git push functions, they're similar, but not exactly the same - //gitlab.PushGitOpsToGitLab(dryRun) - viper.Set("gitlab.metaphor-pushed", true) - viper.WriteConfig() + clientset, err := kubernetes.NewForConfig(config) + if err != nil { + panic(err.Error()) } - if !viper.GetBool("gitlab.registered") { - informUser("Changing registry to Gitlab") - gitlab.ChangeRegistryToGitLab(dryRun) - progressPrinter.IncrementTracker("step-post-gitlab", 1) - // todo triage / force apply the contents adjusting - // todo kind: Application .repoURL: - viper.Set("gitlab.registered", true) - viper.WriteConfig() + argocdPodClient := clientset.CoreV1().Pods("argocd") + argocdPodName := k8s.GetPodNameByLabel(argocdPodClient, "app.kubernetes.io/name=argocd-server") + kPortForwardArgocd.Process.Signal(syscall.SIGTERM) + informUser("deleting argocd-server pod") + k8s.DeletePodByName(argocdPodClient, argocdPodName) + informUser("waiting for argocd to be ready") + waitArgoCDToBeReady(dryRun) + + informUser("Port forwarding to new argocd-server pod") + if !dryRun { + time.Sleep(time.Second * 20) + var kPortForwardArgocdOutb, kPortForwardArgocdErrb bytes.Buffer + config := configs.ReadConfig() + kPortForwardArgocd := exec.Command(config.KubectlClientPath, "--kubeconfig", config.KubeConfigPath, "-n", "argocd", "port-forward", "svc/argocd-server", "8080:80") + kPortForwardArgocd.Stdout = &kPortForwardArgocdOutb + kPortForwardArgocd.Stderr = &kPortForwardArgocdErrb + err = kPortForwardArgocd.Start() + defer kPortForwardArgocd.Process.Signal(syscall.SIGTERM) + if err != nil { + log.Printf("Commad Execution STDOUT: %s", kPortForwardArgocdOutb.String()) + log.Printf("Commad Execution STDERR: %s", kPortForwardArgocdErrb.String()) + log.Panicf("error: failed to port-forward to argocd in main thread %s", err) + } + log.Println("sleeping for 40 seconds") + time.Sleep(40 * time.Second) } + + informUser("Syncing the registry application") + token := argocd.GetArgocdAuthToken(dryRun) + argocd.SyncArgocdApplication(dryRun, "registry", token) + + viper.Set("gitlab.registered", true) + viper.WriteConfig() } + sendCompleteInstallTelemetry(dryRun) time.Sleep(time.Millisecond * 100) diff --git a/cmd/createUtils.go b/cmd/createUtils.go index e132d6fb2..f3425ffd1 100644 --- a/cmd/createUtils.go +++ b/cmd/createUtils.go @@ -129,7 +129,11 @@ func waitVaultToBeRunning(dryRun bool) { } } -func loopUntilPodIsReady() { +func loopUntilPodIsReady(dryRun bool) { + if dryRun { + log.Printf("[#99] Dry-run mode, loopUntilPodIsReady skipped.") + return + } x := 50 url := "http://localhost:8200/v1/sys/health" @@ -153,7 +157,7 @@ func loopUntilPodIsReady() { log.Println("vault is availbale but the body is not what is expected ", err) continue } - fmt.Println(string(body)) + log.Println(string(body)) var responseJson map[string]interface{} @@ -196,7 +200,11 @@ type VaultUnsealResponse struct { KeysB64 []string `json:"keys_base64"` } -func initializeVaultAndAutoUnseal() { +func initializeVaultAndAutoUnseal(dryRun bool) { + if dryRun { + log.Printf("[#99] Dry-run mode, initializeVaultAndAutoUnseal skipped.") + return + } url := "http://127.0.0.1:8200/v1/sys/init" payload := strings.NewReader("{\n\t\"stored_shares\": 3,\n\t\"recovery_threshold\": 3,\n\t\"recovery_shares\": 5\n}") diff --git a/cmd/destroy.go b/cmd/destroy.go index e34c54471..c55d1d5e5 100644 --- a/cmd/destroy.go +++ b/cmd/destroy.go @@ -3,6 +3,7 @@ package cmd import ( "bytes" "log" + "os" "os/exec" "syscall" @@ -44,14 +45,14 @@ if the registry has already been deleted.`, log.Panic(err) } - // kPortForward := exec.Command(config.KubectlClientPath, "--kubeconfig", config.KubeConfigPath, "-n", "gitlab", "port-forward", "svc/gitlab-webservice-default", "8888:8080") - // kPortForward.Stdout = os.Stdout - // kPortForward.Stderr = os.Stderr - // defer kPortForward.Process.Signal(syscall.SIGTERM) - // err = kPortForward.Start() - // if err != nil { - // log.Panicf("error: failed to port-forward to gitlab in main thread %s", err) - // } + kPortForward := exec.Command(config.KubectlClientPath, "--kubeconfig", config.KubeConfigPath, "-n", "gitlab", "port-forward", "svc/gitlab-webservice-default", "8888:8080") + kPortForward.Stdout = os.Stdout + kPortForward.Stderr = os.Stderr + defer kPortForward.Process.Signal(syscall.SIGTERM) + err = kPortForward.Start() + if err != nil { + log.Printf("warning: failed to port-forward to gitlab in main thread %s", err) + } var kPortForwardArgocdOutb, kPortForwardArgocdErrb bytes.Buffer kPortForwardArgocd := exec.Command(config.KubectlClientPath, "--kubeconfig", config.KubeConfigPath, "-n", "argocd", "port-forward", "svc/argocd-server", "8080:80") @@ -60,8 +61,8 @@ if the registry has already been deleted.`, err = kPortForwardArgocd.Start() defer kPortForwardArgocd.Process.Signal(syscall.SIGTERM) if err != nil { - log.Println("Commad Execution STDOUT: %s", kPortForwardArgocdOutb.String()) - log.Println("Commad Execution STDERR: %s", kPortForwardArgocdErrb.String()) + log.Printf("Commad Execution STDOUT: %s", kPortForwardArgocdOutb.String()) + log.Printf("Commad Execution STDERR: %s", kPortForwardArgocdErrb.String()) log.Panicf("error: failed to port-forward to argocd in main thread %s", err) } // kPortForwardVault := exec.Command(config.KubectlClientPath, "--kubeconfig", config.KubeConfigPath, "-n", "vault", "port-forward", "svc/vault", "8200:8200") diff --git a/cmd/kubefirstTemplate.go b/cmd/kubefirstTemplate.go index 6ae7afffc..0d0a09ae2 100644 --- a/cmd/kubefirstTemplate.go +++ b/cmd/kubefirstTemplate.go @@ -14,6 +14,7 @@ import ( "github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing/object" "github.com/kubefirst/kubefirst/configs" + "github.com/kubefirst/kubefirst/pkg" "github.com/spf13/viper" ) @@ -42,7 +43,7 @@ func prepareKubefirstTemplateRepo(config *configs.Config, githubOrg, repoName st log.Printf("cloned %s-template repository to directory %s/%s", repoName, config.K1FolderPath, repoName) log.Printf("detokenizing %s/%s", config.K1FolderPath, repoName) - detokenize(directory) + pkg.Detokenize(directory) log.Printf("detokenization of %s/%s complete", config.K1FolderPath, repoName) viper.Set(fmt.Sprintf("init.repos.%s.detokenized", repoName), true) @@ -78,13 +79,13 @@ func prepareKubefirstTemplateRepo(config *configs.Config, githubOrg, repoName st viper.WriteConfig() } -func detokenize(path string) { +// func detokenize(path string) { - err := filepath.Walk(path, detokenizeDirectory) - if err != nil { - panic(err) - } -} +// err := filepath.Walk(path, detokenizeDirectory) +// if err != nil { +// panic(err) +// } +// } func detokenizeDirectory(path string, fi os.FileInfo, err error) error { if err != nil { diff --git a/cmd/kubernetes.go b/cmd/kubernetes.go index 0a55ac04b..c2ce85624 100644 --- a/cmd/kubernetes.go +++ b/cmd/kubernetes.go @@ -9,15 +9,16 @@ import ( "context" "encoding/json" "fmt" + "log" + "os" + "os/exec" + "time" + "github.com/kubefirst/kubefirst/configs" "github.com/kubefirst/kubefirst/pkg" "github.com/spf13/viper" metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" coreV1Types "k8s.io/client-go/kubernetes/typed/core/v1" - "log" - "os" - "os/exec" - "time" ) var vaultRootToken string @@ -29,16 +30,16 @@ var vaultSecretClient coreV1Types.SecretInterface var argocdSecretClient coreV1Types.SecretInterface var gitlabPodsClient coreV1Types.PodInterface -func getPodNameByLabel(gitlabPodsClient coreV1Types.PodInterface, label string) string { - pods, err := gitlabPodsClient.List(context.TODO(), metaV1.ListOptions{LabelSelector: fmt.Sprintf("app=%s", label)}) - if err != nil { - fmt.Println(err) - } +// func getPodNameByLabel(gitlabPodsClient coreV1Types.PodInterface, label string) string { +// pods, err := gitlabPodsClient.List(context.TODO(), metaV1.ListOptions{LabelSelector: label}) +// if err != nil { +// fmt.Println(err) +// } - gitlabToolboxPodName = pods.Items[0].Name +// gitlabToolboxPodName = pods.Items[0].Name - return gitlabToolboxPodName -} +// return gitlabToolboxPodName +// } func waitForVaultUnseal(dryRun bool, config *configs.Config) { if dryRun { @@ -99,7 +100,7 @@ func createVaultConfiguredSecret(dryRun bool, config *configs.Config) { if err != nil { log.Panicf("failed to create secret for vault-configured: %s", err) } - log.Println("the secret create output is: %s", output.String()) + log.Printf("the secret create output is: %s", output.String()) viper.Set("vault.configuredsecret", true) viper.WriteConfig() @@ -136,6 +137,15 @@ func getSecretValue(k8sClient coreV1Types.SecretInterface, secretName, key strin return string(secret.Data[key]) } +func patchSecret(k8sClient coreV1Types.SecretInterface, secretName, key, val string) { + secret, err := k8sClient.Get(context.TODO(), secretName, metaV1.GetOptions{}) + if err != nil { + log.Println(fmt.Sprintf("error getting key: %s from secret: %s", key, secretName), err) + } + secret.Data[key] = []byte(val) + k8sClient.Update(context.TODO(), secret, metaV1.UpdateOptions{}) +} + func waitForNamespaceandPods(dryRun bool, config *configs.Config, namespace, podLabel string) { if dryRun { log.Printf("[#99] Dry-run mode, waitForNamespaceandPods skipped") diff --git a/internal/argocd/argocd.go b/internal/argocd/argocd.go index c940b8c81..8cdf1a9f0 100644 --- a/internal/argocd/argocd.go +++ b/internal/argocd/argocd.go @@ -145,20 +145,26 @@ func GetArgocdAuthToken(dryRun bool) string { x := 3 for i := 0; i < x; i++ { + log.Print("requesting auth token from argocd: attempt %s of %s", i, x) + time.Sleep(1 * time.Second) res, err := client.Do(req) + if err != nil { - log.Panic("error requesting auth token from argocd", err) - } else { - defer res.Body.Close() + log.Print("error requesting auth token from argocd", err) + continue + } else { + defer res.Body.Close() body, err := ioutil.ReadAll(res.Body) if err != nil { - log.Panic("error sending POST request to get argocd auth token :", err) + log.Print("error sending POST request to get argocd auth token:", err) + continue } var dat map[string]interface{} if err := json.Unmarshal(body, &dat); err != nil { - log.Panicf("error unmarshalling %s", err) + log.Print("error unmarshalling %s", err) + continue } token := dat["token"] viper.Set("argocd.admin.apitoken", token) @@ -168,6 +174,9 @@ func GetArgocdAuthToken(dryRun bool) string { return token.(string) } } + log.Panic("Fail to get a token") + // This code is unreacheble, as in absence of token we want to fail the install. + // I kept is to avoid compiler to complain. return "" } @@ -188,3 +197,21 @@ func SyncArgocdApplication(dryRun bool, applicationName, argocdAuthToken string) log.Panicf("error: curl appSync failed failed %s", err) } } + +func DeleteArgocdApplicationNoCascade(dryRun bool, applicationName, argocdAuthToken string) { + if dryRun { + log.Printf("[#99] Dry-run mode, SyncArgocdApplication skipped.") + return + } + + // todo need to replace this with a curl wrapper and see if it WORKS + + url := fmt.Sprintf("https://localhost:8080/api/v1/applications/%s?cascade=false", applicationName) + var outb bytes.Buffer + + _, _, err := pkg.ExecShellReturnStrings("curl", "-k", "-L", "-X", "DELETE", url, "-H", fmt.Sprintf("Authorization: Bearer %s", argocdAuthToken)) + log.Println("the value from the curl command to delete registry in argocd is:", outb.String()) + if err != nil { + log.Panicf("error: curl app delete failed %s", err) + } +} diff --git a/internal/gitlab/gitlab.go b/internal/gitlab/gitlab.go index b0d88b697..664e91233 100644 --- a/internal/gitlab/gitlab.go +++ b/internal/gitlab/gitlab.go @@ -124,7 +124,7 @@ func PushGitOpsToGitLab(dryRun bool) { }, }) if err != nil { - log.Panicf("error committing changes", err) + log.Panicf("error committing changes %s", err) } log.Println("setting auth...") @@ -141,34 +141,38 @@ func PushGitOpsToGitLab(dryRun bool) { Auth: auth, }) if err != nil { - log.Panicf("error pushing to remote", err) + log.Panicf("error pushing to remote %s", err) } } -func AwaitGitlab(dryRun bool) { +func AwaitHost(appName string, dryRun bool) { - log.Println("AwaitGitlab called") + log.Println("AwaitHost called") if dryRun { - log.Printf("[#99] Dry-run mode, AwaitGitlab skipped.") + log.Printf("[#99] Dry-run mode, AwaitHost skipped.") return } max := 200 for i := 0; i < max; i++ { hostedZoneName := viper.GetString("aws.hostedzonename") - resp, _ := http.Get(fmt.Sprintf("https://gitlab.%s", hostedZoneName)) + resp, _ := http.Get(fmt.Sprintf("https://%s.%s", appName, hostedZoneName)) if resp != nil && resp.StatusCode == 200 { - log.Println("gitlab host resolved, 30 second grace period required...") + log.Println(fmt.Printf("%s host resolved, 30 second grace period required...", appName)) time.Sleep(time.Second * 30) i = max } else { - log.Println("gitlab host not resolved, sleeping 10s") + log.Println(fmt.Printf("%s host not resolved, sleeping 10s", appName)) time.Sleep(time.Second * 10) } } } func ProduceGitlabTokens(dryRun bool) { + if dryRun { + log.Printf("[#99] Dry-run mode, ProduceGitlabTokens skipped.") + return + } //TODO: Should this step be skipped if already executed? config := configs.ReadConfig() k8sConfig, err := clientcmd.BuildConfigFromFlags("", config.KubeConfigPath) @@ -180,10 +184,6 @@ func ProduceGitlabTokens(dryRun bool) { log.Panic(err.Error()) } log.Println("discovering gitlab toolbox pod") - if dryRun { - log.Printf("[#99] Dry-run mode, ProduceGitlabTokens skipped.") - return - } time.Sleep(30 * time.Second) // todo: move it to config k8s.ArgocdSecretClient = clientset.CoreV1().Secrets("argocd") @@ -195,8 +195,8 @@ func ProduceGitlabTokens(dryRun bool) { log.Println("discovering gitlab toolbox pod") - k8s.GitlabPodsClient = clientset.CoreV1().Pods("gitlab") - gitlabPodName := k8s.GetPodNameByLabel(k8s.GitlabPodsClient, "toolbox") + gitlabPodClient := clientset.CoreV1().Pods("gitlab") + gitlabPodName := k8s.GetPodNameByLabel(gitlabPodClient, "app=toolbox") k8s.GitlabSecretClient = clientset.CoreV1().Secrets("gitlab") secrets, err := k8s.GitlabSecretClient.List(context.TODO(), metaV1.ListOptions{}) @@ -391,27 +391,30 @@ func ChangeRegistryToGitLab(dryRun bool) { var secrets bytes.Buffer c, err := template.New("creds-gitlab").Parse(` - apiVersion: v1 - data: - password: {{ .PersonalAccessToken }} - url: {{ .URL }} - username: cm9vdA== - kind: Secret - metadata: - annotations: - managed-by: argocd.argoproj.io - labels: - argocd.argoproj.io/secret-type: repo-creds - name: creds-gitlab - namespace: argocd - type: Opaque - `) + apiVersion: v1 + data: + password: {{ .PersonalAccessToken }} + url: {{ .URL }} + username: cm9vdA== + kind: Secret + metadata: + annotations: + managed-by: argocd.argoproj.io + labels: + argocd.argoproj.io/secret-type: repo-creds + name: creds-gitlab + namespace: argocd + type: Opaque + `) if err := c.Execute(&secrets, creds); err != nil { log.Panicf("error executing golang template for git repository credentials template %s", err) } ba := []byte(secrets.String()) err = yaml.Unmarshal(ba, &argocdRepositoryAccessTokenSecret) + if err != nil { + log.Println("error unmarshalling yaml during argocd repository secret create", err) + } _, err = k8s.ArgocdSecretClient.Create(context.TODO(), argocdRepositoryAccessTokenSecret, metaV1.CreateOptions{}) if err != nil { @@ -421,21 +424,21 @@ func ChangeRegistryToGitLab(dryRun bool) { var repoSecrets bytes.Buffer c, err = template.New("repo-gitlab").Parse(` - apiVersion: v1 - data: - project: ZGVmYXVsdA== - type: Z2l0 - url: {{ .FullURL }} - kind: Secret - metadata: - annotations: - managed-by: argocd.argoproj.io - labels: - argocd.argoproj.io/secret-type: repository - name: repo-gitlab - namespace: argocd - type: Opaque - `) + apiVersion: v1 + data: + project: ZGVmYXVsdA== + type: Z2l0 + url: {{ .FullURL }} + kind: Secret + metadata: + annotations: + managed-by: argocd.argoproj.io + labels: + argocd.argoproj.io/secret-type: repository + name: repo-gitlab + namespace: argocd + type: Opaque + `) if err := c.Execute(&repoSecrets, creds); err != nil { log.Panicf("error executing golang template for gitops repository template %s", err) } @@ -448,6 +451,10 @@ func ChangeRegistryToGitLab(dryRun bool) { log.Panicf("error creating argocd repository connection secret %s", err) } + // curl -X 'DELETE' \ + // 'https://$ARGO_ADDRESS/api/v1/applications/registry?cascade=false' \ + // -H 'accept: application/json' + _, _, err = pkg.ExecShellReturnStrings(config.KubectlClientPath, "--kubeconfig", config.KubeConfigPath, "-n", "argocd", "apply", "-f", fmt.Sprintf("%s/gitops/components/gitlab/argocd-adopts-gitlab.yaml", config.K1FolderPath)) if err != nil { log.Panicf("failed to call execute kubectl apply of argocd patch to adopt gitlab: %s", err) @@ -538,6 +545,8 @@ func PushGitRepo(dryRun bool, config *configs.Config, gitOrigin, repoName string os.RemoveAll(repoDir + "/terraform/gitlab/.terraform") os.RemoveAll(repoDir + "/terraform/vault/.terraform") os.Remove(repoDir + "/terraform/base/.terraform.lock.hcl") + os.Remove(repoDir + "/terraform/vault/.terraform.lock.hcl") + os.Remove(repoDir + "/terraform/users/.terraform.lock.hcl") os.Remove(repoDir + "/terraform/gitlab/.terraform.lock.hcl") CommitToRepo(repo, repoName) auth, _ := pkg.PublicKey() @@ -555,12 +564,53 @@ func PushGitRepo(dryRun bool, config *configs.Config, gitOrigin, repoName string } if gitOrigin == "gitlab" { + registryFileContent := `apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: argocd-components + namespace: argocd + annotations: + argocd.argoproj.io/sync-wave: "100" +spec: + project: default + source: + repoURL: ssh://soft-serve.soft-serve.svc.cluster.local:22/gitops + path: components/argocd + targetRevision: HEAD + destination: + server: https://kubernetes.default.svc + namespace: argocd + syncPolicy: + automated: + prune: true + selfHeal: true + syncOptions: + - CreateNamespace=true + retry: + limit: 5 + backoff: + duration: 5s + maxDuration: 5m0s + factor: 2` + file, err := os.Create(fmt.Sprintf("%s/gitops/registry/argocd.yaml", config.K1FolderPath)) + if err != nil { + log.Println(err) + } + _, err = file.WriteString(registryFileContent) + if err != nil { + log.Println(err) + } + file.Close() + pkg.Detokenize(repoDir) os.RemoveAll(repoDir + "/terraform/base/.terraform") os.RemoveAll(repoDir + "/terraform/gitlab/.terraform") os.RemoveAll(repoDir + "/terraform/vault/.terraform") os.Remove(repoDir + "/terraform/base/.terraform.lock.hcl") + os.Remove(repoDir + "/terraform/vault/.terraform.lock.hcl") + os.Remove(repoDir + "/terraform/users/.terraform.lock.hcl") os.Remove(repoDir + "/terraform/gitlab/.terraform.lock.hcl") + CommitToRepo(repo, repoName) auth := &gitHttp.BasicAuth{ Username: "root", diff --git a/internal/k8s/kubernetes.go b/internal/k8s/kubernetes.go index f3f5c77b9..fc395aa9b 100644 --- a/internal/k8s/kubernetes.go +++ b/internal/k8s/kubernetes.go @@ -8,13 +8,14 @@ import ( "context" "encoding/json" "fmt" + "log" + "time" + "github.com/kubefirst/kubefirst/internal/argocd" "github.com/kubefirst/kubefirst/pkg" "github.com/spf13/viper" metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" coreV1Types "k8s.io/client-go/kubernetes/typed/core/v1" - "log" - "time" ) var vaultRootToken string @@ -24,12 +25,13 @@ var gitlabToolboxPodName string var GitlabSecretClient coreV1Types.SecretInterface var VaultSecretClient coreV1Types.SecretInterface var ArgocdSecretClient coreV1Types.SecretInterface -var GitlabPodsClient coreV1Types.PodInterface -func GetPodNameByLabel(gitlabPodsClient coreV1Types.PodInterface, label string) string { - pods, err := gitlabPodsClient.List(context.TODO(), metaV1.ListOptions{LabelSelector: fmt.Sprintf("app=%s", label)}) +// var GitlabPodsClient coreV1Types.PodInterface + +func GetPodNameByLabel(podsClient coreV1Types.PodInterface, label string) string { + pods, err := podsClient.List(context.TODO(), metaV1.ListOptions{LabelSelector: label}) if err != nil { - fmt.Println(err) + log.Println(err) } gitlabToolboxPodName = pods.Items[0].Name @@ -37,6 +39,21 @@ func GetPodNameByLabel(gitlabPodsClient coreV1Types.PodInterface, label string) return gitlabToolboxPodName } +func DeletePodByName(podsClient coreV1Types.PodInterface, podName string) { + err := podsClient.Delete(context.TODO(), podName, metaV1.DeleteOptions{}) + if err != nil { + log.Println(err) + } +} + +// func CreateRepoSecret() { + +// } + +// func CreateCredentialsTemplateSecret() { + +// } + func getVaultRootToken(vaultSecretClient coreV1Types.SecretInterface) string { name := "vault-unseal-keys" log.Printf("Reading secret %s\n", name) diff --git a/internal/vault/vault.go b/internal/vault/vault.go index 8cdd677b6..510761af5 100644 --- a/internal/vault/vault.go +++ b/internal/vault/vault.go @@ -187,7 +187,7 @@ func AddGitlabOidcApplications(dryRun bool) { func addVaultSecret(secretPath string, secretData map[string]interface{}) { config := vault.DefaultConfig() - config.Address = fmt.Sprintf("https://vault.%s", viper.GetString("aws.hostedzonename")) + config.Address = viper.GetString("vault.local.service") client, err := vault.NewClient(config) if err != nil { diff --git a/pkg/helpers.go b/pkg/helpers.go index 762b7703c..a5b8dfd3b 100644 --- a/pkg/helpers.go +++ b/pkg/helpers.go @@ -3,13 +3,14 @@ package pkg import ( "errors" "fmt" - "github.com/kubefirst/kubefirst/configs" "io/ioutil" "log" "os" "path/filepath" "strings" + "github.com/kubefirst/kubefirst/configs" + "github.com/spf13/viper" ) @@ -30,7 +31,7 @@ func DetokenizeDirectory(path string, fi os.FileInfo, err error) error { return nil // } - if strings.Contains(path, ".gitClient") || strings.Contains(path, ".terraform") { + if strings.Contains(path, ".gitClient") || strings.Contains(path, ".terraform") || strings.Contains(path, ".git/") { return nil } @@ -68,6 +69,7 @@ func DetokenizeDirectory(path string, fi os.FileInfo, err error) error { awsAccountId := viper.GetString("aws.accountid") kmsKeyId := viper.GetString("vault.kmskeyid") clusterName := viper.GetString("cluster-name") + argocdOidcClientId := viper.GetString(("gitlab.oidc.argocd.applicationid")) newContents = strings.Replace(newContents, "", strings.TrimSpace(botPublicKey), -1) newContents = strings.Replace(newContents, "", bucketStateStore, -1) @@ -84,6 +86,10 @@ func DetokenizeDirectory(path string, fi os.FileInfo, err error) error { } newContents = strings.Replace(newContents, "", clusterName, -1) + if argocdOidcClientId != "" { + newContents = strings.Replace(newContents, "", argocdOidcClientId, -1) + } + if viper.GetBool("create.terraformapplied.gitlab") { newContents = strings.Replace(newContents, "", hostedZoneName, -1) newContents = strings.Replace(newContents, "", region, -1) diff --git a/pkg/keys.go b/pkg/keys.go index 21c4caf46..3dbae86aa 100644 --- a/pkg/keys.go +++ b/pkg/keys.go @@ -32,34 +32,6 @@ func CreateSshKeyPair() { privateKey := viper.GetString("botprivatekey") var argocdInitValuesYaml = []byte(fmt.Sprintf(` -server: - additionalApplications: - - name: registry - namespace: argocd - additionalLabels: {} - additionalAnnotations: {} - finalizers: - - resources-finalizer.argocd.argoproj.io - project: default - source: - repoURL: ssh://soft-serve.soft-serve.svc.cluster.local:22/gitops - targetRevision: HEAD - path: registry - destination: - server: https://kubernetes.default.svc - namespace: argocd - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true - retry: - limit: 5 - backoff: - duration: 5s - maxDuration: 5m0s - factor: 2 configs: repositories: soft-serve-gitops: