mygithub.libinneed.workers.dev/stackitcloud/stackit-cli
Advanced tools
@@ -78,12 +78,2 @@ # STACKIT CLI release workflow. | ||
| GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }} | ||
| - name: Install Docker | ||
| run: | | ||
| # Install Docker on macOS runner | ||
| brew install --cask docker | ||
| # Start Docker daemon | ||
| sudo /Applications/Docker.app/Contents/MacOS/Docker & | ||
| # Wait for Docker to be ready | ||
| sleep 30 | ||
| docker --version | ||
| echo "Docker is now available for createrepo_c operations" | ||
| - name: Publish packages to APT repo | ||
@@ -95,7 +85,1 @@ if: contains(github.ref_name, '-') == false | ||
| run: ./scripts/publish-apt-packages.sh | ||
| - name: Publish packages to RPM repo | ||
| if: contains(github.ref_name, '-') == false | ||
| env: | ||
| GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} | ||
| GPG_PRIVATE_KEY_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }} | ||
| run: ./scripts/publish-rpm-packages.sh |
@@ -16,5 +16,5 @@ name: Renovate | ||
| - name: Self-hosted Renovate | ||
| uses: renovatebot/github-action@v43.0.5 | ||
| uses: renovatebot/github-action@v43.0.3 | ||
| with: | ||
| configurationFile: .github/renovate.json | ||
| token: ${{ secrets.RENOVATE_TOKEN }} |
+2
-1
@@ -168,3 +168,4 @@ version: 2 | ||
| # if the tag has a prerelease indicator (e.g. v0.0.1-alpha1) | ||
| skip_upload: auto | ||
| # Temporarily not skipping prereleases to test integration with Winget | ||
| # skip_upload: auto | ||
| repository: | ||
@@ -171,0 +172,0 @@ owner: stackitcloud |
@@ -32,3 +32,3 @@ ## stackit mongodbflex user create | ||
| --instance-id string ID of the instance | ||
| --role strings Roles of the user, possible values are ["read" "readWrite" "readWriteAnyDatabase"] (default [read]) | ||
| --role strings Roles of the user, possible values are ["read" "readWrite"] (default [read]) | ||
| --username string Username of the user. If not specified, a random username will be assigned | ||
@@ -35,0 +35,0 @@ ``` |
@@ -26,3 +26,3 @@ ## stackit mongodbflex user update | ||
| --instance-id string ID of the instance | ||
| --role strings Roles of the user, possible values are ["read" "readWrite" "readWriteAnyDatabase"] (default []) | ||
| --role strings Roles of the user, possible values are ["read" "readWrite"] (default []) | ||
| ``` | ||
@@ -29,0 +29,0 @@ |
| ## stackit ske cluster create | ||
| Creates a SKE cluster | ||
| Creates an SKE cluster | ||
@@ -18,9 +18,9 @@ ### Synopsis | ||
| ``` | ||
| Create a SKE cluster using default configuration | ||
| Create an SKE cluster using default configuration | ||
| $ stackit ske cluster create my-cluster | ||
| Create a SKE cluster using an API payload sourced from the file "./payload.json" | ||
| Create an SKE cluster using an API payload sourced from the file "./payload.json" | ||
| $ stackit ske cluster create my-cluster --payload @./payload.json | ||
| Create a SKE cluster using an API payload provided as a JSON string | ||
| Create an SKE cluster using an API payload provided as a JSON string | ||
| $ stackit ske cluster create my-cluster --payload "{...}" | ||
@@ -27,0 +27,0 @@ |
@@ -16,3 +16,3 @@ ## stackit ske cluster delete | ||
| ``` | ||
| Delete a SKE cluster with name "my-cluster" | ||
| Delete an SKE cluster with name "my-cluster" | ||
| $ stackit ske cluster delete my-cluster | ||
@@ -19,0 +19,0 @@ ``` |
| ## stackit ske cluster describe | ||
| Shows details of a SKE cluster | ||
| Shows details of a SKE cluster | ||
| ### Synopsis | ||
| Shows details of a STACKIT Kubernetes Engine (SKE) cluster. | ||
| Shows details of a STACKIT Kubernetes Engine (SKE) cluster. | ||
@@ -16,6 +16,6 @@ ``` | ||
| ``` | ||
| Get details of a SKE cluster with name "my-cluster" | ||
| Get details of an SKE cluster with name "my-cluster" | ||
| $ stackit ske cluster describe my-cluster | ||
| Get details of a SKE cluster with name "my-cluster" in JSON format | ||
| Get details of an SKE cluster with name "my-cluster" in JSON format | ||
| $ stackit ske cluster describe my-cluster --output-format json | ||
@@ -22,0 +22,0 @@ ``` |
| ## stackit ske cluster update | ||
| Updates a SKE cluster | ||
| Updates an SKE cluster | ||
@@ -18,6 +18,6 @@ ### Synopsis | ||
| ``` | ||
| Update a SKE cluster using an API payload sourced from the file "./payload.json" | ||
| Update an SKE cluster using an API payload sourced from the file "./payload.json" | ||
| $ stackit ske cluster update my-cluster --payload @./payload.json | ||
| Update a SKE cluster using an API payload provided as a JSON string | ||
| Update an SKE cluster using an API payload provided as a JSON string | ||
| $ stackit ske cluster update my-cluster --payload "{...}" | ||
@@ -24,0 +24,0 @@ |
@@ -33,12 +33,8 @@ ## stackit ske cluster | ||
| * [stackit ske](./stackit_ske.md) - Provides functionality for SKE | ||
| * [stackit ske cluster create](./stackit_ske_cluster_create.md) - Creates a SKE cluster | ||
| * [stackit ske cluster create](./stackit_ske_cluster_create.md) - Creates an SKE cluster | ||
| * [stackit ske cluster delete](./stackit_ske_cluster_delete.md) - Deletes a SKE cluster | ||
| * [stackit ske cluster describe](./stackit_ske_cluster_describe.md) - Shows details of a SKE cluster | ||
| * [stackit ske cluster describe](./stackit_ske_cluster_describe.md) - Shows details of a SKE cluster | ||
| * [stackit ske cluster generate-payload](./stackit_ske_cluster_generate-payload.md) - Generates a payload to create/update SKE clusters | ||
| * [stackit ske cluster hibernate](./stackit_ske_cluster_hibernate.md) - Trigger hibernate for a SKE cluster | ||
| * [stackit ske cluster list](./stackit_ske_cluster_list.md) - Lists all SKE clusters | ||
| * [stackit ske cluster maintenance](./stackit_ske_cluster_maintenance.md) - Trigger maintenance for a SKE cluster | ||
| * [stackit ske cluster reconcile](./stackit_ske_cluster_reconcile.md) - Trigger reconcile for a SKE cluster | ||
| * [stackit ske cluster update](./stackit_ske_cluster_update.md) - Updates a SKE cluster | ||
| * [stackit ske cluster wakeup](./stackit_ske_cluster_wakeup.md) - Trigger wakeup from hibernation for a SKE cluster | ||
| * [stackit ske cluster update](./stackit_ske_cluster_update.md) - Updates an SKE cluster | ||
| ## stackit ske kubeconfig create | ||
| Creates or update a kubeconfig for a SKE cluster | ||
| Creates or update a kubeconfig for an SKE cluster | ||
| ### Synopsis | ||
| Creates a kubeconfig for a STACKIT Kubernetes Engine (SKE) cluster, if the config exists in the kubeconfig file the information will be updated. | ||
| Creates a kubeconfig for a STACKIT Kubernetes Engine (SKE) cluster, if the config exits in the kubeconfig file the information will be updated. | ||
@@ -9,0 +9,0 @@ By default, the kubeconfig information of the SKE cluster is merged into the default kubeconfig file of the current user. If the kubeconfig file doesn't exist, a new one will be created. |
@@ -33,4 +33,4 @@ ## stackit ske kubeconfig | ||
| * [stackit ske](./stackit_ske.md) - Provides functionality for SKE | ||
| * [stackit ske kubeconfig create](./stackit_ske_kubeconfig_create.md) - Creates or update a kubeconfig for a SKE cluster | ||
| * [stackit ske kubeconfig create](./stackit_ske_kubeconfig_create.md) - Creates or update a kubeconfig for an SKE cluster | ||
| * [stackit ske kubeconfig login](./stackit_ske_kubeconfig_login.md) - Login plugin for kubernetes clients | ||
+26
-26
@@ -12,3 +12,3 @@ module github.com/stackitcloud/stackit-cli | ||
| github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf | ||
| github.com/jedib0t/go-pretty/v6 v6.6.8 | ||
| github.com/jedib0t/go-pretty/v6 v6.6.7 | ||
| github.com/lmittmann/tint v1.1.2 | ||
@@ -19,20 +19,20 @@ github.com/mattn/go-colorable v0.1.14 | ||
| github.com/spf13/viper v1.20.1 | ||
| github.com/stackitcloud/stackit-sdk-go/core v0.17.3 | ||
| github.com/stackitcloud/stackit-sdk-go/services/alb v0.6.1 | ||
| github.com/stackitcloud/stackit-sdk-go/services/authorization v0.8.1 | ||
| github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 | ||
| github.com/stackitcloud/stackit-sdk-go/services/git v0.7.1 | ||
| github.com/stackitcloud/stackit-sdk-go/services/iaas v0.27.1 | ||
| github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.1 | ||
| github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1 | ||
| github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1 | ||
| github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.1 | ||
| github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.1 | ||
| github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.1 | ||
| github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.2 | ||
| github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.1 | ||
| github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.9.1 | ||
| github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.2 | ||
| github.com/stackitcloud/stackit-sdk-go/services/ske v1.3.0 | ||
| github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.1 | ||
| github.com/stackitcloud/stackit-sdk-go/core v0.17.2 | ||
| github.com/stackitcloud/stackit-sdk-go/services/alb v0.6.0 | ||
| github.com/stackitcloud/stackit-sdk-go/services/authorization v0.8.0 | ||
| github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.0 | ||
| github.com/stackitcloud/stackit-sdk-go/services/git v0.7.0 | ||
| github.com/stackitcloud/stackit-sdk-go/services/iaas v0.27.0 | ||
| github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.0 | ||
| github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.0 | ||
| github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.0 | ||
| github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.0 | ||
| github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.0 | ||
| github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.0 | ||
| github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.1 | ||
| github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.0 | ||
| github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.9.0 | ||
| github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.1 | ||
| github.com/stackitcloud/stackit-sdk-go/services/ske v1.1.0 | ||
| github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.0 | ||
| github.com/zalando/go-keyring v0.2.6 | ||
@@ -243,9 +243,9 @@ golang.org/x/mod v0.26.0 | ||
| github.com/spf13/cast v1.7.1 // indirect | ||
| github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.5.1 | ||
| github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.1 | ||
| github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1 | ||
| github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.1 | ||
| github.com/stackitcloud/stackit-sdk-go/services/observability v0.9.1 | ||
| github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.1 | ||
| github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.1 | ||
| github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.5.0 | ||
| github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.0 | ||
| github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.0 | ||
| github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.0 | ||
| github.com/stackitcloud/stackit-sdk-go/services/observability v0.9.0 | ||
| github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.0 | ||
| github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.0 | ||
| github.com/subosito/gotenv v1.6.0 // indirect | ||
@@ -252,0 +252,0 @@ go.uber.org/multierr v1.11.0 // indirect |
+1
-41
@@ -20,45 +20,5 @@ # Installation | ||
| ```shell | ||
| brew install --cask stackit | ||
| brew install stackit | ||
| ``` | ||
| #### Formula deprecated | ||
| The homebrew formula is deprecated, will no longer be updated and will be removed after 2026-01-22. | ||
| You need to install the STACKIT CLI as cask. | ||
| Therefor you need to uninstall the formula and reinstall it as cask. | ||
| Your profiles should normally remain. To ensure that nothing will be gone, you should backup them. | ||
| 1. Export your existing profiles. This will create a json file in your current directory. | ||
| ```shell | ||
| stackit config profile export default | ||
| ``` | ||
| 2. If you have multiple profiles, then execute the export command for each of them. You can find your profiles via: | ||
| ```shell | ||
| stackit config profile list | ||
| stackit config profile export <profile-name> | ||
| ``` | ||
| 3. Uninstall the formula. | ||
| ```shell | ||
| brew uninstall stackit | ||
| ``` | ||
| 4. Install the STACKIT CLI as cask. | ||
| ```shell | ||
| brew install --cask stackit | ||
| ``` | ||
| 5. Check if your configs are still stored. | ||
| ```shell | ||
| stackit config profile list | ||
| ``` | ||
| 6. In case the profiles are gone, import your profiles via: | ||
| ```shell | ||
| $ stackit config profile import -c @default.json --name myProfile | ||
| ``` | ||
| ### Linux | ||
@@ -65,0 +25,0 @@ |
| package getaccesstoken | ||
| import ( | ||
| "encoding/json" | ||
| "fmt" | ||
| "github.com/goccy/go-yaml" | ||
| "github.com/spf13/cobra" | ||
@@ -14,10 +10,4 @@ "github.com/stackitcloud/stackit-cli/internal/cmd/params" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/examples" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/print" | ||
| ) | ||
| type inputModel struct { | ||
| *globalflags.GlobalFlagModel | ||
| } | ||
| func NewCmd(params *params.CmdParams) *cobra.Command { | ||
@@ -34,8 +24,3 @@ cmd := &cobra.Command{ | ||
| ), | ||
| RunE: func(cmd *cobra.Command, _ []string) error { | ||
| model, err := parseInput(params.Printer, cmd) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| RunE: func(_ *cobra.Command, _ []string) error { | ||
| userSessionExpired, err := auth.UserSessionExpired() | ||
@@ -55,28 +40,4 @@ if err != nil { | ||
| switch model.OutputFormat { | ||
| case print.JSONOutputFormat: | ||
| details, err := json.MarshalIndent(map[string]string{ | ||
| "access_token": accessToken, | ||
| }, "", " ") | ||
| if err != nil { | ||
| return fmt.Errorf("marshal image list: %w", err) | ||
| } | ||
| params.Printer.Outputln(string(details)) | ||
| return nil | ||
| case print.YAMLOutputFormat: | ||
| details, err := yaml.MarshalWithOptions(map[string]string{ | ||
| "access_token": accessToken, | ||
| }, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) | ||
| if err != nil { | ||
| return fmt.Errorf("marshal image list: %w", err) | ||
| } | ||
| params.Printer.Outputln(string(details)) | ||
| return nil | ||
| default: | ||
| params.Printer.Outputln(accessToken) | ||
| return nil | ||
| } | ||
| params.Printer.Outputf("%s\n", accessToken) | ||
| return nil | ||
| }, | ||
@@ -86,20 +47,1 @@ } | ||
| } | ||
| func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { | ||
| globalFlags := globalflags.Parse(p, cmd) | ||
| model := inputModel{ | ||
| GlobalFlagModel: globalFlags, | ||
| } | ||
| if p.IsVerbosityDebug() { | ||
| modelStr, err := print.BuildDebugStrFromInputModel(model) | ||
| if err != nil { | ||
| p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) | ||
| } else { | ||
| p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) | ||
| } | ||
| } | ||
| return &model, nil | ||
| } |
@@ -106,3 +106,3 @@ package create | ||
| func configureFlags(cmd *cobra.Command) { | ||
| roleOptions := []string{"read", "readWrite", "readWriteAnyDatabase"} | ||
| roleOptions := []string{"read", "readWrite"} | ||
@@ -109,0 +109,0 @@ cmd.Flags().Var(flags.UUIDFlag(), instanceIdFlag, "ID of the instance") |
@@ -100,3 +100,3 @@ package update | ||
| func configureFlags(cmd *cobra.Command) { | ||
| roleOptions := []string{"read", "readWrite", "readWriteAnyDatabase"} | ||
| roleOptions := []string{"read", "readWrite"} | ||
@@ -103,0 +103,0 @@ cmd.Flags().Var(flags.UUIDFlag(), instanceIdFlag, "ID of the instance") |
@@ -9,8 +9,4 @@ package cluster | ||
| generatepayload "github.com/stackitcloud/stackit-cli/internal/cmd/ske/cluster/generate-payload" | ||
| "github.com/stackitcloud/stackit-cli/internal/cmd/ske/cluster/hibernate" | ||
| "github.com/stackitcloud/stackit-cli/internal/cmd/ske/cluster/list" | ||
| "github.com/stackitcloud/stackit-cli/internal/cmd/ske/cluster/maintenance" | ||
| "github.com/stackitcloud/stackit-cli/internal/cmd/ske/cluster/reconcile" | ||
| "github.com/stackitcloud/stackit-cli/internal/cmd/ske/cluster/update" | ||
| "github.com/stackitcloud/stackit-cli/internal/cmd/ske/cluster/wakeup" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/args" | ||
@@ -41,6 +37,2 @@ "github.com/stackitcloud/stackit-cli/internal/pkg/utils" | ||
| cmd.AddCommand(update.NewCmd(params)) | ||
| cmd.AddCommand(hibernate.NewCmd(params)) | ||
| cmd.AddCommand(maintenance.NewCmd(params)) | ||
| cmd.AddCommand(reconcile.NewCmd(params)) | ||
| cmd.AddCommand(wakeup.NewCmd(params)) | ||
| } |
@@ -43,3 +43,3 @@ package create | ||
| Use: fmt.Sprintf("create %s", clusterNameArg), | ||
| Short: "Creates a SKE cluster", | ||
| Short: "Creates an SKE cluster", | ||
| Long: fmt.Sprintf("%s\n%s\n%s", | ||
@@ -53,9 +53,9 @@ "Creates a STACKIT Kubernetes Engine (SKE) cluster.", | ||
| examples.NewExample( | ||
| `Create a SKE cluster using default configuration`, | ||
| `Create an SKE cluster using default configuration`, | ||
| "$ stackit ske cluster create my-cluster"), | ||
| examples.NewExample( | ||
| `Create a SKE cluster using an API payload sourced from the file "./payload.json"`, | ||
| `Create an SKE cluster using an API payload sourced from the file "./payload.json"`, | ||
| "$ stackit ske cluster create my-cluster --payload @./payload.json"), | ||
| examples.NewExample( | ||
| `Create a SKE cluster using an API payload provided as a JSON string`, | ||
| `Create an SKE cluster using an API payload provided as a JSON string`, | ||
| `$ stackit ske cluster create my-cluster --payload "{...}"`), | ||
@@ -62,0 +62,0 @@ examples.NewExample( |
@@ -38,3 +38,3 @@ package delete | ||
| examples.NewExample( | ||
| `Delete a SKE cluster with name "my-cluster"`, | ||
| `Delete an SKE cluster with name "my-cluster"`, | ||
| "$ stackit ske cluster delete my-cluster"), | ||
@@ -41,0 +41,0 @@ ), |
@@ -34,11 +34,11 @@ package describe | ||
| Use: fmt.Sprintf("describe %s", clusterNameArg), | ||
| Short: "Shows details of a SKE cluster", | ||
| Long: "Shows details of a STACKIT Kubernetes Engine (SKE) cluster.", | ||
| Short: "Shows details of a SKE cluster", | ||
| Long: "Shows details of a STACKIT Kubernetes Engine (SKE) cluster.", | ||
| Args: args.SingleArg(clusterNameArg, nil), | ||
| Example: examples.Build( | ||
| examples.NewExample( | ||
| `Get details of a SKE cluster with name "my-cluster"`, | ||
| `Get details of an SKE cluster with name "my-cluster"`, | ||
| "$ stackit ske cluster describe my-cluster"), | ||
| examples.NewExample( | ||
| `Get details of a SKE cluster with name "my-cluster" in JSON format`, | ||
| `Get details of an SKE cluster with name "my-cluster" in JSON format`, | ||
| "$ stackit ske cluster describe my-cluster --output-format json"), | ||
@@ -45,0 +45,0 @@ ), |
@@ -40,3 +40,3 @@ package update | ||
| Use: fmt.Sprintf("update %s", clusterNameArg), | ||
| Short: "Updates a SKE cluster", | ||
| Short: "Updates an SKE cluster", | ||
| Long: fmt.Sprintf("%s\n%s\n%s", | ||
@@ -50,6 +50,6 @@ "Updates a STACKIT Kubernetes Engine (SKE) cluster.", | ||
| examples.NewExample( | ||
| `Update a SKE cluster using an API payload sourced from the file "./payload.json"`, | ||
| `Update an SKE cluster using an API payload sourced from the file "./payload.json"`, | ||
| "$ stackit ske cluster update my-cluster --payload @./payload.json"), | ||
| examples.NewExample( | ||
| `Update a SKE cluster using an API payload provided as a JSON string`, | ||
| `Update an SKE cluster using an API payload provided as a JSON string`, | ||
| `$ stackit ske cluster update my-cluster --payload "{...}"`), | ||
@@ -56,0 +56,0 @@ examples.NewExample( |
@@ -47,5 +47,5 @@ package create | ||
| Use: fmt.Sprintf("create %s", clusterNameArg), | ||
| Short: "Creates or update a kubeconfig for a SKE cluster", | ||
| Short: "Creates or update a kubeconfig for an SKE cluster", | ||
| Long: fmt.Sprintf("%s\n\n%s\n%s\n%s\n%s", | ||
| "Creates a kubeconfig for a STACKIT Kubernetes Engine (SKE) cluster, if the config exists in the kubeconfig file the information will be updated.", | ||
| "Creates a kubeconfig for a STACKIT Kubernetes Engine (SKE) cluster, if the config exits in the kubeconfig file the information will be updated.", | ||
| "By default, the kubeconfig information of the SKE cluster is merged into the default kubeconfig file of the current user. If the kubeconfig file doesn't exist, a new one will be created.", | ||
@@ -52,0 +52,0 @@ "You can override this behavior by specifying a custom filepath with the --filepath flag.\n", |
@@ -31,9 +31,9 @@ package ske | ||
| func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { | ||
| cmd.AddCommand(cluster.NewCmd(params)) | ||
| cmd.AddCommand(credentials.NewCmd(params)) | ||
| cmd.AddCommand(describe.NewCmd(params)) | ||
| cmd.AddCommand(disable.NewCmd(params)) | ||
| cmd.AddCommand(enable.NewCmd(params)) | ||
| cmd.AddCommand(kubeconfig.NewCmd(params)) | ||
| cmd.AddCommand(disable.NewCmd(params)) | ||
| cmd.AddCommand(cluster.NewCmd(params)) | ||
| cmd.AddCommand(credentials.NewCmd(params)) | ||
| cmd.AddCommand(options.NewCmd(params)) | ||
| } |
| ## stackit ske cluster hibernate | ||
| Trigger hibernate for a SKE cluster | ||
| ### Synopsis | ||
| Trigger hibernate for a STACKIT Kubernetes Engine (SKE) cluster. | ||
| ``` | ||
| stackit ske cluster hibernate CLUSTER_NAME [flags] | ||
| ``` | ||
| ### Examples | ||
| ``` | ||
| Trigger hibernate for a SKE cluster with name "my-cluster" | ||
| $ stackit ske cluster hibernate my-cluster | ||
| ``` | ||
| ### Options | ||
| ``` | ||
| -h, --help Help for "stackit ske cluster hibernate" | ||
| ``` | ||
| ### Options inherited from parent commands | ||
| ``` | ||
| -y, --assume-yes If set, skips all confirmation prompts | ||
| --async If set, runs the command asynchronously | ||
| -o, --output-format string Output format, one of ["json" "pretty" "none" "yaml"] | ||
| -p, --project-id string Project ID | ||
| --region string Target region for region-specific requests | ||
| --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") | ||
| ``` | ||
| ### SEE ALSO | ||
| * [stackit ske cluster](./stackit_ske_cluster.md) - Provides functionality for SKE cluster | ||
| ## stackit ske cluster maintenance | ||
| Trigger maintenance for a SKE cluster | ||
| ### Synopsis | ||
| Trigger maintenance for a STACKIT Kubernetes Engine (SKE) cluster. | ||
| ``` | ||
| stackit ske cluster maintenance CLUSTER_NAME [flags] | ||
| ``` | ||
| ### Examples | ||
| ``` | ||
| Trigger maintenance for a SKE cluster with name "my-cluster" | ||
| $ stackit ske cluster maintenance my-cluster | ||
| ``` | ||
| ### Options | ||
| ``` | ||
| -h, --help Help for "stackit ske cluster maintenance" | ||
| ``` | ||
| ### Options inherited from parent commands | ||
| ``` | ||
| -y, --assume-yes If set, skips all confirmation prompts | ||
| --async If set, runs the command asynchronously | ||
| -o, --output-format string Output format, one of ["json" "pretty" "none" "yaml"] | ||
| -p, --project-id string Project ID | ||
| --region string Target region for region-specific requests | ||
| --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") | ||
| ``` | ||
| ### SEE ALSO | ||
| * [stackit ske cluster](./stackit_ske_cluster.md) - Provides functionality for SKE cluster | ||
| ## stackit ske cluster reconcile | ||
| Trigger reconcile for a SKE cluster | ||
| ### Synopsis | ||
| Trigger reconcile for a STACKIT Kubernetes Engine (SKE) cluster. | ||
| ``` | ||
| stackit ske cluster reconcile CLUSTER_NAME [flags] | ||
| ``` | ||
| ### Examples | ||
| ``` | ||
| Trigger reconcile for a SKE cluster with name "my-cluster" | ||
| $ stackit ske cluster reconcile my-cluster | ||
| ``` | ||
| ### Options | ||
| ``` | ||
| -h, --help Help for "stackit ske cluster reconcile" | ||
| ``` | ||
| ### Options inherited from parent commands | ||
| ``` | ||
| -y, --assume-yes If set, skips all confirmation prompts | ||
| --async If set, runs the command asynchronously | ||
| -o, --output-format string Output format, one of ["json" "pretty" "none" "yaml"] | ||
| -p, --project-id string Project ID | ||
| --region string Target region for region-specific requests | ||
| --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") | ||
| ``` | ||
| ### SEE ALSO | ||
| * [stackit ske cluster](./stackit_ske_cluster.md) - Provides functionality for SKE cluster | ||
| ## stackit ske cluster wakeup | ||
| Trigger wakeup from hibernation for a SKE cluster | ||
| ### Synopsis | ||
| Trigger wakeup from hibernation for a STACKIT Kubernetes Engine (SKE) cluster. | ||
| ``` | ||
| stackit ske cluster wakeup CLUSTER_NAME [flags] | ||
| ``` | ||
| ### Examples | ||
| ``` | ||
| Trigger wakeup from hibernation for a SKE cluster with name "my-cluster" | ||
| $ stackit ske cluster wakeup my-cluster | ||
| ``` | ||
| ### Options | ||
| ``` | ||
| -h, --help Help for "stackit ske cluster wakeup" | ||
| ``` | ||
| ### Options inherited from parent commands | ||
| ``` | ||
| -y, --assume-yes If set, skips all confirmation prompts | ||
| --async If set, runs the command asynchronously | ||
| -o, --output-format string Output format, one of ["json" "pretty" "none" "yaml"] | ||
| -p, --project-id string Project ID | ||
| --region string Target region for region-specific requests | ||
| --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") | ||
| ``` | ||
| ### SEE ALSO | ||
| * [stackit ske cluster](./stackit_ske_cluster.md) - Provides functionality for SKE cluster | ||
| package hibernate | ||
| import ( | ||
| "context" | ||
| "testing" | ||
| "github.com/google/go-cmp/cmp" | ||
| "github.com/google/go-cmp/cmp/cmpopts" | ||
| "github.com/google/uuid" | ||
| "github.com/spf13/cobra" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/print" | ||
| "github.com/stackitcloud/stackit-sdk-go/services/ske" | ||
| ) | ||
| type testCtxKey struct{} | ||
| const ( | ||
| testRegion = "eu01" | ||
| testClusterName = "my-cluster" | ||
| ) | ||
| var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") | ||
| var testClient = &ske.APIClient{} | ||
| var testProjectId = uuid.NewString() | ||
| func fixtureArgValues(mods ...func(argValues []string)) []string { | ||
| argValues := []string{ | ||
| testClusterName, | ||
| } | ||
| for _, mod := range mods { | ||
| mod(argValues) | ||
| } | ||
| return argValues | ||
| } | ||
| func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { | ||
| flagValues := map[string]string{ | ||
| globalflags.ProjectIdFlag: testProjectId, | ||
| globalflags.RegionFlag: testRegion, | ||
| } | ||
| for _, mod := range mods { | ||
| mod(flagValues) | ||
| } | ||
| return flagValues | ||
| } | ||
| func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { | ||
| model := &inputModel{ | ||
| GlobalFlagModel: &globalflags.GlobalFlagModel{ | ||
| ProjectId: testProjectId, | ||
| Region: testRegion, | ||
| Verbosity: globalflags.VerbosityDefault, | ||
| }, | ||
| ClusterName: testClusterName, | ||
| } | ||
| for _, mod := range mods { | ||
| mod(model) | ||
| } | ||
| return model | ||
| } | ||
| func fixtureRequest(mods ...func(request *ske.ApiTriggerHibernateRequest)) ske.ApiTriggerHibernateRequest { | ||
| request := testClient.TriggerHibernate(testCtx, testProjectId, testRegion, testClusterName) | ||
| for _, mod := range mods { | ||
| mod(&request) | ||
| } | ||
| return request | ||
| } | ||
| func TestParseInput(t *testing.T) { | ||
| tests := []struct { | ||
| description string | ||
| argValues []string | ||
| flagValues map[string]string | ||
| isValid bool | ||
| expectedModel *inputModel | ||
| }{ | ||
| { | ||
| description: "base", | ||
| argValues: fixtureArgValues(), | ||
| flagValues: fixtureFlagValues(), | ||
| isValid: true, | ||
| expectedModel: fixtureInputModel(), | ||
| }, | ||
| { | ||
| description: "missing project id", | ||
| argValues: fixtureArgValues(), | ||
| flagValues: fixtureFlagValues(func(fv map[string]string) { | ||
| delete(fv, globalflags.ProjectIdFlag) | ||
| }), | ||
| isValid: false, | ||
| }, | ||
| { | ||
| description: "invalid project id - empty string", | ||
| argValues: fixtureArgValues(), | ||
| flagValues: fixtureFlagValues(func(fv map[string]string) { | ||
| fv[globalflags.ProjectIdFlag] = "" | ||
| }), | ||
| isValid: false, | ||
| }, | ||
| { | ||
| description: "invalid uuid format", | ||
| argValues: fixtureArgValues(), | ||
| flagValues: fixtureFlagValues(func(fv map[string]string) { | ||
| fv[globalflags.ProjectIdFlag] = "not-a-uuid" | ||
| }), | ||
| isValid: false, | ||
| }, | ||
| } | ||
| for _, tt := range tests { | ||
| t.Run(tt.description, func(t *testing.T) { | ||
| p := print.NewPrinter() | ||
| cmd := &cobra.Command{} | ||
| err := globalflags.Configure(cmd.Flags()) | ||
| if err != nil { | ||
| t.Fatalf("configure global flags: %v", err) | ||
| } | ||
| for flag, value := range tt.flagValues { | ||
| err := cmd.Flags().Set(flag, value) | ||
| if err != nil { | ||
| if !tt.isValid { | ||
| return | ||
| } | ||
| t.Fatalf("setting flag --%s=%s: %v", flag, value, err) | ||
| } | ||
| } | ||
| if len(tt.argValues) == 0 { | ||
| _, err := parseInput(p, cmd, tt.argValues) | ||
| if err == nil && !tt.isValid { | ||
| t.Fatalf("expected error due to missing args") | ||
| } | ||
| return | ||
| } | ||
| model, err := parseInput(p, cmd, tt.argValues) | ||
| if err != nil { | ||
| if !tt.isValid { | ||
| return | ||
| } | ||
| t.Fatalf("error parsing flags: %v", err) | ||
| } | ||
| if !tt.isValid { | ||
| t.Fatalf("did not fail on invalid input") | ||
| } | ||
| diff := cmp.Diff(model, tt.expectedModel) | ||
| if diff != "" { | ||
| t.Fatalf("data does not match:\n%s", diff) | ||
| } | ||
| }) | ||
| } | ||
| } | ||
| func TestBuildRequest(t *testing.T) { | ||
| tests := []struct { | ||
| description string | ||
| model *inputModel | ||
| expectedRequest ske.ApiTriggerHibernateRequest | ||
| }{ | ||
| { | ||
| description: "base", | ||
| model: fixtureInputModel(), | ||
| expectedRequest: fixtureRequest(), | ||
| }, | ||
| } | ||
| for _, tt := range tests { | ||
| t.Run(tt.description, func(t *testing.T) { | ||
| request := buildRequest(testCtx, tt.model, testClient) | ||
| diff := cmp.Diff(request, tt.expectedRequest, | ||
| cmpopts.EquateComparable(testCtx), | ||
| cmp.AllowUnexported(tt.expectedRequest), | ||
| ) | ||
| if diff != "" { | ||
| t.Fatalf("request mismatch:\n%s", diff) | ||
| } | ||
| }) | ||
| } | ||
| } |
| package hibernate | ||
| import ( | ||
| "context" | ||
| "fmt" | ||
| "github.com/spf13/cobra" | ||
| "github.com/stackitcloud/stackit-cli/internal/cmd/params" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/args" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/errors" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/examples" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/print" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/services/ske/client" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" | ||
| "github.com/stackitcloud/stackit-sdk-go/services/ske" | ||
| "github.com/stackitcloud/stackit-sdk-go/services/ske/wait" | ||
| ) | ||
| const ( | ||
| clusterNameArg = "CLUSTER_NAME" | ||
| ) | ||
| type inputModel struct { | ||
| *globalflags.GlobalFlagModel | ||
| ClusterName string | ||
| } | ||
| func NewCmd(params *params.CmdParams) *cobra.Command { | ||
| cmd := &cobra.Command{ | ||
| Use: fmt.Sprintf("hibernate %s", clusterNameArg), | ||
| Short: "Trigger hibernate for a SKE cluster", | ||
| Long: "Trigger hibernate for a STACKIT Kubernetes Engine (SKE) cluster.", | ||
| Args: args.SingleArg(clusterNameArg, nil), | ||
| Example: examples.Build( | ||
| examples.NewExample( | ||
| `Trigger hibernate for a SKE cluster with name "my-cluster"`, | ||
| "$ stackit ske cluster hibernate my-cluster"), | ||
| ), | ||
| RunE: func(cmd *cobra.Command, args []string) error { | ||
| ctx := context.Background() | ||
| model, err := parseInput(params.Printer, cmd, args) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| // Configure API client | ||
| apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| projectLabel, err := projectname.GetProjectName(ctx, params.Printer, params.CliVersion, cmd) | ||
| if err != nil { | ||
| params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) | ||
| projectLabel = model.ProjectId | ||
| } | ||
| if !model.AssumeYes { | ||
| prompt := fmt.Sprintf("Are you sure you want to trigger hibernate for %q in project %q?", model.ClusterName, projectLabel) | ||
| err = params.Printer.PromptForConfirmation(prompt) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| } | ||
| // Call API | ||
| req := buildRequest(ctx, model, apiClient) | ||
| _, err = req.Execute() | ||
| if err != nil { | ||
| return fmt.Errorf("hibernate SKE cluster: %w", err) | ||
| } | ||
| // Wait for async operation, if async mode not enabled | ||
| if !model.Async { | ||
| s := spinner.New(params.Printer) | ||
| s.Start("Hibernating cluster") | ||
| _, err = wait.TriggerClusterHibernationWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx) | ||
| if err != nil { | ||
| return fmt.Errorf("wait for SKE cluster hibernation: %w", err) | ||
| } | ||
| s.Stop() | ||
| } | ||
| operationState := "Hibernated" | ||
| if model.Async { | ||
| operationState = "Triggered hibernation of" | ||
| } | ||
| params.Printer.Outputf("%s cluster %q\n", operationState, model.ClusterName) | ||
| return nil | ||
| }, | ||
| } | ||
| return cmd | ||
| } | ||
| func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { | ||
| clusterName := inputArgs[0] | ||
| globalFlags := globalflags.Parse(p, cmd) | ||
| if globalFlags.ProjectId == "" { | ||
| return nil, &errors.ProjectIdError{} | ||
| } | ||
| model := inputModel{ | ||
| GlobalFlagModel: globalFlags, | ||
| ClusterName: clusterName, | ||
| } | ||
| if p.IsVerbosityDebug() { | ||
| modelStr, err := print.BuildDebugStrFromInputModel(model) | ||
| if err != nil { | ||
| p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) | ||
| } else { | ||
| p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) | ||
| } | ||
| } | ||
| return &model, nil | ||
| } | ||
| func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClient) ske.ApiTriggerHibernateRequest { | ||
| req := apiClient.TriggerHibernate(ctx, model.ProjectId, model.Region, model.ClusterName) | ||
| return req | ||
| } |
| package maintenance | ||
| import ( | ||
| "context" | ||
| "testing" | ||
| "github.com/google/go-cmp/cmp" | ||
| "github.com/google/go-cmp/cmp/cmpopts" | ||
| "github.com/google/uuid" | ||
| "github.com/spf13/cobra" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/print" | ||
| "github.com/stackitcloud/stackit-sdk-go/services/ske" | ||
| ) | ||
| type testCtxKey struct{} | ||
| const ( | ||
| testRegion = "eu01" | ||
| testClusterName = "my-cluster" | ||
| ) | ||
| var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") | ||
| var testClient = &ske.APIClient{} | ||
| var testProjectId = uuid.NewString() | ||
| func fixtureArgValues(mods ...func([]string)) []string { | ||
| argValues := []string{ | ||
| testClusterName, | ||
| } | ||
| for _, m := range mods { | ||
| m(argValues) | ||
| } | ||
| return argValues | ||
| } | ||
| func fixtureFlagValues(mods ...func(map[string]string)) map[string]string { | ||
| flagValues := map[string]string{ | ||
| globalflags.ProjectIdFlag: testProjectId, | ||
| globalflags.RegionFlag: testRegion, | ||
| } | ||
| for _, m := range mods { | ||
| m(flagValues) | ||
| } | ||
| return flagValues | ||
| } | ||
| func fixtureInputModel(mods ...func(*inputModel)) *inputModel { | ||
| model := &inputModel{ | ||
| GlobalFlagModel: &globalflags.GlobalFlagModel{ | ||
| ProjectId: testProjectId, | ||
| Region: testRegion, | ||
| Verbosity: globalflags.VerbosityDefault, | ||
| }, | ||
| ClusterName: testClusterName, | ||
| } | ||
| for _, m := range mods { | ||
| m(model) | ||
| } | ||
| return model | ||
| } | ||
| func fixtureRequest(mods ...func(*ske.ApiTriggerMaintenanceRequest)) ske.ApiTriggerMaintenanceRequest { | ||
| request := testClient.TriggerMaintenance(testCtx, testProjectId, testRegion, testClusterName) | ||
| for _, m := range mods { | ||
| m(&request) | ||
| } | ||
| return request | ||
| } | ||
| func TestParseInput(t *testing.T) { | ||
| tests := []struct { | ||
| description string | ||
| argValues []string | ||
| flagValues map[string]string | ||
| isValid bool | ||
| expectedModel *inputModel | ||
| }{ | ||
| { | ||
| description: "base", | ||
| argValues: fixtureArgValues(), | ||
| flagValues: fixtureFlagValues(), | ||
| isValid: true, | ||
| expectedModel: fixtureInputModel(), | ||
| }, | ||
| { | ||
| description: "missing project id", | ||
| argValues: fixtureArgValues(), | ||
| flagValues: fixtureFlagValues(func(fv map[string]string) { | ||
| delete(fv, globalflags.ProjectIdFlag) | ||
| }), | ||
| isValid: false, | ||
| }, | ||
| { | ||
| description: "invalid project id - empty string", | ||
| argValues: fixtureArgValues(), | ||
| flagValues: fixtureFlagValues(func(fv map[string]string) { | ||
| fv[globalflags.ProjectIdFlag] = "" | ||
| }), | ||
| isValid: false, | ||
| }, | ||
| { | ||
| description: "invalid uuid format", | ||
| argValues: fixtureArgValues(), | ||
| flagValues: fixtureFlagValues(func(fv map[string]string) { | ||
| fv[globalflags.ProjectIdFlag] = "not-a-uuid" | ||
| }), | ||
| isValid: false, | ||
| }, | ||
| } | ||
| for _, tt := range tests { | ||
| t.Run(tt.description, func(t *testing.T) { | ||
| p := print.NewPrinter() | ||
| cmd := &cobra.Command{} | ||
| err := globalflags.Configure(cmd.Flags()) | ||
| if err != nil { | ||
| t.Fatalf("configure global flags: %v", err) | ||
| } | ||
| for flag, value := range tt.flagValues { | ||
| err := cmd.Flags().Set(flag, value) | ||
| if err != nil { | ||
| if !tt.isValid { | ||
| return | ||
| } | ||
| t.Fatalf("setting flag --%s=%s: %v", flag, value, err) | ||
| } | ||
| } | ||
| if len(tt.argValues) == 0 { | ||
| _, err := parseInput(p, cmd, tt.argValues) | ||
| if err == nil && !tt.isValid { | ||
| t.Fatalf("expected error due to missing args") | ||
| } | ||
| return | ||
| } | ||
| model, err := parseInput(p, cmd, tt.argValues) | ||
| if err != nil { | ||
| if !tt.isValid { | ||
| return | ||
| } | ||
| t.Fatalf("error parsing input: %v", err) | ||
| } | ||
| if !tt.isValid { | ||
| t.Fatalf("did not fail on invalid input") | ||
| } | ||
| diff := cmp.Diff(model, tt.expectedModel) | ||
| if diff != "" { | ||
| t.Fatalf("input model mismatch:\n%s", diff) | ||
| } | ||
| }) | ||
| } | ||
| } | ||
| func TestBuildRequest(t *testing.T) { | ||
| tests := []struct { | ||
| description string | ||
| model *inputModel | ||
| expectedRequest ske.ApiTriggerMaintenanceRequest | ||
| }{ | ||
| { | ||
| description: "base", | ||
| model: fixtureInputModel(), | ||
| expectedRequest: fixtureRequest(), | ||
| }, | ||
| } | ||
| for _, tt := range tests { | ||
| t.Run(tt.description, func(t *testing.T) { | ||
| got := buildRequest(testCtx, tt.model, testClient) | ||
| want := tt.expectedRequest | ||
| diff := cmp.Diff(got, want, | ||
| cmpopts.EquateComparable(testCtx), | ||
| cmp.AllowUnexported(want), | ||
| ) | ||
| if diff != "" { | ||
| t.Fatalf("request mismatch:\n%s", diff) | ||
| } | ||
| }) | ||
| } | ||
| } |
| package maintenance | ||
| import ( | ||
| "context" | ||
| "fmt" | ||
| "github.com/spf13/cobra" | ||
| "github.com/stackitcloud/stackit-cli/internal/cmd/params" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/args" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/errors" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/examples" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/print" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/services/ske/client" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" | ||
| "github.com/stackitcloud/stackit-sdk-go/services/ske" | ||
| "github.com/stackitcloud/stackit-sdk-go/services/ske/wait" | ||
| ) | ||
| const ( | ||
| clusterNameArg = "CLUSTER_NAME" | ||
| ) | ||
| type inputModel struct { | ||
| *globalflags.GlobalFlagModel | ||
| ClusterName string | ||
| } | ||
| func NewCmd(params *params.CmdParams) *cobra.Command { | ||
| cmd := &cobra.Command{ | ||
| Use: fmt.Sprintf("maintenance %s", clusterNameArg), | ||
| Short: "Trigger maintenance for a SKE cluster", | ||
| Long: "Trigger maintenance for a STACKIT Kubernetes Engine (SKE) cluster.", | ||
| Args: args.SingleArg(clusterNameArg, nil), | ||
| Example: examples.Build( | ||
| examples.NewExample( | ||
| `Trigger maintenance for a SKE cluster with name "my-cluster"`, | ||
| "$ stackit ske cluster maintenance my-cluster"), | ||
| ), | ||
| RunE: func(cmd *cobra.Command, args []string) error { | ||
| ctx := context.Background() | ||
| model, err := parseInput(params.Printer, cmd, args) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| // Configure API client | ||
| apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| projectLabel, err := projectname.GetProjectName(ctx, params.Printer, params.CliVersion, cmd) | ||
| if err != nil { | ||
| params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) | ||
| projectLabel = model.ProjectId | ||
| } | ||
| if !model.AssumeYes { | ||
| prompt := fmt.Sprintf("Are you sure you want to trigger maintenance for %q in project %q?", model.ClusterName, projectLabel) | ||
| err = params.Printer.PromptForConfirmation(prompt) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| } | ||
| // Call API | ||
| req := buildRequest(ctx, model, apiClient) | ||
| _, err = req.Execute() | ||
| if err != nil { | ||
| return fmt.Errorf("trigger maintenance SKE cluster: %w", err) | ||
| } | ||
| // Wait for async operation, if async mode not enabled | ||
| if !model.Async { | ||
| s := spinner.New(params.Printer) | ||
| s.Start("Performing cluster maintenance") | ||
| _, err = wait.TriggerClusterMaintenanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx) | ||
| if err != nil { | ||
| return fmt.Errorf("wait for SKE cluster maintenance to complete: %w", err) | ||
| } | ||
| s.Stop() | ||
| } | ||
| operationState := "Performed maintenance for" | ||
| if model.Async { | ||
| operationState = "Triggered maintenance for" | ||
| } | ||
| params.Printer.Outputf("%s cluster %q\n", operationState, model.ClusterName) | ||
| return nil | ||
| }, | ||
| } | ||
| return cmd | ||
| } | ||
| func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { | ||
| clusterName := inputArgs[0] | ||
| globalFlags := globalflags.Parse(p, cmd) | ||
| if globalFlags.ProjectId == "" { | ||
| return nil, &errors.ProjectIdError{} | ||
| } | ||
| model := inputModel{ | ||
| GlobalFlagModel: globalFlags, | ||
| ClusterName: clusterName, | ||
| } | ||
| if p.IsVerbosityDebug() { | ||
| modelStr, err := print.BuildDebugStrFromInputModel(model) | ||
| if err != nil { | ||
| p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) | ||
| } else { | ||
| p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) | ||
| } | ||
| } | ||
| return &model, nil | ||
| } | ||
| func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClient) ske.ApiTriggerMaintenanceRequest { | ||
| req := apiClient.TriggerMaintenance(ctx, model.ProjectId, model.Region, model.ClusterName) | ||
| return req | ||
| } |
| package reconcile | ||
| import ( | ||
| "context" | ||
| "testing" | ||
| "github.com/google/go-cmp/cmp" | ||
| "github.com/google/go-cmp/cmp/cmpopts" | ||
| "github.com/google/uuid" | ||
| "github.com/spf13/cobra" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/print" | ||
| "github.com/stackitcloud/stackit-sdk-go/services/ske" | ||
| ) | ||
| type testCtxKey struct{} | ||
| const ( | ||
| testRegion = "eu01" | ||
| testClusterName = "my-cluster" | ||
| ) | ||
| var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") | ||
| var testClient = &ske.APIClient{} | ||
| var testProjectId = uuid.NewString() | ||
| func fixtureArgValues(mods ...func([]string)) []string { | ||
| argValues := []string{ | ||
| testClusterName, | ||
| } | ||
| for _, m := range mods { | ||
| m(argValues) | ||
| } | ||
| return argValues | ||
| } | ||
| func fixtureFlagValues(mods ...func(map[string]string)) map[string]string { | ||
| flagValues := map[string]string{ | ||
| globalflags.ProjectIdFlag: testProjectId, | ||
| globalflags.RegionFlag: testRegion, | ||
| } | ||
| for _, m := range mods { | ||
| m(flagValues) | ||
| } | ||
| return flagValues | ||
| } | ||
| func fixtureInputModel(mods ...func(*inputModel)) *inputModel { | ||
| model := &inputModel{ | ||
| GlobalFlagModel: &globalflags.GlobalFlagModel{ | ||
| ProjectId: testProjectId, | ||
| Region: testRegion, | ||
| Verbosity: globalflags.VerbosityDefault, | ||
| }, | ||
| ClusterName: testClusterName, | ||
| } | ||
| for _, m := range mods { | ||
| m(model) | ||
| } | ||
| return model | ||
| } | ||
| func fixtureRequest(mods ...func(request *ske.ApiTriggerReconcileRequest)) ske.ApiTriggerHibernateRequest { | ||
| request := testClient.TriggerReconcile(testCtx, testProjectId, testRegion, testClusterName) | ||
| for _, m := range mods { | ||
| m(&request) | ||
| } | ||
| return request | ||
| } | ||
| func TestParseInput(t *testing.T) { | ||
| tests := []struct { | ||
| description string | ||
| argValues []string | ||
| flagValues map[string]string | ||
| isValid bool | ||
| expectedModel *inputModel | ||
| }{ | ||
| { | ||
| description: "base", | ||
| argValues: fixtureArgValues(), | ||
| flagValues: fixtureFlagValues(), | ||
| isValid: true, | ||
| expectedModel: fixtureInputModel(), | ||
| }, | ||
| { | ||
| description: "missing project id", | ||
| argValues: fixtureArgValues(), | ||
| flagValues: fixtureFlagValues(func(fv map[string]string) { | ||
| delete(fv, globalflags.ProjectIdFlag) | ||
| }), | ||
| isValid: false, | ||
| }, | ||
| { | ||
| description: "invalid project id - empty string", | ||
| argValues: fixtureArgValues(), | ||
| flagValues: fixtureFlagValues(func(fv map[string]string) { | ||
| fv[globalflags.ProjectIdFlag] = "" | ||
| }), | ||
| isValid: false, | ||
| }, | ||
| { | ||
| description: "invalid uuid format", | ||
| argValues: fixtureArgValues(), | ||
| flagValues: fixtureFlagValues(func(fv map[string]string) { | ||
| fv[globalflags.ProjectIdFlag] = "not-a-uuid" | ||
| }), | ||
| isValid: false, | ||
| }, | ||
| } | ||
| for _, tt := range tests { | ||
| t.Run(tt.description, func(t *testing.T) { | ||
| p := print.NewPrinter() | ||
| cmd := &cobra.Command{} | ||
| err := globalflags.Configure(cmd.Flags()) | ||
| if err != nil { | ||
| t.Fatalf("configure global flags: %v", err) | ||
| } | ||
| for flag, value := range tt.flagValues { | ||
| err := cmd.Flags().Set(flag, value) | ||
| if err != nil { | ||
| if !tt.isValid { | ||
| return | ||
| } | ||
| t.Fatalf("setting flag --%s=%s: %v", flag, value, err) | ||
| } | ||
| } | ||
| if len(tt.argValues) == 0 { | ||
| _, err := parseInput(p, cmd, tt.argValues) | ||
| if err == nil && !tt.isValid { | ||
| t.Fatalf("expected error due to missing args") | ||
| } | ||
| return | ||
| } | ||
| model, err := parseInput(p, cmd, tt.argValues) | ||
| if err != nil { | ||
| if !tt.isValid { | ||
| return | ||
| } | ||
| t.Fatalf("error parsing input: %v", err) | ||
| } | ||
| if !tt.isValid { | ||
| t.Fatalf("did not fail on invalid input") | ||
| } | ||
| diff := cmp.Diff(model, tt.expectedModel) | ||
| if diff != "" { | ||
| t.Fatalf("input model mismatch:\n%s", diff) | ||
| } | ||
| }) | ||
| } | ||
| } | ||
| func TestBuildRequest(t *testing.T) { | ||
| tests := []struct { | ||
| description string | ||
| model *inputModel | ||
| expectedRequest ske.ApiTriggerHibernateRequest | ||
| }{ | ||
| { | ||
| description: "base", | ||
| model: fixtureInputModel(), | ||
| expectedRequest: fixtureRequest(), | ||
| }, | ||
| } | ||
| for _, tt := range tests { | ||
| t.Run(tt.description, func(t *testing.T) { | ||
| got := buildRequest(testCtx, tt.model, testClient) | ||
| want := tt.expectedRequest | ||
| diff := cmp.Diff(got, want, | ||
| cmpopts.EquateComparable(testCtx), | ||
| cmp.AllowUnexported(want), | ||
| ) | ||
| if diff != "" { | ||
| t.Fatalf("request mismatch:\n%s", diff) | ||
| } | ||
| }) | ||
| } | ||
| } |
| package reconcile | ||
| import ( | ||
| "context" | ||
| "fmt" | ||
| "github.com/spf13/cobra" | ||
| "github.com/stackitcloud/stackit-cli/internal/cmd/params" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/args" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/errors" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/examples" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/print" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/services/ske/client" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" | ||
| "github.com/stackitcloud/stackit-sdk-go/services/ske" | ||
| "github.com/stackitcloud/stackit-sdk-go/services/ske/wait" | ||
| ) | ||
| const ( | ||
| clusterNameArg = "CLUSTER_NAME" | ||
| ) | ||
| type inputModel struct { | ||
| *globalflags.GlobalFlagModel | ||
| ClusterName string | ||
| } | ||
| func NewCmd(params *params.CmdParams) *cobra.Command { | ||
| cmd := &cobra.Command{ | ||
| Use: fmt.Sprintf("reconcile %s", clusterNameArg), | ||
| Short: "Trigger reconcile for a SKE cluster", | ||
| Long: "Trigger reconcile for a STACKIT Kubernetes Engine (SKE) cluster.", | ||
| Args: args.SingleArg(clusterNameArg, nil), | ||
| Example: examples.Build( | ||
| examples.NewExample( | ||
| `Trigger reconcile for a SKE cluster with name "my-cluster"`, | ||
| "$ stackit ske cluster reconcile my-cluster"), | ||
| ), | ||
| RunE: func(cmd *cobra.Command, args []string) error { | ||
| ctx := context.Background() | ||
| model, err := parseInput(params.Printer, cmd, args) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| // Configure API client | ||
| apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| // Call API | ||
| req := buildRequest(ctx, model, apiClient) | ||
| _, err = req.Execute() | ||
| if err != nil { | ||
| return fmt.Errorf("reconcile SKE cluster: %w", err) | ||
| } | ||
| // Wait for async operation, if async mode not enabled | ||
| if !model.Async { | ||
| s := spinner.New(params.Printer) | ||
| s.Start("Performing cluster reconciliation") | ||
| _, err = wait.TriggerClusterReconciliationWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx) | ||
| if err != nil { | ||
| return fmt.Errorf("wait for SKE cluster reconciliation: %w", err) | ||
| } | ||
| s.Stop() | ||
| } | ||
| operationState := "Performed reconciliation for" | ||
| if model.Async { | ||
| operationState = "Triggered reconcile for" | ||
| } | ||
| params.Printer.Outputf("%s cluster %q\n", operationState, model.ClusterName) | ||
| return nil | ||
| }, | ||
| } | ||
| return cmd | ||
| } | ||
| func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { | ||
| clusterName := inputArgs[0] | ||
| globalFlags := globalflags.Parse(p, cmd) | ||
| if globalFlags.ProjectId == "" { | ||
| return nil, &errors.ProjectIdError{} | ||
| } | ||
| model := inputModel{ | ||
| GlobalFlagModel: globalFlags, | ||
| ClusterName: clusterName, | ||
| } | ||
| if p.IsVerbosityDebug() { | ||
| modelStr, err := print.BuildDebugStrFromInputModel(model) | ||
| if err != nil { | ||
| p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) | ||
| } else { | ||
| p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) | ||
| } | ||
| } | ||
| return &model, nil | ||
| } | ||
| func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClient) ske.ApiTriggerReconcileRequest { | ||
| req := apiClient.TriggerReconcile(ctx, model.ProjectId, model.Region, model.ClusterName) | ||
| return req | ||
| } |
| package wakeup | ||
| import ( | ||
| "context" | ||
| "testing" | ||
| "github.com/google/go-cmp/cmp" | ||
| "github.com/google/go-cmp/cmp/cmpopts" | ||
| "github.com/google/uuid" | ||
| "github.com/spf13/cobra" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/print" | ||
| "github.com/stackitcloud/stackit-sdk-go/services/ske" | ||
| ) | ||
| type testCtxKey struct{} | ||
| const ( | ||
| testRegion = "eu01" | ||
| testClusterName = "my-cluster" | ||
| ) | ||
| var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") | ||
| var testClient = &ske.APIClient{} | ||
| var testProjectId = uuid.NewString() | ||
| func fixtureArgValues(mods ...func([]string)) []string { | ||
| argValues := []string{testClusterName} | ||
| for _, m := range mods { | ||
| m(argValues) | ||
| } | ||
| return argValues | ||
| } | ||
| func fixtureFlagValues(mods ...func(map[string]string)) map[string]string { | ||
| flags := map[string]string{ | ||
| globalflags.ProjectIdFlag: testProjectId, | ||
| globalflags.RegionFlag: testRegion, | ||
| } | ||
| for _, m := range mods { | ||
| m(flags) | ||
| } | ||
| return flags | ||
| } | ||
| func fixtureInputModel(mods ...func(*inputModel)) *inputModel { | ||
| model := &inputModel{ | ||
| GlobalFlagModel: &globalflags.GlobalFlagModel{ | ||
| ProjectId: testProjectId, | ||
| Region: testRegion, | ||
| Verbosity: globalflags.VerbosityDefault, | ||
| }, | ||
| ClusterName: testClusterName, | ||
| } | ||
| for _, m := range mods { | ||
| m(model) | ||
| } | ||
| return model | ||
| } | ||
| func fixtureRequest(mods ...func(*ske.ApiTriggerWakeupRequest)) ske.ApiTriggerWakeupRequest { | ||
| req := testClient.TriggerWakeup(testCtx, testProjectId, testRegion, testClusterName) | ||
| for _, m := range mods { | ||
| m(&req) | ||
| } | ||
| return req | ||
| } | ||
| func TestParseInput(t *testing.T) { | ||
| tests := []struct { | ||
| description string | ||
| argValues []string | ||
| flagValues map[string]string | ||
| isValid bool | ||
| expectedModel *inputModel | ||
| }{ | ||
| { | ||
| description: "base", | ||
| argValues: fixtureArgValues(), | ||
| flagValues: fixtureFlagValues(), | ||
| isValid: true, | ||
| expectedModel: fixtureInputModel(), | ||
| }, | ||
| { | ||
| description: "missing project id", | ||
| argValues: fixtureArgValues(), | ||
| flagValues: fixtureFlagValues(func(fv map[string]string) { | ||
| delete(fv, globalflags.ProjectIdFlag) | ||
| }), | ||
| isValid: false, | ||
| }, | ||
| { | ||
| description: "invalid project id - empty string", | ||
| argValues: fixtureArgValues(), | ||
| flagValues: fixtureFlagValues(func(fv map[string]string) { | ||
| fv[globalflags.ProjectIdFlag] = "" | ||
| }), | ||
| isValid: false, | ||
| }, | ||
| { | ||
| description: "invalid uuid format", | ||
| argValues: fixtureArgValues(), | ||
| flagValues: fixtureFlagValues(func(fv map[string]string) { | ||
| fv[globalflags.ProjectIdFlag] = "not-a-uuid" | ||
| }), | ||
| isValid: false, | ||
| }, | ||
| } | ||
| for _, tt := range tests { | ||
| t.Run(tt.description, func(t *testing.T) { | ||
| p := print.NewPrinter() | ||
| cmd := &cobra.Command{} | ||
| err := globalflags.Configure(cmd.Flags()) | ||
| if err != nil { | ||
| t.Fatalf("configure global flags: %v", err) | ||
| } | ||
| for flag, value := range tt.flagValues { | ||
| err := cmd.Flags().Set(flag, value) | ||
| if err != nil { | ||
| if !tt.isValid { | ||
| return | ||
| } | ||
| t.Fatalf("setting flag --%s=%s: %v", flag, value, err) | ||
| } | ||
| } | ||
| if len(tt.argValues) == 0 { | ||
| _, err := parseInput(p, cmd, tt.argValues) | ||
| if err == nil && !tt.isValid { | ||
| t.Fatalf("expected failure due to missing args") | ||
| } | ||
| return | ||
| } | ||
| model, err := parseInput(p, cmd, tt.argValues) | ||
| if err != nil { | ||
| if !tt.isValid { | ||
| return | ||
| } | ||
| t.Fatalf("unexpected error: %v", err) | ||
| } | ||
| if !tt.isValid { | ||
| t.Fatalf("did not fail on invalid input") | ||
| } | ||
| diff := cmp.Diff(model, tt.expectedModel) | ||
| if diff != "" { | ||
| t.Fatalf("input model mismatch:\n%s", diff) | ||
| } | ||
| }) | ||
| } | ||
| } | ||
| func TestBuildRequest(t *testing.T) { | ||
| tests := []struct { | ||
| description string | ||
| model *inputModel | ||
| expectedRequest ske.ApiTriggerHibernateRequest | ||
| }{ | ||
| { | ||
| description: "base", | ||
| model: fixtureInputModel(), | ||
| expectedRequest: fixtureRequest(), | ||
| }, | ||
| } | ||
| for _, tt := range tests { | ||
| t.Run(tt.description, func(t *testing.T) { | ||
| got := buildRequest(testCtx, tt.model, testClient) | ||
| want := tt.expectedRequest | ||
| diff := cmp.Diff(got, want, | ||
| cmpopts.EquateComparable(testCtx), | ||
| cmp.AllowUnexported(want), | ||
| ) | ||
| if diff != "" { | ||
| t.Fatalf("request mismatch:\n%s", diff) | ||
| } | ||
| }) | ||
| } | ||
| } |
| package wakeup | ||
| import ( | ||
| "context" | ||
| "fmt" | ||
| "github.com/spf13/cobra" | ||
| "github.com/stackitcloud/stackit-cli/internal/cmd/params" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/args" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/errors" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/examples" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/print" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/services/ske/client" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" | ||
| "github.com/stackitcloud/stackit-sdk-go/services/ske" | ||
| "github.com/stackitcloud/stackit-sdk-go/services/ske/wait" | ||
| ) | ||
| const ( | ||
| clusterNameArg = "CLUSTER_NAME" | ||
| ) | ||
| type inputModel struct { | ||
| *globalflags.GlobalFlagModel | ||
| ClusterName string | ||
| } | ||
| func NewCmd(params *params.CmdParams) *cobra.Command { | ||
| cmd := &cobra.Command{ | ||
| Use: fmt.Sprintf("wakeup %s", clusterNameArg), | ||
| Short: "Trigger wakeup from hibernation for a SKE cluster", | ||
| Long: "Trigger wakeup from hibernation for a STACKIT Kubernetes Engine (SKE) cluster.", | ||
| Args: args.SingleArg(clusterNameArg, nil), | ||
| Example: examples.Build( | ||
| examples.NewExample( | ||
| `Trigger wakeup from hibernation for a SKE cluster with name "my-cluster"`, | ||
| "$ stackit ske cluster wakeup my-cluster"), | ||
| ), | ||
| RunE: func(cmd *cobra.Command, args []string) error { | ||
| ctx := context.Background() | ||
| model, err := parseInput(params.Printer, cmd, args) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| // Configure API client | ||
| apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| // Call API | ||
| req := buildRequest(ctx, model, apiClient) | ||
| _, err = req.Execute() | ||
| if err != nil { | ||
| return fmt.Errorf("wakeup SKE cluster: %w", err) | ||
| } | ||
| // Wait for async operation, if async mode not enabled | ||
| if !model.Async { | ||
| s := spinner.New(params.Printer) | ||
| s.Start("Performing cluster wakeup") | ||
| _, err = wait.TriggerClusterWakeupWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx) | ||
| if err != nil { | ||
| return fmt.Errorf("wait for SKE cluster wakeup: %w", err) | ||
| } | ||
| s.Stop() | ||
| } | ||
| operationState := "Performed wakeup of" | ||
| if model.Async { | ||
| operationState = "Triggered wakeup of" | ||
| } | ||
| params.Printer.Outputf("%s cluster %q\n", operationState, model.ClusterName) | ||
| return nil | ||
| }, | ||
| } | ||
| return cmd | ||
| } | ||
| func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { | ||
| clusterName := inputArgs[0] | ||
| globalFlags := globalflags.Parse(p, cmd) | ||
| if globalFlags.ProjectId == "" { | ||
| return nil, &errors.ProjectIdError{} | ||
| } | ||
| model := inputModel{ | ||
| GlobalFlagModel: globalFlags, | ||
| ClusterName: clusterName, | ||
| } | ||
| if p.IsVerbosityDebug() { | ||
| modelStr, err := print.BuildDebugStrFromInputModel(model) | ||
| if err != nil { | ||
| p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) | ||
| } else { | ||
| p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) | ||
| } | ||
| } | ||
| return &model, nil | ||
| } | ||
| func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClient) ske.ApiTriggerWakeupRequest { | ||
| req := apiClient.TriggerWakeup(ctx, model.ProjectId, model.Region, model.ClusterName) | ||
| return req | ||
| } |
| #!/bin/bash | ||
| # This script is used to publish new packages to the CLI RPM repository | ||
| # Usage: ./publish-rpm-packages.sh | ||
| set -eo pipefail | ||
| ROOT_DIR=$(git rev-parse --show-toplevel) | ||
| PACKAGES_BUCKET_URL="https://packages.stackit.cloud" | ||
| RPM_REPO_PATH="rpm/cli" | ||
| RPM_BUCKET_NAME="distribution" | ||
| CUSTOM_KEYRING_FILE="rpm-keyring.gpg" | ||
| GORELEASER_PACKAGES_FOLDER="dist/" | ||
| TEMP_DIR=$(mktemp -d) | ||
| # We need to disable the key database daemon (keyboxd) | ||
| # This can be done by removing "use-keyboxd" from ~/.gnupg/common.conf (see https://github.com/gpg/gnupg/blob/master/README) | ||
| echo -n >~/.gnupg/common.conf | ||
| # Create a local mirror of the current state of the remote RPM repository | ||
| printf ">>> Creating mirror \n" | ||
| curl ${PACKAGES_BUCKET_URL}/${RPM_REPO_PATH}/repodata/repomd.xml >${TEMP_DIR}/repomd.xml || echo "No existing repository found, creating new one" | ||
| # Create RPM repository structure | ||
| mkdir -p ${TEMP_DIR}/rpm-repo/RPMS | ||
| # Copy existing RPMs from remote repository (if any) | ||
| printf "\n>>> Downloading existing RPMs \n" | ||
| aws s3 sync s3://${RPM_BUCKET_NAME}/${RPM_REPO_PATH}/RPMS/ ${TEMP_DIR}/rpm-repo/RPMS/ --endpoint-url https://object.storage.eu01.onstackit.cloud || echo "No existing RPMs found" | ||
| # Copy new generated .rpm packages to the local repo | ||
| # Note: GoReleaser already signs these RPM packages with embedded signatures | ||
| printf "\n>>> Adding new packages to local repo \n" | ||
| cp ${GORELEASER_PACKAGES_FOLDER}/*.rpm ${TEMP_DIR}/rpm-repo/RPMS/ | ||
| # Create RPM repository metadata using createrepo_c in Docker | ||
| printf "\n>>> Creating RPM repository metadata \n" | ||
| docker run --rm \ | ||
| -v "${TEMP_DIR}/rpm-repo:/repo" \ | ||
| fedora:latest \ | ||
| bash -c " | ||
| # Install createrepo_c | ||
| dnf install -y createrepo_c | ||
| # Create repository metadata | ||
| createrepo_c /repo | ||
| " | ||
| # Sign the repository metadata using the same GPG key as APT | ||
| if [ -n "$GPG_PRIVATE_KEY_FINGERPRINT" ] && [ -n "$GPG_PASSPHRASE" ]; then | ||
| printf "\n>>> Signing repository metadata \n" | ||
| gpg --batch --yes --pinentry-mode loopback --local-user="${GPG_PRIVATE_KEY_FINGERPRINT}" --passphrase="${GPG_PASSPHRASE}" --detach-sign --armor ${TEMP_DIR}/rpm-repo/repodata/repomd.xml | ||
| else | ||
| echo ">>> Skipping repository metadata signing (GPG environment variables not set)" | ||
| fi | ||
| # Upload to S3 | ||
| printf "\n>>> Uploading to S3 \n" | ||
| aws s3 sync ${TEMP_DIR}/rpm-repo/ s3://${RPM_BUCKET_NAME}/${RPM_REPO_PATH}/ --endpoint-url https://object.storage.eu01.onstackit.cloud | ||
| # Clean up | ||
| rm -rf ${TEMP_DIR} | ||
| printf "\n>>> RPM repository published successfully to ${PACKAGES_BUCKET_URL}/${RPM_REPO_PATH} \n" |
Sorry, the diff of this file is too big to display