From 43bd3b0fd7084835721b3a21f2876ce3d70b35d0 Mon Sep 17 00:00:00 2001 From: Pierre Gerbelot Date: Tue, 2 Jan 2024 17:24:52 +0100 Subject: [PATCH] feat(COR-803): helm define custom domains --- cmd/helm.go | 1 + cmd/helm_container_create.go | 100 ++++++++++++++++++++++ cmd/helm_domain.go | 24 ++++++ cmd/helm_domain_edit.go | 98 +++++++++++++++++++++ cmd/helm_domain_list.go | 160 +++++++++++++++++++++++++++++++++++ cmd/hem_domain_delete.go | 89 +++++++++++++++++++ go.mod | 2 +- go.sum | 2 + 8 files changed, 475 insertions(+), 1 deletion(-) create mode 100644 cmd/helm_container_create.go create mode 100644 cmd/helm_domain.go create mode 100644 cmd/helm_domain_edit.go create mode 100644 cmd/helm_domain_list.go create mode 100644 cmd/hem_domain_delete.go diff --git a/cmd/helm.go b/cmd/helm.go index 4d5936b9..fea0884b 100644 --- a/cmd/helm.go +++ b/cmd/helm.go @@ -15,6 +15,7 @@ var chartGitCommitId string var charGitCommitBranch string var valuesOverrideCommitId string var valuesOverrideCommitBranch string +var helmCustomDomain string var helmCmd = &cobra.Command{ Use: "helm", diff --git a/cmd/helm_container_create.go b/cmd/helm_container_create.go new file mode 100644 index 00000000..24d970fc --- /dev/null +++ b/cmd/helm_container_create.go @@ -0,0 +1,100 @@ +package cmd + +import ( + "context" + "fmt" + "os" + "strconv" + + "github.com/qovery/qovery-client-go" + + "github.com/pterm/pterm" + "github.com/qovery/qovery-cli/utils" + "github.com/spf13/cobra" +) + + +var helmDomainCreateCmd = &cobra.Command{ + Use: "create", + Short: "Create helm custom domain", + Run: func(cmd *cobra.Command, args []string) { + utils.Capture(cmd) + + tokenType, token, err := utils.GetAccessToken() + if err != nil { + utils.PrintlnError(err) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + client := utils.GetQoveryClient(tokenType, token) + _, _, envId, err := getOrganizationProjectEnvironmentContextResourcesIds(client) + + if err != nil { + utils.PrintlnError(err) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + helms, _, err := client.HelmsAPI.ListHelms(context.Background(), envId).Execute() + + if err != nil { + utils.PrintlnError(err) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + helm := utils.FindByHelmName(helms.GetResults(), helmName) + + if helm == nil { + utils.PrintlnError(fmt.Errorf("helm %s not found", helmName)) + utils.PrintlnInfo("You can list all helms with: qovery helm list") + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + customDomains, _, err := client.CustomDomainAPI.ListHelmCustomDomain(context.Background(), helm.Id).Execute() + + if err != nil { + utils.PrintlnError(err) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + customDomain := utils.FindByCustomDomainName(customDomains.GetResults(), helmCustomDomain) + if customDomain != nil { + utils.PrintlnError(fmt.Errorf("custom domain %s already exists", helmCustomDomain)) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + generateCertificate := !doNotGenerateCertificate + req := qovery.CustomDomainRequest{ + Domain: helmCustomDomain, + GenerateCertificate: generateCertificate, + } + + createdDomain, _, err := client.CustomDomainAPI.CreateHelmCustomDomain(context.Background(), helm.Id).CustomDomainRequest(req).Execute() + + if err != nil { + utils.PrintlnError(err) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + utils.Println(fmt.Sprintf("Custom domain %s has been created (generate certificate: %s)", pterm.FgBlue.Sprintf(createdDomain.Domain), pterm.FgBlue.Sprintf(strconv.FormatBool(createdDomain.GenerateCertificate)))) + }, +} + +func init() { + helmDomainCmd.AddCommand(helmDomainCreateCmd) + helmDomainCreateCmd.Flags().StringVarP(&organizationName, "organization", "", "", "Organization Name") + helmDomainCreateCmd.Flags().StringVarP(&projectName, "project", "", "", "Project Name") + helmDomainCreateCmd.Flags().StringVarP(&environmentName, "environment", "", "", "Environment Name") + helmDomainCreateCmd.Flags().StringVarP(&helmName, "helm", "n", "", "helm Name") + helmDomainCreateCmd.Flags().StringVarP(&helmCustomDomain, "domain", "", "", "Custom Domain ") + helmDomainCreateCmd.Flags().BoolVarP(&doNotGenerateCertificate, "do-not-generate-certificate", "", false, "Do Not Generate Certificate") + + _ = helmDomainCreateCmd.MarkFlagRequired("helm") + _ = helmDomainCreateCmd.MarkFlagRequired("domain") +} diff --git a/cmd/helm_domain.go b/cmd/helm_domain.go new file mode 100644 index 00000000..915fe933 --- /dev/null +++ b/cmd/helm_domain.go @@ -0,0 +1,24 @@ +package cmd + +import ( + "github.com/qovery/qovery-cli/utils" + "github.com/spf13/cobra" + "os" +) + +var helmDomainCmd = &cobra.Command{ + Use: "domain", + Short: "Manage helm domains", + Run: func(cmd *cobra.Command, args []string) { + utils.Capture(cmd) + + if len(args) == 0 { + _ = cmd.Help() + os.Exit(0) + } + }, +} + +func init() { + helmCmd.AddCommand(helmDomainCmd) +} diff --git a/cmd/helm_domain_edit.go b/cmd/helm_domain_edit.go new file mode 100644 index 00000000..c1ed7e13 --- /dev/null +++ b/cmd/helm_domain_edit.go @@ -0,0 +1,98 @@ +package cmd + +import ( + "context" + "fmt" + "github.com/qovery/qovery-client-go" + "os" + "strconv" + + "github.com/pterm/pterm" + "github.com/qovery/qovery-cli/utils" + "github.com/spf13/cobra" +) + +var helmDomainEditCmd = &cobra.Command{ + Use: "edit", + Short: "Edit helm custom domain", + Run: func(cmd *cobra.Command, args []string) { + utils.Capture(cmd) + + tokenType, token, err := utils.GetAccessToken() + if err != nil { + utils.PrintlnError(err) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + client := utils.GetQoveryClient(tokenType, token) + _, _, envId, err := getOrganizationProjectEnvironmentContextResourcesIds(client) + + if err != nil { + utils.PrintlnError(err) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + helms, _, err := client.HelmsAPI.ListHelms(context.Background(), envId).Execute() + + if err != nil { + utils.PrintlnError(err) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + helm := utils.FindByHelmName(helms.GetResults(), helmName) + + if helm == nil { + utils.PrintlnError(fmt.Errorf("helm %s not found", helmName)) + utils.PrintlnInfo("You can list all helms with: qovery helm list") + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + customDomains, _, err := client.CustomDomainAPI.ListHelmCustomDomain(context.Background(), helm.Id).Execute() + + if err != nil { + utils.PrintlnError(err) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + customDomain := utils.FindByCustomDomainName(customDomains.GetResults(), helmCustomDomain) + if customDomain == nil { + utils.PrintlnError(fmt.Errorf("custom domain %s does not exist", helmCustomDomain)) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + generateCertificate := !doNotGenerateCertificate + req := qovery.CustomDomainRequest{ + Domain: helmCustomDomain, + GenerateCertificate: generateCertificate, + } + + editedDomain, _, err := client.HelmCustomDomainAPI.EditHelmCustomDomain(context.Background(), helm.Id, customDomain.Id).CustomDomainRequest(req).Execute() + + if err != nil { + utils.PrintlnError(err) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + utils.Println(fmt.Sprintf("Custom domain %s has been edited (generate certificate: %s)", pterm.FgBlue.Sprintf(editedDomain.Domain), pterm.FgBlue.Sprintf(strconv.FormatBool(editedDomain.GenerateCertificate)))) + }, +} + +func init() { + helmDomainCmd.AddCommand(helmDomainEditCmd) + helmDomainEditCmd.Flags().StringVarP(&organizationName, "organization", "", "", "Organization Name") + helmDomainEditCmd.Flags().StringVarP(&projectName, "project", "", "", "Project Name") + helmDomainEditCmd.Flags().StringVarP(&environmentName, "environment", "", "", "Environment Name") + helmDomainEditCmd.Flags().StringVarP(&helmName, "helm", "n", "", "helm Name") + helmDomainEditCmd.Flags().StringVarP(&helmCustomDomain, "domain", "", "", "Custom Domain ") + helmDomainEditCmd.Flags().BoolVarP(&doNotGenerateCertificate, "do-not-generate-certificate", "", false, "Do Not Generate Certificate") + + _ = helmDomainEditCmd.MarkFlagRequired("helm") + _ = helmDomainEditCmd.MarkFlagRequired("domain") +} diff --git a/cmd/helm_domain_list.go b/cmd/helm_domain_list.go new file mode 100644 index 00000000..2ad9bfa6 --- /dev/null +++ b/cmd/helm_domain_list.go @@ -0,0 +1,160 @@ +package cmd + +import ( + "context" + "encoding/json" + "fmt" + "github.com/qovery/qovery-client-go" + "os" + "strconv" + "strings" + + "github.com/qovery/qovery-cli/utils" + "github.com/spf13/cobra" +) + +var helmDomainListCmd = &cobra.Command{ + Use: "list", + Short: "List helm domains", + Run: func(cmd *cobra.Command, args []string) { + utils.Capture(cmd) + + tokenType, token, err := utils.GetAccessToken() + if err != nil { + utils.PrintlnError(err) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + client := utils.GetQoveryClient(tokenType, token) + + _, _, envId, err := getOrganizationProjectEnvironmentContextResourcesIds(client) + + if err != nil { + utils.PrintlnError(err) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + helms, _, err := client.HelmsAPI.ListHelms(context.Background(), envId).Execute() + + if err != nil { + utils.PrintlnError(err) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + helm := utils.FindByHelmName(helms.GetResults(), helmName) + + if helm == nil { + utils.PrintlnError(fmt.Errorf("helm %s not found", helmName)) + utils.PrintlnInfo("You can list all helms with: qovery helm list") + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + customDomains, _, err := client.CustomDomainAPI.ListHelmCustomDomain(context.Background(), helm.Id).Execute() + + if err != nil { + utils.PrintlnError(err) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + customDomainsSet := make(map[string]bool) + var data [][]string + + for _, customDomain := range customDomains.GetResults() { + customDomainsSet[customDomain.Domain] = true + + data = append(data, []string{ + customDomain.Id, + "CUSTOM_DOMAIN", + customDomain.Domain, + *customDomain.ValidationDomain, + strconv.FormatBool(customDomain.GenerateCertificate), + }) + } + + links, _, err := client.HelmMainCallsAPI.ListHelmLinks(context.Background(), helm.Id).Execute() + + if err != nil { + utils.PrintlnError(err) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + if jsonFlag { + utils.Println(gethelmDomainJsonOutput(links.GetResults(), customDomains.GetResults())) + return + } + + for _, link := range links.GetResults() { + if link.Url != nil { + domain := strings.ReplaceAll(*link.Url, "https://", "") + if !customDomainsSet[domain] { + data = append(data, []string{ + "N/A", + "BUILT_IN_DOMAIN", + domain, + "N/A", + "N/A", + }) + } + } + } + + err = utils.PrintTable([]string{"Id", "Type", "Domain", "Validation Domain", "Generate Certificate"}, data) + + if err != nil { + utils.PrintlnError(err) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + }, +} + +func gethelmDomainJsonOutput(links []qovery.Link, domains []qovery.CustomDomain) string { + var results []interface{} + + for _, link := range links { + if link.Url != nil { + results = append(results, map[string]interface{}{ + "id": nil, + "type": "BUILT_IN_DOMAIN", + "domain": strings.ReplaceAll(*link.Url, "https://", ""), + "validation_domain": nil, + }) + } + } + + for _, domain := range domains { + results = append(results, map[string]interface{}{ + "id": domain.Id, + "type": "CUSTOM_DOMAIN", + "domain": domain.Domain, + "validation_domain": *domain.ValidationDomain, + }) + } + + j, err := json.Marshal(results) + + if err != nil { + utils.PrintlnError(err) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + return string(j) +} + +func init() { + helmDomainCmd.AddCommand(helmDomainListCmd) + helmDomainListCmd.Flags().StringVarP(&organizationName, "organization", "", "", "Organization Name") + helmDomainListCmd.Flags().StringVarP(&projectName, "project", "", "", "Project Name") + helmDomainListCmd.Flags().StringVarP(&environmentName, "environment", "", "", "Environment Name") + helmDomainListCmd.Flags().StringVarP(&helmName, "helm", "n", "", "helm Name") + helmDomainListCmd.Flags().BoolVarP(&jsonFlag, "json", "", false, "JSON output") + + _ = helmDomainListCmd.MarkFlagRequired("helm") +} diff --git a/cmd/hem_domain_delete.go b/cmd/hem_domain_delete.go new file mode 100644 index 00000000..5c895855 --- /dev/null +++ b/cmd/hem_domain_delete.go @@ -0,0 +1,89 @@ +package cmd + +import ( + "context" + "fmt" + "os" + + "github.com/pterm/pterm" + "github.com/qovery/qovery-cli/utils" + "github.com/spf13/cobra" +) + +var helmDomainDeleteCmd = &cobra.Command{ + Use: "delete", + Short: "Delete helm custom domain", + Run: func(cmd *cobra.Command, args []string) { + utils.Capture(cmd) + + tokenType, token, err := utils.GetAccessToken() + if err != nil { + utils.PrintlnError(err) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + client := utils.GetQoveryClient(tokenType, token) + _, _, envId, err := getOrganizationProjectEnvironmentContextResourcesIds(client) + + if err != nil { + utils.PrintlnError(err) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + helms, _, err := client.HelmsAPI.ListHelms(context.Background(), envId).Execute() + + if err != nil { + utils.PrintlnError(err) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + helm := utils.FindByHelmName(helms.GetResults(), helmName) + + if helm == nil { + utils.PrintlnError(fmt.Errorf("helm %s not found", helmName)) + utils.PrintlnInfo("You can list all helms with: qovery helm list") + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + customDomains, _, err := client.CustomDomainAPI.ListHelmCustomDomain(context.Background(), helm.Id).Execute() + + if err != nil { + utils.PrintlnError(err) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + customDomain := utils.FindByCustomDomainName(customDomains.GetResults(), helmCustomDomain) + if customDomain == nil { + utils.PrintlnError(fmt.Errorf("custom domain %s does not exist", helmCustomDomain)) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + _, err = client.HelmCustomDomainAPI.DeleteHelmCustomDomain(context.Background(), helm.Id, customDomain.Id).Execute() + + if err != nil { + utils.PrintlnError(err) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + utils.Println(fmt.Sprintf("Custom domain %s has been deleted", pterm.FgBlue.Sprintf(helmCustomDomain))) + }, +} + +func init() { + helmDomainCmd.AddCommand(helmDomainDeleteCmd) + helmDomainDeleteCmd.Flags().StringVarP(&organizationName, "organization", "", "", "Organization Name") + helmDomainDeleteCmd.Flags().StringVarP(&projectName, "project", "", "", "Project Name") + helmDomainDeleteCmd.Flags().StringVarP(&environmentName, "environment", "", "", "Environment Name") + helmDomainDeleteCmd.Flags().StringVarP(&helmName, "helm", "n", "", "helm Name") + helmDomainDeleteCmd.Flags().StringVarP(&helmCustomDomain, "domain", "", "", "Custom Domain ") + + _ = helmDomainDeleteCmd.MarkFlagRequired("helm") + _ = helmDomainDeleteCmd.MarkFlagRequired("domain") +} diff --git a/go.mod b/go.mod index daefb76e..ea829fa3 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/posthog/posthog-go v0.0.0-20221221115252-24dfed35d71a github.com/pterm/pterm v0.12.55 - github.com/qovery/qovery-client-go v0.0.0-20240102111457-e9d5e9a578cd + github.com/qovery/qovery-client-go v0.0.0-20240102155005-3a6753cad4f4 github.com/sirupsen/logrus v1.9.0 github.com/spf13/cobra v1.6.1 github.com/spf13/pflag v1.0.5 diff --git a/go.sum b/go.sum index 095f683f..971cda84 100644 --- a/go.sum +++ b/go.sum @@ -196,6 +196,8 @@ github.com/qovery/qovery-client-go v0.0.0-20231222093609-d7ae5a912bea h1:/MLgKpX github.com/qovery/qovery-client-go v0.0.0-20231222093609-d7ae5a912bea/go.mod h1:5QD7sC1Z6XCCYd31c4XKVwGdEOjvtgG0NDcaVDoWb+o= github.com/qovery/qovery-client-go v0.0.0-20240102111457-e9d5e9a578cd h1:K3H0JYTE+VN7hIo2T/UlKgDCbL2Z8Om7vkqrhVVP7og= github.com/qovery/qovery-client-go v0.0.0-20240102111457-e9d5e9a578cd/go.mod h1:5QD7sC1Z6XCCYd31c4XKVwGdEOjvtgG0NDcaVDoWb+o= +github.com/qovery/qovery-client-go v0.0.0-20240102155005-3a6753cad4f4 h1:jF8XOqAsbbZeEJOjyVDsy8fI9RNCLKNP/xa38mgizpo= +github.com/qovery/qovery-client-go v0.0.0-20240102155005-3a6753cad4f4/go.mod h1:5QD7sC1Z6XCCYd31c4XKVwGdEOjvtgG0NDcaVDoWb+o= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=