diff --git a/cmd/aws/command.go b/cmd/aws/command.go index 0ecad9d26..6a384085b 100644 --- a/cmd/aws/command.go +++ b/cmd/aws/command.go @@ -35,6 +35,7 @@ var ( ecrFlag bool nodeTypeFlag string nodeCountFlag string + installCatalogApps string // RootCredentials copyArgoCDPasswordToClipboardFlag bool @@ -98,6 +99,7 @@ func Create() *cobra.Command { createCmd.Flags().StringVar(&gitlabGroupFlag, "gitlab-group", "", "the GitLab group for the new gitops and metaphor projects - required if using gitlab") createCmd.Flags().StringVar(&gitopsTemplateBranchFlag, "gitops-template-branch", "", "the branch to clone for the gitops-template repository") createCmd.Flags().StringVar(&gitopsTemplateURLFlag, "gitops-template-url", "https://github.com/kubefirst/gitops-template.git", "the fully qualified url to the gitops-template repository to clone") + createCmd.Flags().StringVar(&installCatalogApps, "install-catalog-apps", "", "comma seperated values to install after provision") createCmd.Flags().BoolVar(&useTelemetryFlag, "use-telemetry", true, "whether to emit telemetry") createCmd.Flags().BoolVar(&ecrFlag, "ecr", false, "whether or not to use ecr vs the git provider") diff --git a/cmd/aws/create.go b/cmd/aws/create.go index d2c25db77..2d53f4cd9 100644 --- a/cmd/aws/create.go +++ b/cmd/aws/create.go @@ -11,6 +11,7 @@ import ( "os" "github.com/aws/aws-sdk-go/aws" + "github.com/kubefirst/kubefirst/internal/catalog" "github.com/kubefirst/kubefirst/internal/cluster" "github.com/kubefirst/kubefirst/internal/gitShim" "github.com/kubefirst/kubefirst/internal/launch" @@ -34,6 +35,11 @@ func createAws(cmd *cobra.Command, args []string) error { progress.DisplayLogHints(40) + isValid, catalogApps, err := catalog.ValidateCatalogApps(cliFlags.InstallCatalogApps) + if !isValid { + return err + } + err = ValidateProvidedFlags(cliFlags.GitProvider) if err != nil { progress.Error(err.Error()) @@ -112,7 +118,7 @@ func createAws(cmd *cobra.Command, args []string) error { progress.Error("unable to start kubefirst api") } - provision.CreateMgmtCluster(gitAuth, cliFlags) + provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps) return nil } diff --git a/cmd/civo/command.go b/cmd/civo/command.go index 572977e26..db6608863 100644 --- a/cmd/civo/command.go +++ b/cmd/civo/command.go @@ -34,6 +34,7 @@ var ( useTelemetryFlag bool nodeTypeFlag string nodeCountFlag string + installCatalogApps string // RootCredentials copyArgoCDPasswordToClipboardFlag bool @@ -109,6 +110,7 @@ func Create() *cobra.Command { createCmd.Flags().StringVar(&gitlabGroupFlag, "gitlab-group", "", "the GitLab group for the new gitops and metaphor projects - required if using gitlab") createCmd.Flags().StringVar(&gitopsTemplateBranchFlag, "gitops-template-branch", "", "the branch to clone for the gitops-template repository") createCmd.Flags().StringVar(&gitopsTemplateURLFlag, "gitops-template-url", "https://github.com/kubefirst/gitops-template.git", "the fully qualified url to the gitops-template repository to clone") + createCmd.Flags().StringVar(&installCatalogApps, "install-catalog-apps", "", "comma seperated values to install after provision") createCmd.Flags().BoolVar(&useTelemetryFlag, "use-telemetry", true, "whether to emit telemetry") return createCmd diff --git a/cmd/civo/create.go b/cmd/civo/create.go index 2469ec692..53864b535 100644 --- a/cmd/civo/create.go +++ b/cmd/civo/create.go @@ -10,6 +10,7 @@ import ( "fmt" "os" + "github.com/kubefirst/kubefirst/internal/catalog" "github.com/kubefirst/kubefirst/internal/cluster" "github.com/kubefirst/kubefirst/internal/gitShim" "github.com/kubefirst/kubefirst/internal/launch" @@ -32,6 +33,11 @@ func createCivo(cmd *cobra.Command, args []string) error { progress.DisplayLogHints(15) + isValid, catalogApps, err := catalog.ValidateCatalogApps(cliFlags.InstallCatalogApps) + if !isValid { + return err + } + err = ValidateProvidedFlags(cliFlags.GitProvider) if err != nil { progress.Error(err.Error()) @@ -39,12 +45,6 @@ func createCivo(cmd *cobra.Command, args []string) error { } // If cluster setup is complete, return - clusterSetupComplete := viper.GetBool("kubefirst-checks.cluster-install-complete") - if clusterSetupComplete { - err = fmt.Errorf("this cluster install process has already completed successfully") - progress.Error(err.Error()) - return nil - } utilities.CreateK1ClusterDirectory(clusterNameFlag) @@ -88,7 +88,7 @@ func createCivo(cmd *cobra.Command, args []string) error { progress.Error("unable to start kubefirst api") } - provision.CreateMgmtCluster(gitAuth, cliFlags) + provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps) return nil } diff --git a/cmd/digitalocean/command.go b/cmd/digitalocean/command.go index 239cb30bd..3ebd429f6 100644 --- a/cmd/digitalocean/command.go +++ b/cmd/digitalocean/command.go @@ -35,6 +35,7 @@ var ( useTelemetryFlag bool nodeTypeFlag string nodeCountFlag string + installCatalogApps string // RootCredentials copyArgoCDPasswordToClipboardFlag bool @@ -102,6 +103,7 @@ func Create() *cobra.Command { createCmd.Flags().StringVar(&gitlabGroupFlag, "gitlab-group", "", "the GitLab group for the new gitops and metaphor projects - required if using gitlab") createCmd.Flags().StringVar(&gitopsTemplateBranchFlag, "gitops-template-branch", "", "the branch to clone for the gitops-template repository") createCmd.Flags().StringVar(&gitopsTemplateURLFlag, "gitops-template-url", "https://github.com/kubefirst/gitops-template.git", "the fully qualified url to the gitops-template repository to clone") + createCmd.Flags().StringVar(&installCatalogApps, "install-catalog-apps", "", "comma seperated values to install after provision") createCmd.Flags().BoolVar(&useTelemetryFlag, "use-telemetry", true, "whether to emit telemetry") return createCmd diff --git a/cmd/digitalocean/create.go b/cmd/digitalocean/create.go index af54c20c2..33e0f38ac 100644 --- a/cmd/digitalocean/create.go +++ b/cmd/digitalocean/create.go @@ -12,6 +12,7 @@ import ( "github.com/rs/zerolog/log" + "github.com/kubefirst/kubefirst/internal/catalog" "github.com/kubefirst/kubefirst/internal/cluster" "github.com/kubefirst/kubefirst/internal/gitShim" "github.com/kubefirst/kubefirst/internal/launch" @@ -33,6 +34,11 @@ func createDigitalocean(cmd *cobra.Command, args []string) error { progress.DisplayLogHints(20) + isValid, catalogApps, err := catalog.ValidateCatalogApps(cliFlags.InstallCatalogApps) + if !isValid { + return err + } + err = ValidateProvidedFlags(cliFlags.GitProvider) if err != nil { progress.Error(err.Error()) @@ -89,7 +95,7 @@ func createDigitalocean(cmd *cobra.Command, args []string) error { progress.Error("unable to start kubefirst api") } - provision.CreateMgmtCluster(gitAuth, cliFlags) + provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps) return nil } diff --git a/cmd/google/command.go b/cmd/google/command.go index 3135ded17..f447b49b6 100644 --- a/cmd/google/command.go +++ b/cmd/google/command.go @@ -36,6 +36,7 @@ var ( forceDestroyFlag bool nodeTypeFlag string nodeCountFlag string + installCatalogApps string // RootCredentials copyArgoCDPasswordToClipboardFlag bool @@ -106,6 +107,7 @@ func Create() *cobra.Command { createCmd.Flags().StringVar(&gitlabGroupFlag, "gitlab-group", "", "the GitLab group for the new gitops and metaphor projects - required if using gitlab") createCmd.Flags().StringVar(&gitopsTemplateBranchFlag, "gitops-template-branch", "", "the branch to clone for the gitops-template repository") createCmd.Flags().StringVar(&gitopsTemplateURLFlag, "gitops-template-url", "https://github.com/kubefirst/gitops-template.git", "the fully qualified url to the gitops-template repository to clone") + createCmd.Flags().StringVar(&installCatalogApps, "install-catalog-apps", "", "comma seperated values to install after provision") createCmd.Flags().BoolVar(&useTelemetryFlag, "use-telemetry", true, "whether to emit telemetry") createCmd.Flags().BoolVar(&forceDestroyFlag, "force-destroy", false, "allows force destruction on objects (helpful for test environments, defaults to false)") return createCmd diff --git a/cmd/google/create.go b/cmd/google/create.go index c979db231..87f393c10 100644 --- a/cmd/google/create.go +++ b/cmd/google/create.go @@ -12,6 +12,7 @@ import ( "github.com/rs/zerolog/log" + "github.com/kubefirst/kubefirst/internal/catalog" "github.com/kubefirst/kubefirst/internal/cluster" "github.com/kubefirst/kubefirst/internal/gitShim" "github.com/kubefirst/kubefirst/internal/launch" @@ -34,6 +35,11 @@ func createGoogle(cmd *cobra.Command, args []string) error { progress.DisplayLogHints(20) + isValid, catalogApps, err := catalog.ValidateCatalogApps(cliFlags.InstallCatalogApps) + if !isValid { + return err + } + err = ValidateProvidedFlags(cliFlags.GitProvider) if err != nil { progress.Error(err.Error()) @@ -87,7 +93,7 @@ func createGoogle(cmd *cobra.Command, args []string) error { progress.Error("unable to start kubefirst api") } - provision.CreateMgmtCluster(gitAuth, cliFlags) + provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps) return nil } diff --git a/cmd/k3d/command.go b/cmd/k3d/command.go index 0658b967b..51f2c65e7 100644 --- a/cmd/k3d/command.go +++ b/cmd/k3d/command.go @@ -29,6 +29,7 @@ var ( gitopsTemplateURLFlag string gitopsTemplateBranchFlag string useTelemetryFlag bool + installCatalogApps string // RootCredentials copyArgoCDPasswordToClipboardFlag bool @@ -95,6 +96,7 @@ func Create() *cobra.Command { createCmd.Flags().StringVar(&gitlabGroupFlag, "gitlab-group", "", "the GitLab group for the new gitops and metaphor projects - required if using gitlab") createCmd.Flags().StringVar(&gitopsTemplateBranchFlag, "gitops-template-branch", "", "the branch to clone for the gitops-template repository") createCmd.Flags().StringVar(&gitopsTemplateURLFlag, "gitops-template-url", "https://github.com/kubefirst/gitops-template.git", "the fully qualified url to the gitops-template repository to clone") + createCmd.Flags().StringVar(&installCatalogApps, "install-catalog-apps", "", "comma seperated values of catalog apps to install after provision") createCmd.Flags().BoolVar(&useTelemetryFlag, "use-telemetry", true, "whether to emit telemetry") return createCmd diff --git a/cmd/k3d/create.go b/cmd/k3d/create.go index 955a52463..fd7bb5523 100644 --- a/cmd/k3d/create.go +++ b/cmd/k3d/create.go @@ -26,6 +26,7 @@ import ( "github.com/kubefirst/kubefirst-api/pkg/handlers" "github.com/kubefirst/kubefirst-api/pkg/reports" "github.com/kubefirst/kubefirst-api/pkg/wrappers" + "github.com/kubefirst/kubefirst/internal/catalog" "github.com/kubefirst/kubefirst/internal/gitShim" "github.com/kubefirst/kubefirst/internal/segment" "github.com/kubefirst/kubefirst/internal/utilities" @@ -105,6 +106,11 @@ func runK3d(cmd *cobra.Command, args []string) error { return err } + installCatalogAppsFlag, err := cmd.Flags().GetString("install-catalog-apps") + if err != nil { + return err + } + useTelemetryFlag, err := cmd.Flags().GetBool("use-telemetry") if err != nil { return err @@ -119,6 +125,11 @@ func runK3d(cmd *cobra.Command, args []string) error { utilities.CreateK1ClusterDirectory(clusterNameFlag) helpers.DisplayLogHints() + isValid, catalogApps, err := catalog.ValidateCatalogApps(installCatalogAppsFlag) + if !isValid { + return err + } + switch gitProviderFlag { case "github": key, err := internalssh.GetHostKey("github.com") @@ -1347,7 +1358,7 @@ func runK3d(cmd *cobra.Command, args []string) error { // Set flags used to track status of active options helpers.SetClusterStatusFlags(k3d.CloudProvider, config.GitProvider) - cluster := utilities.CreateClusterRecordFromRaw(useTelemetryFlag, cGitOwner, cGitUser, cGitToken, cGitlabOwnerGroupID, gitopsTemplateURLFlag, gitopsTemplateBranchFlag) + cluster := utilities.CreateClusterRecordFromRaw(useTelemetryFlag, cGitOwner, cGitUser, cGitToken, cGitlabOwnerGroupID, gitopsTemplateURLFlag, gitopsTemplateBranchFlag, catalogApps) err = utilities.ExportCluster(cluster, kcfg) if err != nil { diff --git a/cmd/vultr/command.go b/cmd/vultr/command.go index a0227d9bc..1f81e71c4 100644 --- a/cmd/vultr/command.go +++ b/cmd/vultr/command.go @@ -34,6 +34,7 @@ var ( useTelemetryFlag bool nodeTypeFlag string nodeCountFlag string + installCatalogApps string // RootCredentials copyArgoCDPasswordToClipboardFlag bool @@ -102,6 +103,7 @@ func Create() *cobra.Command { createCmd.Flags().StringVar(&gitlabGroupFlag, "gitlab-group", "", "the GitLab group for the new gitops and metaphor projects - required if using gitlab") createCmd.Flags().StringVar(&gitopsTemplateBranchFlag, "gitops-template-branch", "", "the branch to clone for the gitops-template repository") createCmd.Flags().StringVar(&gitopsTemplateURLFlag, "gitops-template-url", "https://github.com/kubefirst/gitops-template.git", "the fully qualified url to the gitops-template repository to clone") + createCmd.Flags().StringVar(&installCatalogApps, "install-catalog-apps", "", "comma seperated values to install after provision") createCmd.Flags().BoolVar(&useTelemetryFlag, "use-telemetry", true, "whether to emit telemetry") return createCmd diff --git a/cmd/vultr/create.go b/cmd/vultr/create.go index 7643480aa..0b3a5c2b9 100644 --- a/cmd/vultr/create.go +++ b/cmd/vultr/create.go @@ -10,6 +10,7 @@ import ( "fmt" "os" + "github.com/kubefirst/kubefirst/internal/catalog" "github.com/kubefirst/kubefirst/internal/cluster" "github.com/kubefirst/kubefirst/internal/gitShim" "github.com/kubefirst/kubefirst/internal/launch" @@ -33,6 +34,11 @@ func createVultr(cmd *cobra.Command, args []string) error { progress.DisplayLogHints(15) + isValid, catalogApps, err := catalog.ValidateCatalogApps(cliFlags.InstallCatalogApps) + if !isValid { + return err + } + err = ValidateProvidedFlags(cliFlags.GitProvider) if err != nil { progress.Error(err.Error()) @@ -89,7 +95,7 @@ func createVultr(cmd *cobra.Command, args []string) error { progress.Error("unable to start kubefirst api") } - provision.CreateMgmtCluster(gitAuth, cliFlags) + provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps) return nil } diff --git a/go.mod b/go.mod index b5b8dcc5d..db8769bfb 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/dustin/go-humanize v1.0.1 github.com/go-git/go-git/v5 v5.6.1 github.com/hashicorp/vault/api v1.9.0 - github.com/kubefirst/kubefirst-api v0.1.9 + github.com/kubefirst/kubefirst-api v0.1.11 github.com/kubefirst/metrics-client v0.3.0 github.com/kubefirst/runtime v0.4.0 github.com/nxadm/tail v1.4.8 @@ -222,6 +222,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-cmp v0.5.9 // indirect + github.com/google/go-github/v52 v52.0.0 github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect diff --git a/go.sum b/go.sum index 92ff137d6..589a5632e 100644 --- a/go.sum +++ b/go.sum @@ -532,6 +532,8 @@ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github/v45 v45.2.0 h1:5oRLszbrkvxDDqBCNj2hjDZMKmvexaZ1xw/FCD+K3FI= github.com/google/go-github/v45 v45.2.0/go.mod h1:FObaZJEDSTa/WGCzZ2Z3eoCDXWJKMenWWTrd8jrta28= +github.com/google/go-github/v52 v52.0.0 h1:uyGWOY+jMQ8GVGSX8dkSwCzlehU3WfdxQ7GweO/JP7M= +github.com/google/go-github/v52 v52.0.0/go.mod h1:WJV6VEEUPuMo5pXqqa2ZCZEdbQqua4zAk2MZTIo+m+4= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -719,8 +721,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kubefirst/kubefirst-api v0.1.9 h1:HCPO2usOW64NS3B/zRL84qfADBNFfcbeKd3yWdbvf8I= -github.com/kubefirst/kubefirst-api v0.1.9/go.mod h1:hik4k99JDLrxxh25jYt6eYxYPhIodX1yxb4gh5tfJ3U= +github.com/kubefirst/kubefirst-api v0.1.11 h1:nRq0y40StwBCL/YwjzHXAURN+/SA63g6pzvQjAxgdOk= +github.com/kubefirst/kubefirst-api v0.1.11/go.mod h1:pAcgIJVYRvRldNMcdIbhcIuHeM+euNlfKVEd/JNS6c8= github.com/kubefirst/metrics-client v0.3.0 h1:zCug82pEzeWhHhpeYQvdhytRNDxrLxX18dPQ5PSxY3s= github.com/kubefirst/metrics-client v0.3.0/go.mod h1:GR7wsMcyYhd+EU67PeuMCBYFE6OJ7P/j5OI5BLOoRMc= github.com/kubefirst/runtime v0.4.0 h1:BQzls1f6l5kV0uDcjp71GwM1x6xl3czX0jGkUu3e2AQ= diff --git a/internal/catalog/catalog.go b/internal/catalog/catalog.go new file mode 100644 index 000000000..f6d0c3cc7 --- /dev/null +++ b/internal/catalog/catalog.go @@ -0,0 +1,173 @@ +/* +Copyright (C) 2021-2023, Kubefirst + +This program is licensed under MIT. +See the LICENSE file for more details. +*/ +package catalog + +import ( + "context" + "fmt" + "io" + "os" + "strings" + + git "github.com/google/go-github/v52/github" + + apiTypes "github.com/kubefirst/kubefirst-api/pkg/types" + + "github.com/rs/zerolog/log" + "gopkg.in/yaml.v2" +) + +const ( + KubefirstGitHubOrganization = "kubefirst" + KubefirstGitopsCatalogRepository = "gitops-catalog" + basePath = "/" +) + +type GitHubClient struct { + Client *git.Client +} + +// NewGitHub instantiates an unauthenticated GitHub client +func NewGitHub() *git.Client { + return git.NewClient(nil) +} + +func ReadActiveApplications() (apiTypes.GitopsCatalogApps, error) { + gh := GitHubClient{ + Client: NewGitHub(), + } + + activeContent, err := gh.ReadGitopsCatalogRepoContents() + if err != nil { + return apiTypes.GitopsCatalogApps{}, fmt.Errorf("error retrieving gitops catalog repository content: %s", err) + } + + index, err := gh.ReadGitopsCatalogIndex(activeContent) + if err != nil { + return apiTypes.GitopsCatalogApps{}, fmt.Errorf("error retrieving gitops catalog index content: %s", err) + } + + var out apiTypes.GitopsCatalogApps + + err = yaml.Unmarshal(index, &out) + if err != nil { + return apiTypes.GitopsCatalogApps{}, fmt.Errorf("error retrieving gitops catalog applications: %s", err) + } + + return out, nil +} + +func ValidateCatalogApps(catalogApps string) (bool, []apiTypes.GitopsCatalogApp, error) { + items := strings.Split(catalogApps, ",") + + gitopsCatalogapps := []apiTypes.GitopsCatalogApp{} + if catalogApps == "" { + return true, gitopsCatalogapps, nil + } + + apps, err := ReadActiveApplications() + if err != nil { + log.Error().Msgf(fmt.Sprintf("Error getting gitops catalag applications: %s", err)) + return false, gitopsCatalogapps, err + } + + for _, app := range items { + found := false + for _, catalogApp := range apps.Apps { + if app == catalogApp.Name { + found = true + + if catalogApp.SecretKeys != nil { + for _, secret := range catalogApp.SecretKeys { + secretValue := os.Getenv(secret.Env) + + if secretValue == "" { + return false, gitopsCatalogapps, fmt.Errorf("your %s environment variable is not set for %s catalog application. Please set and try again", secret.Env, app) + } + + secret.Value = secretValue + } + } + + if catalogApp.ConfigKeys != nil { + for _, config := range catalogApp.ConfigKeys { + configValue := os.Getenv(config.Env) + if configValue == "" { + return false, gitopsCatalogapps, fmt.Errorf("your %s environment variable is not set for %s catalog application. Please set and try again", config.Env, app) + } + config.Value = configValue + } + } + + gitopsCatalogapps = append(gitopsCatalogapps, catalogApp) + + break + } + } + if !found { + return false, gitopsCatalogapps, fmt.Errorf(fmt.Sprintf("catalag app is not supported: %s", app)) + } + } + + return true, gitopsCatalogapps, nil +} + +func (gh *GitHubClient) ReadGitopsCatalogRepoContents() ([]*git.RepositoryContent, error) { + _, directoryContent, _, err := gh.Client.Repositories.GetContents( + context.Background(), + KubefirstGitHubOrganization, + KubefirstGitopsCatalogRepository, + basePath, + nil, + ) + if err != nil { + return nil, err + } + + return directoryContent, nil +} + +// ReadGitopsCatalogIndex reads the gitops catalog repository index +func (gh *GitHubClient) ReadGitopsCatalogIndex(contents []*git.RepositoryContent) ([]byte, error) { + for _, content := range contents { + switch *content.Type { + case "file": + switch *content.Name { + case "index.yaml": + b, err := gh.readFileContents(content) + if err != nil { + return b, err + } + return b, nil + } + } + } + + return []byte{}, fmt.Errorf("index.yaml not found in gitops catalog repository") +} + +// readFileContents parses the contents of a file in a GitHub repository +func (gh *GitHubClient) readFileContents(content *git.RepositoryContent) ([]byte, error) { + rc, _, err := gh.Client.Repositories.DownloadContents( + context.Background(), + KubefirstGitHubOrganization, + KubefirstGitopsCatalogRepository, + *content.Path, + nil, + ) + if err != nil { + return []byte{}, err + } + defer rc.Close() + + b, err := io.ReadAll(rc) + if err != nil { + return []byte{}, err + } + + return b, nil +} diff --git a/internal/launch/constants.go b/internal/launch/constants.go index f6fa66de4..3c682cf0b 100644 --- a/internal/launch/constants.go +++ b/internal/launch/constants.go @@ -11,7 +11,7 @@ const ( helmChartName = "kubefirst" helmChartRepoName = "kubefirst" helmChartRepoURL = "https://charts.kubefirst.com" - helmChartVersion = "2.3.8-rc44" + helmChartVersion = "2.3.8-rc60" namespace = "kubefirst" secretName = "kubefirst-initial-secrets" ) diff --git a/internal/progress/message.go b/internal/progress/message.go index 1e9e12dc7..ffb33b524 100644 --- a/internal/progress/message.go +++ b/internal/progress/message.go @@ -195,7 +195,7 @@ func Error(message string) { Progress.Send(renderedMessage) } -func StartProvisioning(clusterName string, estimatedTime int) { +func StartProvisioning(clusterName string) { provisioningMessage := startProvision{ clusterName: clusterName, } diff --git a/internal/provision/provision.go b/internal/provision/provision.go index 5256818a9..0e86a315c 100644 --- a/internal/provision/provision.go +++ b/internal/provision/provision.go @@ -7,6 +7,7 @@ See the LICENSE file for more details. package provision import ( + apiTypes "github.com/kubefirst/kubefirst-api/pkg/types" runtimeTypes "github.com/kubefirst/kubefirst-api/pkg/types" "github.com/kubefirst/kubefirst/internal/cluster" "github.com/kubefirst/kubefirst/internal/progress" @@ -15,10 +16,11 @@ import ( "github.com/rs/zerolog/log" ) -func CreateMgmtCluster(gitAuth runtimeTypes.GitAuth, cliFlags types.CliFlags) { +func CreateMgmtCluster(gitAuth runtimeTypes.GitAuth, cliFlags types.CliFlags, catalogApps []apiTypes.GitopsCatalogApp) { clusterRecord := utilities.CreateClusterDefinitionRecordFromRaw( gitAuth, cliFlags, + catalogApps, ) clusterCreated, err := cluster.GetCluster(clusterRecord.ClusterName) @@ -38,5 +40,5 @@ func CreateMgmtCluster(gitAuth runtimeTypes.GitAuth, cliFlags types.CliFlags) { cluster.CreateCluster(clusterRecord) } - progress.StartProvisioning(clusterRecord.ClusterName, 35) + progress.StartProvisioning(clusterRecord.ClusterName) } diff --git a/internal/types/flags.go b/internal/types/flags.go index c5516c7f9..e4910b57d 100644 --- a/internal/types/flags.go +++ b/internal/types/flags.go @@ -27,4 +27,5 @@ type CliFlags struct { Ecr bool NodeType string NodeCount string + InstallCatalogApps string } diff --git a/internal/types/proxy.go b/internal/types/proxy.go index c3ba36eda..454808c7e 100644 --- a/internal/types/proxy.go +++ b/internal/types/proxy.go @@ -6,11 +6,13 @@ See the LICENSE file for more details. */ package types -import "github.com/kubefirst/kubefirst-api/pkg/types" +import ( + apiTypes "github.com/kubefirst/kubefirst-api/pkg/types" +) type ProxyCreateClusterRequest struct { - Body types.ClusterDefinition `bson:"body" json:"body"` - Url string `bson:"url" json:"url"` + Body apiTypes.ClusterDefinition `bson:"body" json:"body"` + Url string `bson:"url" json:"url"` } type ProxyResetClusterRequest struct { diff --git a/internal/utilities/flags.go b/internal/utilities/flags.go index 8b4439dae..20afd4c72 100644 --- a/internal/utilities/flags.go +++ b/internal/utilities/flags.go @@ -104,6 +104,12 @@ func GetFlags(cmd *cobra.Command, cloudProvider string) (types.CliFlags, error) return cliFlags, err } + installCatalogAppsFlag, err := cmd.Flags().GetString("install-catalog-apps") + if err != nil { + progress.Error(err.Error()) + return cliFlags, err + } + nodeCountFlag, err := cmd.Flags().GetString("node-count") if err != nil { progress.Error(err.Error()) @@ -146,6 +152,7 @@ func GetFlags(cmd *cobra.Command, cloudProvider string) (types.CliFlags, error) cliFlags.CloudProvider = cloudProvider cliFlags.NodeType = nodeTypeFlag cliFlags.NodeCount = nodeCountFlag + cliFlags.InstallCatalogApps = installCatalogAppsFlag viper.Set("flags.alerts-email", cliFlags.AlertsEmail) viper.Set("flags.cluster-name", cliFlags.ClusterName) diff --git a/internal/utilities/utilities.go b/internal/utilities/utilities.go index 320b581ca..8412ab5b8 100644 --- a/internal/utilities/utilities.go +++ b/internal/utilities/utilities.go @@ -49,7 +49,16 @@ const ( exportFilePath = "/tmp/api/cluster/export" ) -func CreateClusterRecordFromRaw(useTelemetry bool, gitOwner string, gitUser string, gitToken string, gitlabOwnerGroupID int, gitopsTemplateURL string, gitopsTemplateBranch string) apiTypes.Cluster { +func CreateClusterRecordFromRaw( + useTelemetry bool, + gitOwner string, + gitUser string, + gitToken string, + gitlabOwnerGroupID int, + gitopsTemplateURL string, + gitopsTemplateBranch string, + catalogApps []apiTypes.GitopsCatalogApp, +) apiTypes.Cluster { cloudProvider := viper.GetString("kubefirst.cloud-provider") domainName := viper.GetString("flags.domain-name") gitProvider := viper.GetString("flags.git-provider") @@ -60,29 +69,30 @@ func CreateClusterRecordFromRaw(useTelemetry bool, gitOwner string, gitUser stri } cl := apiTypes.Cluster{ - ID: primitive.NewObjectID(), - CreationTimestamp: fmt.Sprintf("%v", time.Now().UTC()), - UseTelemetry: useTelemetry, - Status: "provisioned", - AlertsEmail: viper.GetString("flags.alerts-email"), - ClusterName: viper.GetString("flags.cluster-name"), - CloudProvider: cloudProvider, - CloudRegion: viper.GetString("flags.cloud-region"), - DomainName: domainName, - ClusterID: viper.GetString("kubefirst.cluster-id"), - ClusterType: "mgmt", - GitopsTemplateURL: gitopsTemplateURL, - GitopsTemplateBranch: gitopsTemplateBranch, - GitProvider: gitProvider, - GitHost: fmt.Sprintf("%s.com", gitProvider), - GitProtocol: viper.GetString("flags.git-protocol"), - DnsProvider: viper.GetString("flags.dns-provider"), - GitlabOwnerGroupID: gitlabOwnerGroupID, - AtlantisWebhookSecret: viper.GetString("secrets.atlantis-webhook"), - AtlantisWebhookURL: fmt.Sprintf("https://atlantis.%s/events", domainName), - KubefirstTeam: kubefirstTeam, - ArgoCDAuthToken: viper.GetString("components.argocd.auth-token"), - ArgoCDPassword: viper.GetString("components.argocd.password"), + ID: primitive.NewObjectID(), + CreationTimestamp: fmt.Sprintf("%v", time.Now().UTC()), + UseTelemetry: useTelemetry, + Status: "provisioned", + AlertsEmail: viper.GetString("flags.alerts-email"), + ClusterName: viper.GetString("flags.cluster-name"), + CloudProvider: cloudProvider, + CloudRegion: viper.GetString("flags.cloud-region"), + DomainName: domainName, + ClusterID: viper.GetString("kubefirst.cluster-id"), + ClusterType: "mgmt", + GitopsTemplateURL: gitopsTemplateURL, + GitopsTemplateBranch: gitopsTemplateBranch, + GitProvider: gitProvider, + GitHost: fmt.Sprintf("%s.com", gitProvider), + GitProtocol: viper.GetString("flags.git-protocol"), + DnsProvider: viper.GetString("flags.dns-provider"), + GitlabOwnerGroupID: gitlabOwnerGroupID, + AtlantisWebhookSecret: viper.GetString("secrets.atlantis-webhook"), + AtlantisWebhookURL: fmt.Sprintf("https://atlantis.%s/events", domainName), + KubefirstTeam: kubefirstTeam, + ArgoCDAuthToken: viper.GetString("components.argocd.auth-token"), + ArgoCDPassword: viper.GetString("components.argocd.password"), + PostInstallCatalogApps: catalogApps, GitAuth: apiTypes.GitAuth{ Token: gitToken, User: gitUser, @@ -126,7 +136,7 @@ func CreateClusterRecordFromRaw(useTelemetry bool, gitOwner string, gitUser stri return cl } -func CreateClusterDefinitionRecordFromRaw(gitAuth apiTypes.GitAuth, cliFlags types.CliFlags) apiTypes.ClusterDefinition { +func CreateClusterDefinitionRecordFromRaw(gitAuth apiTypes.GitAuth, cliFlags types.CliFlags, catalogApps []apiTypes.GitopsCatalogApp) apiTypes.ClusterDefinition { cloudProvider := viper.GetString("kubefirst.cloud-provider") domainName := viper.GetString("flags.domain-name") gitProvider := viper.GetString("flags.git-provider") @@ -142,21 +152,22 @@ func CreateClusterDefinitionRecordFromRaw(gitAuth apiTypes.GitAuth, cliFlags typ } cl := apiTypes.ClusterDefinition{ - AdminEmail: viper.GetString("flags.alerts-email"), - ClusterName: viper.GetString("flags.cluster-name"), - CloudProvider: cloudProvider, - CloudRegion: viper.GetString("flags.cloud-region"), - DomainName: domainName, - SubdomainName: cliFlags.SubDomainName, - Type: "mgmt", - NodeType: cliFlags.NodeType, - NodeCount: stringToIntNodeCount, - GitopsTemplateURL: cliFlags.GitopsTemplateURL, - GitopsTemplateBranch: cliFlags.GitopsTemplateBranch, - GitProvider: gitProvider, - GitProtocol: viper.GetString("flags.git-protocol"), - DnsProvider: viper.GetString("flags.dns-provider"), - LogFileName: viper.GetString("k1-paths.log-file-name"), + AdminEmail: viper.GetString("flags.alerts-email"), + ClusterName: viper.GetString("flags.cluster-name"), + CloudProvider: cloudProvider, + CloudRegion: viper.GetString("flags.cloud-region"), + DomainName: domainName, + SubdomainName: cliFlags.SubDomainName, + Type: "mgmt", + NodeType: cliFlags.NodeType, + NodeCount: stringToIntNodeCount, + GitopsTemplateURL: cliFlags.GitopsTemplateURL, + GitopsTemplateBranch: cliFlags.GitopsTemplateBranch, + GitProvider: gitProvider, + GitProtocol: viper.GetString("flags.git-protocol"), + DnsProvider: viper.GetString("flags.dns-provider"), + LogFileName: viper.GetString("k1-paths.log-file-name"), + PostInstallCatalogApps: catalogApps, GitAuth: apiTypes.GitAuth{ Token: gitAuth.Token, User: gitAuth.User,