diff --git a/cmd/container_create.go b/cmd/container_create.go new file mode 100644 index 00000000..9b9e0c91 --- /dev/null +++ b/cmd/container_create.go @@ -0,0 +1,120 @@ +package cmd + +import ( + "context" + "encoding/json" + "fmt" + "io" + + "github.com/pkg/errors" + "github.com/pterm/pterm" + "github.com/qovery/qovery-cli/utils" + "github.com/qovery/qovery-client-go" + "github.com/spf13/cobra" +) + +var containerRegistryId string +var containerPort int32 +var containerCpu int32 +var containerMemory int32 +var containerMinRunningInstances int32 +var containerMaxRunningInstances int32 + +var containerCreateCmd = &cobra.Command{ + Use: "create", + Short: "Create a container service", + Run: func(cmd *cobra.Command, args []string) { + utils.Capture(cmd) + + tokenType, token, err := utils.GetAccessToken() + utils.CheckError(err) + + client := utils.GetQoveryClient(tokenType, token) + _, _, envId, err := getOrganizationProjectEnvironmentContextResourcesIds(client) + utils.CheckError(err) + + var ports []qovery.ServicePortRequestPortsInner + if containerPort > 0 { + portName := fmt.Sprintf("p%d", containerPort) + protocol := qovery.PORTPROTOCOLENUM_HTTP + ports = append(ports, qovery.ServicePortRequestPortsInner{ + Name: &portName, + InternalPort: containerPort, + ExternalPort: utils.Int32(443), + PubliclyAccessible: true, + IsDefault: utils.Bool(true), + Protocol: &protocol, + }) + } + + req := qovery.ContainerRequest{ + Name: containerName, + RegistryId: containerRegistryId, + ImageName: containerImageName, + Tag: containerTag, + Ports: ports, + Cpu: utils.Int32(containerCpu), + Memory: utils.Int32(containerMemory), + MinRunningInstances: utils.Int32(containerMinRunningInstances), + MaxRunningInstances: utils.Int32(containerMaxRunningInstances), + Healthchecks: *qovery.NewHealthcheck(), + } + + created, res, err := client.ContainersAPI.CreateContainer(context.Background(), envId).ContainerRequest(req).Execute() + if err != nil && res != nil && res.StatusCode != 201 { + result, _ := io.ReadAll(res.Body) + utils.PrintlnError(errors.Errorf("status code: %s ; body: %s", res.Status, string(result))) + } + utils.CheckError(err) + + var publicLink string + if len(ports) > 0 { + links, _, err := client.ContainerMainCallsAPI.ListContainerLinks(context.Background(), created.Id).Execute() + if err == nil { + for _, link := range links.GetResults() { + publicLink = link.Url + break + } + } + } + + if jsonFlag { + out := struct { + Id string `json:"id"` + Name string `json:"name"` + PublicLink string `json:"public_link,omitempty"` + }{Id: created.Id, Name: created.Name, PublicLink: publicLink} + j, _ := json.Marshal(out) + utils.Println(string(j)) + return + } + + msg := fmt.Sprintf("Container service %s created! (id: %s)", pterm.FgBlue.Sprintf("%s", created.Name), pterm.FgBlue.Sprintf("%s", created.Id)) + if publicLink != "" { + msg += fmt.Sprintf(" - Public link: %s", pterm.FgBlue.Sprintf("%s", publicLink)) + } + utils.Println(msg) + }, +} + +func init() { + containerCmd.AddCommand(containerCreateCmd) + containerCreateCmd.Flags().StringVarP(&organizationName, "organization", "", "", "Organization Name") + containerCreateCmd.Flags().StringVarP(&projectName, "project", "", "", "Project Name") + containerCreateCmd.Flags().StringVarP(&environmentName, "environment", "", "", "Environment Name") + containerCreateCmd.Flags().StringVarP(&containerName, "container", "n", "", "Container Name") + containerCreateCmd.Flags().StringVarP(&containerRegistryId, "registry", "", "", "Container Registry ID") + containerCreateCmd.Flags().StringVarP(&containerImageName, "image-name", "", "", "Container Image Name") + containerCreateCmd.Flags().StringVarP(&containerTag, "tag", "t", "", "Container Image Tag") + containerCreateCmd.Flags().Int32VarP(&containerPort, "port", "p", 0, "Container Port (0 = no port exposed)") + containerCreateCmd.Flags().Int32VarP(&containerCpu, "cpu", "", 500, "CPU in millicores (e.g. 500 = 0.5 vCPU)") + containerCreateCmd.Flags().Int32VarP(&containerMemory, "memory", "", 512, "Memory in MB") + containerCreateCmd.Flags().Int32VarP(&containerMinRunningInstances, "min-instances", "", 1, "Minimum number of running instances") + containerCreateCmd.Flags().Int32VarP(&containerMaxRunningInstances, "max-instances", "", 1, "Maximum number of running instances") + containerCreateCmd.Flags().BoolVarP(&jsonFlag, "json", "", false, "JSON output") + + _ = containerCreateCmd.MarkFlagRequired("container") + _ = containerCreateCmd.MarkFlagRequired("registry") + _ = containerCreateCmd.MarkFlagRequired("image-name") + _ = containerCreateCmd.MarkFlagRequired("tag") +} diff --git a/cmd/container_registry.go b/cmd/container_registry.go new file mode 100644 index 00000000..76ba752e --- /dev/null +++ b/cmd/container_registry.go @@ -0,0 +1,25 @@ +package cmd + +import ( + "os" + + "github.com/qovery/qovery-cli/utils" + "github.com/spf13/cobra" +) + +var containerRegistryCmd = &cobra.Command{ + Use: "registry", + Short: "Manage container registries", + Run: func(cmd *cobra.Command, args []string) { + utils.Capture(cmd) + + if len(args) == 0 { + _ = cmd.Help() + os.Exit(0) + } + }, +} + +func init() { + containerCmd.AddCommand(containerRegistryCmd) +} diff --git a/cmd/container_registry_list.go b/cmd/container_registry_list.go new file mode 100644 index 00000000..4ad49b70 --- /dev/null +++ b/cmd/container_registry_list.go @@ -0,0 +1,80 @@ +package cmd + +import ( + "context" + "encoding/json" + + "github.com/qovery/qovery-cli/pkg/usercontext" + "github.com/qovery/qovery-cli/utils" + "github.com/qovery/qovery-client-go" + "github.com/spf13/cobra" +) + +var containerRegistryListCmd = &cobra.Command{ + Use: "list", + Short: "List container registries", + Run: func(cmd *cobra.Command, args []string) { + utils.Capture(cmd) + + tokenType, token, err := utils.GetAccessToken() + utils.CheckError(err) + + client := utils.GetQoveryClient(tokenType, token) + organizationId, err := usercontext.GetOrganizationContextResourceId(client, organizationName) + utils.CheckError(err) + + registries, _, err := client.ContainerRegistriesAPI.ListContainerRegistry(context.Background(), organizationId).Execute() + utils.CheckError(err) + + if jsonFlag { + utils.Println(getContainerRegistryJsonOutput(registries.GetResults())) + return + } + + var data [][]string + for _, registry := range registries.GetResults() { + url := "" + if registry.Url != nil { + url = *registry.Url + } + kind := "" + if registry.Kind != nil { + kind = string(*registry.Kind) + } + data = append(data, []string{registry.Id, *registry.Name, kind, url}) + } + + utils.CheckError(utils.PrintTable([]string{"Id", "Name", "Kind", "URL"}, data)) + }, +} + +func getContainerRegistryJsonOutput(registries []qovery.ContainerRegistryResponse) string { + var results []interface{} + for _, registry := range registries { + url := "" + if registry.Url != nil { + url = *registry.Url + } + kind := "" + if registry.Kind != nil { + kind = string(*registry.Kind) + } + results = append(results, map[string]interface{}{ + "id": registry.Id, + "name": registry.Name, + "kind": kind, + "url": url, + }) + } + + j, err := json.Marshal(results) + utils.CheckError(err) + + return string(j) +} + +func init() { + containerRegistryCmd.AddCommand(containerRegistryListCmd) + containerRegistryListCmd.Flags().StringVarP(&organizationName, "organization", "", "", "Organization Name") + containerRegistryListCmd.Flags().BoolVarP(&jsonFlag, "json", "", false, "JSON output") +}