From 37bfc668f0b26803cd54b48520e0fe8eb22499a8 Mon Sep 17 00:00:00 2001 From: tytv2 Date: Mon, 29 Jun 2026 15:34:46 +0700 Subject: [PATCH] fix(vks): align node group commands with latest API (drop image-id, add --os) The latest VKS API removed imageId from CreateNodeGroupDto/UpdateNodeGroupDto and the cluster create node group. The CLI still required --image-id and sent imageId, which is stale (update-nodegroup even forced a field the API ignores). - create-nodegroup, create-cluster: remove --image-id; add optional --os (ubuntu|linux, default ubuntu) sent as the `os` field - update-nodegroup: remove --image-id entirely; require at least one update field - completion: drop dead image-id completer (/node-group-images); add --os values - docs: replace image-id with --os (creates) / remove (update); fix examples BREAKING: --image-id is no longer accepted on these commands. Co-Authored-By: Claude Opus 4.8 (1M context) --- .changes/next-release/api-change-vks-4yuiroep.json | 5 +++++ docs/commands/vks/create-cluster.md | 12 ++++++------ docs/commands/vks/create-nodegroup.md | 12 ++++++------ docs/commands/vks/update-nodegroup.md | 12 ++---------- docs/usage/dry-run.md | 2 +- docs/usage/getting-started.md | 2 +- docs/usage/shell-completion.md | 2 +- go/cmd/vks/completion.go | 14 +------------- go/cmd/vks/create_cluster.go | 8 ++++---- go/cmd/vks/create_nodegroup.go | 8 ++++---- go/cmd/vks/update_nodegroup.go | 11 +++++------ 11 files changed, 36 insertions(+), 52 deletions(-) create mode 100644 .changes/next-release/api-change-vks-4yuiroep.json diff --git a/.changes/next-release/api-change-vks-4yuiroep.json b/.changes/next-release/api-change-vks-4yuiroep.json new file mode 100644 index 0000000..26cd050 --- /dev/null +++ b/.changes/next-release/api-change-vks-4yuiroep.json @@ -0,0 +1,5 @@ +{ + "type": "api-change", + "category": "vks", + "description": "Align node group commands with latest API: remove --image-id (no longer in the API), add --os (ubuntu/linux, default ubuntu) for create-cluster/create-nodegroup; update-nodegroup no longer requires/sends image" +} diff --git a/docs/commands/vks/create-cluster.md b/docs/commands/vks/create-cluster.md index 4946aa4..f62b9b2 100644 --- a/docs/commands/vks/create-cluster.md +++ b/docs/commands/vks/create-cluster.md @@ -21,7 +21,7 @@ grn vks create-cluster --subnet-id --node-group-name --flavor-id - --image-id + [--os ] --disk-type --ssh-key-id [--cidr ] @@ -92,8 +92,8 @@ grn vks create-cluster `--flavor-id` (required) : Flavor (instance type) ID for the nodes. -`--image-id` (required) -: OS image ID for the nodes. +`--os` (optional, default `ubuntu`) +: Node group OS image. Supported values: `ubuntu`, `linux`. `--disk-type` (required) : Disk type ID for the node boot volumes. @@ -135,7 +135,7 @@ grn vks create-cluster \ --subnet-id sub-abc12345-0000-0000-0000-000000000001 \ --node-group-name default-ng \ --flavor-id flv-2c4g \ - --image-id img-ubuntu-22-04-k8s \ + --os ubuntu \ --disk-type SSD \ --ssh-key-id key-abc12345-0000-0000-0000-000000000001 ``` @@ -152,7 +152,7 @@ grn vks create-cluster \ --subnet-id sub-abc12345-0000-0000-0000-000000000001 \ --node-group-name prod-ng \ --flavor-id flv-4c8g \ - --image-id img-ubuntu-22-04-k8s \ + --os ubuntu \ --disk-type SSD \ --disk-size 200 \ --num-nodes 3 \ @@ -172,7 +172,7 @@ grn vks create-cluster \ --subnet-id sub-abc12345-0000-0000-0000-000000000001 \ --node-group-name default-ng \ --flavor-id flv-2c4g \ - --image-id img-ubuntu-22-04-k8s \ + --os ubuntu \ --disk-type SSD \ --ssh-key-id key-abc12345-0000-0000-0000-000000000001 \ --dry-run diff --git a/docs/commands/vks/create-nodegroup.md b/docs/commands/vks/create-nodegroup.md index 0f176df..00fbbfe 100644 --- a/docs/commands/vks/create-nodegroup.md +++ b/docs/commands/vks/create-nodegroup.md @@ -12,7 +12,7 @@ Use `--dry-run` to validate parameters (name format, disk size range, node count grn vks create-nodegroup --cluster-id --name - --image-id + [--os ] --flavor-id --disk-type --ssh-key-id @@ -35,8 +35,8 @@ grn vks create-nodegroup `--name` (required) : Node group name. Must be 5–15 characters, lowercase alphanumeric and hyphens, starting and ending with an alphanumeric character. -`--image-id` (required) -: OS image ID for the nodes. +`--os` (optional, default `ubuntu`) +: Node group OS image. Supported values: `ubuntu`, `linux`. `--flavor-id` (required) : Flavor (instance type) ID for the nodes. @@ -82,7 +82,7 @@ Create a basic node group: grn vks create-nodegroup \ --cluster-id cls-abc12345-6789-def0-1234-abcdef012345 \ --name worker-ng \ - --image-id img-ubuntu-22-04-k8s \ + --os ubuntu \ --flavor-id flv-4c8g \ --disk-type SSD \ --ssh-key-id key-abc12345-0000-0000-0000-000000000001 @@ -94,7 +94,7 @@ Create a GPU node group with taints and labels: grn vks create-nodegroup \ --cluster-id cls-abc12345-6789-def0-1234-abcdef012345 \ --name gpu-ng \ - --image-id img-ubuntu-22-04-k8s-gpu \ + --os ubuntu \ --flavor-id flv-8c32g-gpu \ --disk-type SSD \ --disk-size 200 \ @@ -111,7 +111,7 @@ Validate parameters without creating: grn vks create-nodegroup \ --cluster-id cls-abc12345-6789-def0-1234-abcdef012345 \ --name worker-ng \ - --image-id img-ubuntu-22-04-k8s \ + --os ubuntu \ --flavor-id flv-4c8g \ --disk-type SSD \ --ssh-key-id key-abc12345-0000-0000-0000-000000000001 \ diff --git a/docs/commands/vks/update-nodegroup.md b/docs/commands/vks/update-nodegroup.md index 643a3d4..d98a0ec 100644 --- a/docs/commands/vks/update-nodegroup.md +++ b/docs/commands/vks/update-nodegroup.md @@ -2,7 +2,7 @@ ## Description -Update a node group's image, node count, security groups, labels, taints, auto-scaling configuration, and upgrade strategy. The image ID is always required by the API, even when the intent is to update only other fields. +Update a node group's node count, security groups, labels, taints, auto-scaling configuration, and upgrade strategy. Use `--dry-run` to preview the update payload without executing it. @@ -12,7 +12,6 @@ Use `--dry-run` to preview the update payload without executing it. grn vks update-nodegroup --cluster-id --nodegroup-id - --image-id [--num-nodes ] [--security-groups ] [--labels ] @@ -33,9 +32,6 @@ grn vks update-nodegroup `--nodegroup-id` (required) : ID of the node group to update. -`--image-id` (required) -: OS image ID. Always required by the API — pass the current image ID to leave it unchanged. - `--num-nodes` (optional) : New desired number of nodes for the node group. @@ -74,17 +70,15 @@ Scale a node group to 5 nodes: grn vks update-nodegroup \ --cluster-id cls-abc12345-6789-def0-1234-abcdef012345 \ --nodegroup-id ng-abc12345-6789-def0-1234-abcdef012345 \ - --image-id img-ubuntu-22-04-k8s \ --num-nodes 5 ``` -Update node image and set auto-scaling limits: +Set auto-scaling limits: ```bash grn vks update-nodegroup \ --cluster-id cls-abc12345-6789-def0-1234-abcdef012345 \ --nodegroup-id ng-abc12345-6789-def0-1234-abcdef012345 \ - --image-id img-ubuntu-22-04-k8s-v2 \ --auto-scale-min 2 \ --auto-scale-max 10 ``` @@ -95,7 +89,6 @@ Update labels and taints: grn vks update-nodegroup \ --cluster-id cls-abc12345-6789-def0-1234-abcdef012345 \ --nodegroup-id ng-abc12345-6789-def0-1234-abcdef012345 \ - --image-id img-ubuntu-22-04-k8s \ --labels env=prod,tier=app \ --taints dedicated=gpu:NoSchedule ``` @@ -106,7 +99,6 @@ Preview the update payload (dry run): grn vks update-nodegroup \ --cluster-id cls-abc12345-6789-def0-1234-abcdef012345 \ --nodegroup-id ng-abc12345-6789-def0-1234-abcdef012345 \ - --image-id img-ubuntu-22-04-k8s \ --num-nodes 3 \ --dry-run ``` diff --git a/docs/usage/dry-run.md b/docs/usage/dry-run.md index 97f66bb..3796707 100644 --- a/docs/usage/dry-run.md +++ b/docs/usage/dry-run.md @@ -11,7 +11,7 @@ grn vks create-nodegroup --dry-run --cluster-id k8s-xxxxx --name workers ... # Preview update parameters grn vks update-cluster --dry-run --cluster-id k8s-xxxxx --k8s-version v1.31 --whitelist-node-cidrs 0.0.0.0/0 -grn vks update-nodegroup --dry-run --cluster-id k8s-xxxxx --nodegroup-id ng-xxxxx --image-id img-xxxxx +grn vks update-nodegroup --dry-run --cluster-id k8s-xxxxx --nodegroup-id ng-xxxxx --num-nodes 3 # Preview what will be deleted grn vks delete-cluster --dry-run --cluster-id k8s-xxxxx diff --git a/docs/usage/getting-started.md b/docs/usage/getting-started.md index 718b3af..e4ce871 100644 --- a/docs/usage/getting-started.md +++ b/docs/usage/getting-started.md @@ -40,7 +40,7 @@ grn vks create-cluster \ --cidr 192.168.0.0/16 \ --node-group-name default \ --flavor-id flav-xxxxx \ - --image-id img-xxxxx \ + --os ubuntu \ --disk-type vtype-xxxxx \ --ssh-key-id ssh-xxxxx diff --git a/docs/usage/shell-completion.md b/docs/usage/shell-completion.md index 1b2a0bc..b61ef71 100644 --- a/docs/usage/shell-completion.md +++ b/docs/usage/shell-completion.md @@ -52,7 +52,7 @@ grn completion powershell | Out-String | Invoke-Expression Beyond commands and flags, `grn` completes flag *values*: - Global: `--region`, `--output`, `--color`, `--profile` -- VKS: `--cluster-id`, `--nodegroup-id`, `--k8s-version`, `--image-id`, `--network-type`, `--release-channel` +- VKS: `--cluster-id`, `--nodegroup-id`, `--k8s-version`, `--os`, `--network-type`, `--release-channel` - vserver resources used by VKS: `--vpc-id`, `--subnet-id`, `--ssh-key-id`, `--security-groups`, `--disk-type` Resource-id completions call the API using your configured credentials and diff --git a/go/cmd/vks/completion.go b/go/cmd/vks/completion.go index fe5e0fa..797fa88 100644 --- a/go/cmd/vks/completion.go +++ b/go/cmd/vks/completion.go @@ -48,24 +48,12 @@ func fetchK8sVersions(_ context.Context, cmd *cobra.Command) ([]string, error) { return cli.ExtractIDs(res, "version", "name", "id"), nil } -func fetchImageIDs(_ context.Context, cmd *cobra.Command) ([]string, error) { - c, err := createClient(cmd) - if err != nil { - return nil, err - } - res, err := c.Get("/v1/node-group-images", nil) - if err != nil { - return nil, err - } - return cli.ExtractIDs(res, "id", "name"), nil -} - func flagCompleters() map[string]cli.CompFunc { return map[string]cli.CompFunc{ "cluster-id": cli.FlagFromAPI(fetchClusterIDs), "nodegroup-id": cli.FlagFromAPI(fetchNodegroupIDs), "k8s-version": cli.FlagFromAPI(fetchK8sVersions), - "image-id": cli.FlagFromAPI(fetchImageIDs), + "os": cli.FlagValues("ubuntu", "linux"), "network-type": cli.FlagValues("CALICO", "CILIUM_OVERLAY", "CILIUM_NATIVE_ROUTING"), "release-channel": cli.FlagValues("RAPID", "STABLE"), "vpc-id": cli.ResourceCompletion("vserver:network"), diff --git a/go/cmd/vks/create_cluster.go b/go/cmd/vks/create_cluster.go index 5bc8081..993023f 100644 --- a/go/cmd/vks/create_cluster.go +++ b/go/cmd/vks/create_cluster.go @@ -26,11 +26,11 @@ func init() { // Node group settings (required) f.String("node-group-name", "", "Default node group name (required)") f.String("flavor-id", "", "Flavor ID for node group (required)") - f.String("image-id", "", "Image ID for node group (required)") + f.String("os", "ubuntu", "Node group OS image (ubuntu, linux)") f.String("disk-type", "", "Disk type ID (required)") f.String("ssh-key-id", "", "SSH key ID for node group (required)") - for _, name := range []string{"name", "k8s-version", "network-type", "vpc-id", "subnet-id", "node-group-name", "flavor-id", "image-id", "disk-type", "ssh-key-id"} { + for _, name := range []string{"name", "k8s-version", "network-type", "vpc-id", "subnet-id", "node-group-name", "flavor-id", "disk-type", "ssh-key-id"} { createClusterCmd.MarkFlagRequired(name) } @@ -67,7 +67,7 @@ func runCreateCluster(cmd *cobra.Command, args []string) error { ngName, _ := cmd.Flags().GetString("node-group-name") flavorID, _ := cmd.Flags().GetString("flavor-id") - imageID, _ := cmd.Flags().GetString("image-id") + osImage, _ := cmd.Flags().GetString("os") diskType, _ := cmd.Flags().GetString("disk-type") sshKeyID, _ := cmd.Flags().GetString("ssh-key-id") diskSize, _ := cmd.Flags().GetInt("disk-size") @@ -82,7 +82,7 @@ func runCreateCluster(cmd *cobra.Command, args []string) error { nodeGroup := map[string]interface{}{ "name": ngName, "flavorId": flavorID, - "imageId": imageID, + "os": osImage, "diskSize": diskSize, "diskType": diskType, "numNodes": numNodes, diff --git a/go/cmd/vks/create_nodegroup.go b/go/cmd/vks/create_nodegroup.go index c65f7b2..5267c82 100644 --- a/go/cmd/vks/create_nodegroup.go +++ b/go/cmd/vks/create_nodegroup.go @@ -19,7 +19,7 @@ func init() { f := createNodegroupCmd.Flags() f.String("cluster-id", "", "Cluster ID (required)") f.String("name", "", "Node group name (required)") - f.String("image-id", "", "Image ID (required)") + f.String("os", "ubuntu", "Node group OS image (ubuntu, linux)") f.String("flavor-id", "", "Flavor ID (required)") f.String("disk-type", "", "Disk type ID (required)") f.String("ssh-key-id", "", "SSH key ID (required)") @@ -33,7 +33,7 @@ func init() { f.Bool("enable-encryption-volume", false, "Enable volume encryption") f.Bool("dry-run", false, "Validate parameters without creating") - for _, name := range []string{"cluster-id", "name", "image-id", "flavor-id", "disk-type", "ssh-key-id"} { + for _, name := range []string{"cluster-id", "name", "flavor-id", "disk-type", "ssh-key-id"} { createNodegroupCmd.MarkFlagRequired(name) } } @@ -41,7 +41,7 @@ func init() { func runCreateNodegroup(cmd *cobra.Command, args []string) error { clusterID, _ := cmd.Flags().GetString("cluster-id") name, _ := cmd.Flags().GetString("name") - imageID, _ := cmd.Flags().GetString("image-id") + osImage, _ := cmd.Flags().GetString("os") flavorID, _ := cmd.Flags().GetString("flavor-id") diskType, _ := cmd.Flags().GetString("disk-type") sshKeyID, _ := cmd.Flags().GetString("ssh-key-id") @@ -62,7 +62,7 @@ func runCreateNodegroup(cmd *cobra.Command, args []string) error { body := map[string]interface{}{ "name": name, "numNodes": numNodes, - "imageId": imageID, + "os": osImage, "flavorId": flavorID, "diskSize": diskSize, "diskType": diskType, diff --git a/go/cmd/vks/update_nodegroup.go b/go/cmd/vks/update_nodegroup.go index 0010f95..427d947 100644 --- a/go/cmd/vks/update_nodegroup.go +++ b/go/cmd/vks/update_nodegroup.go @@ -18,7 +18,6 @@ func init() { f := updateNodegroupCmd.Flags() f.String("cluster-id", "", "Cluster ID (required)") f.String("nodegroup-id", "", "Node group ID (required)") - f.String("image-id", "", "Image ID (required)") f.String("num-nodes", "", "New number of nodes") f.String("security-groups", "", "Security group IDs (comma-separated)") f.String("labels", "", "Node labels as key=value pairs (comma-separated)") @@ -32,13 +31,11 @@ func init() { updateNodegroupCmd.MarkFlagRequired("cluster-id") updateNodegroupCmd.MarkFlagRequired("nodegroup-id") - updateNodegroupCmd.MarkFlagRequired("image-id") } func runUpdateNodegroup(cmd *cobra.Command, args []string) error { clusterID, _ := cmd.Flags().GetString("cluster-id") nodegroupID, _ := cmd.Flags().GetString("nodegroup-id") - imageID, _ := cmd.Flags().GetString("image-id") numNodes, _ := cmd.Flags().GetString("num-nodes") securityGroups, _ := cmd.Flags().GetString("security-groups") labelsStr, _ := cmd.Flags().GetString("labels") @@ -57,9 +54,7 @@ func runUpdateNodegroup(cmd *cobra.Command, args []string) error { return err } - body := map[string]interface{}{ - "imageId": imageID, - } + body := map[string]interface{}{} if numNodes != "" { body["numNodes"] = toInt(numNodes) @@ -99,6 +94,10 @@ func runUpdateNodegroup(cmd *cobra.Command, args []string) error { body["upgradeConfig"] = upgradeConfig } + if len(body) == 0 { + return fmt.Errorf("nothing to update: provide at least one of --num-nodes, --security-groups, --labels, --taints, --auto-scale-min/max, or --upgrade-strategy/max-surge/max-unavailable") + } + if dryRun { fmt.Println("=== DRY RUN: Update node group ===") fmt.Println()