diff --git a/cmd/node/change_rescue_mode.go b/cmd/node/change_rescue_mode.go index 5edf89d..11c44e5 100644 --- a/cmd/node/change_rescue_mode.go +++ b/cmd/node/change_rescue_mode.go @@ -52,8 +52,8 @@ var changeRescueModeCmd = &cobra.Command{ func init() { changeRescueModeCmd.Flags().StringVar(&changeRescueModeId, "id", "", "Node ID (required)") changeRescueModeCmd.Flags().StringVar(&changeRescueModeProjectId, "project-id", "", "Project ID (required)") - changeRescueModeCmd.Flags().BoolVar(&changeRescueModeEnabled, "enabled", false, "Enable or disable rescue mode (required)") - changeRescueModeCmd.Flags().StringVar(&changeRescueModePassword, "password", "", "Password for rescue mode (required)") + changeRescueModeCmd.Flags().BoolVar(&changeRescueModeEnabled, "enabled", false, "Enable or disable rescue mode") + changeRescueModeCmd.Flags().StringVar(&changeRescueModePassword, "password", "", "Password for rescue mode") changeRescueModeCmd.MarkFlagRequired("id") changeRescueModeCmd.MarkFlagRequired("project-id") diff --git a/cmd/project/_network_create.go b/cmd/project/_network_create.go index 85247e9..61463b0 100644 --- a/cmd/project/_network_create.go +++ b/cmd/project/_network_create.go @@ -1,82 +1,11 @@ package project -import ( - "buf.build/gen/go/gportal/gpcore/grpc/go/gpcore/api/admin/v1/adminv1grpc" - adminv1 "buf.build/gen/go/gportal/gpcore/protocolbuffers/go/gpcore/api/admin/v1" - cloudv1 "buf.build/gen/go/gportal/gpcore/protocolbuffers/go/gpcore/api/cloud/v1" - "encoding/json" - "github.com/G-PORTAL/gpcore-cli/pkg/client" - "github.com/G-PORTAL/gpcore-cli/pkg/config" - "github.com/G-PORTAL/gpcore-cli/pkg/protobuf" - "github.com/spf13/cobra" - "google.golang.org/grpc" -) - -// This command is disabled at the moment because the ListSubnets endpoint is -// missing on gRPC (which is needed to get the subnets from the IDs). - -var networkCreateProjectId string -var networkCreateName string -var networkCreateType string -var networkCreateSubnets []string -var networkCreateVlanId int32 -var networkCreateDatacenter string - -var networkCreateCmd = &cobra.Command{ - Args: cobra.OnlyValidArgs, - DisableFlagsInUseLine: true, - Long: "", - RunE: func(cobraCmd *cobra.Command, args []string) error { - ctx := client.ExtractContext(cobraCmd) - grpcConn := ctx.Value("conn").(*grpc.ClientConn) - client := adminv1grpc.NewAdminServiceClient(grpcConn) - - networkCreateSubnetStructs := make([]*cloudv1.Subnet, 0) - // TODO: Get subnets from networkCreateSubnetUUIDList IDs - // TODO: ListSubnets endpoint missing on gRPC - - networkCreateDatacenterStruct := &cloudv1.Datacenter{ - Id: networkCreateDatacenter, - } - - resp, err := client.CreateProjectNetwork(cobraCmd.Context(), &adminv1.CreateProjectNetworkRequest{ - Name: networkCreateName, - ProjectId: networkCreateProjectId, - Subnets: networkCreateSubnetStructs, - Datacenter: networkCreateDatacenterStruct, - Type: protobuf.NetworkTypeToProto(networkCreateType), - VlanId: &networkCreateVlanId, - }) - if err != nil { - return err - } - respData := resp - if config.JSONOutput { - jsonData, err := protobuf.MarshalIndent(respData) - if err != nil { - return err - } - cobraCmd.Println(string(jsonData)) - } - return nil - }, - Short: "", - Use: "network-create", - ValidArgs: []string{"project-id", "name", "type", "subnet-ids", "datacenter-id", "vlan-id"}, -} - -func init() { - networkCreateCmd.Flags().StringVar(&networkCreateProjectId, "project-id", "", "Project ID (required)") - networkCreateCmd.Flags().StringVar(&networkCreateName, "name", "", "Network name (required)") - networkCreateCmd.Flags().StringVar(&networkCreateType, "type", "PRIVATE", "Network type (default:\"cloudv1.NETWORK_TYPE_PRIVATE\")") - networkCreateCmd.Flags().StringSliceVar(&networkCreateSubnets, "subnet-ids", []string{}, "Subnets (required)") - networkCreateCmd.Flags().StringVar(&networkCreateDatacenter, "datacenter-id", "", "Datacenter ID (required)") - networkCreateCmd.Flags().Int32Var(&networkCreateVlanId, "vlan-id", int32(0), "VLAN ID") - - networkCreateCmd.MarkFlagRequired("project-id") - networkCreateCmd.MarkFlagRequired("name") - networkCreateCmd.MarkFlagRequired("type") - networkCreateCmd.MarkFlagRequired("subnets") - - RootProjectCommand.AddCommand(networkCreateCmd) -} +// This command is disabled because the ListSubnets endpoint is missing on +// gRPC (which is needed to resolve subnet IDs). It will be re-enabled once +// the endpoint is available. +// +// TODO: Re-enable once admin.ListSubnets is available in the gRPC API. +// The command should: +// - Accept --subnet-ids and resolve them via ListSubnets +// - Register itself with RootProjectCommand.AddCommand(networkCreateCmd) +// - Fix MarkFlagRequired to use "subnet-ids" (not "subnets") diff --git a/pkg/generator/definition.go b/pkg/generator/definition.go index 2868d6f..f58d3b4 100644 --- a/pkg/generator/definition.go +++ b/pkg/generator/definition.go @@ -32,6 +32,7 @@ type Param struct { Description string `yaml:"description"` Required bool `yaml:"required"` Default interface{} `yaml:"default"` + Optional bool `yaml:"optional"` // Proto field is a pointer type (oneof/optional) } type APICall struct { diff --git a/pkg/generator/definition/image.yaml b/pkg/generator/definition/image.yaml index a567944..1fa8ad3 100644 --- a/pkg/generator/definition/image.yaml +++ b/pkg/generator/definition/image.yaml @@ -25,6 +25,7 @@ actions: default: typev1.CLOUD_PROVIDER_TYPE_AWS description: Filter by cloud provider type required: false + optional: true fields: - Id - Name diff --git a/pkg/generator/definition/network-arp.yaml b/pkg/generator/definition/network-arp.yaml index 7403624..78e84be 100644 --- a/pkg/generator/definition/network-arp.yaml +++ b/pkg/generator/definition/network-arp.yaml @@ -8,7 +8,7 @@ actions: params: - name: mac_address type: string - description: IP address + description: MAC address required: true list: diff --git a/pkg/generator/definition/node.yaml b/pkg/generator/definition/node.yaml index e4390b4..16c8420 100644 --- a/pkg/generator/definition/node.yaml +++ b/pkg/generator/definition/node.yaml @@ -38,7 +38,12 @@ actions: update: api-call: admin.UpdateNode description: Update node details + identifier: nil params: + - name: id + type: string + description: Node UUID + required: true - name: managed type: bool required: true @@ -141,7 +146,7 @@ actions: - name: user_data type: string description: User data - required: true + default: "" power-action: api-call: cloud.PowerActionNode diff --git a/pkg/generator/definition/project.yaml b/pkg/generator/definition/project.yaml index 0ed9f5e..09c7db2 100644 --- a/pkg/generator/definition/project.yaml +++ b/pkg/generator/definition/project.yaml @@ -23,7 +23,6 @@ actions: description: Project ID required: true - # TODO: Fix after dependency upgrade update: api-call: cloud.UpdateProject description: Update project details @@ -32,23 +31,22 @@ actions: type: string description: Project name required: true - - name: description - type: string - description: Project description - required: true - - name: environment - type: cloudv1.ProjectEnvironment - description: Project environment - default: cloudv1.PROJECT_ENVIRONMENT_DEVELOPMENT - required: true - name: credit_card_id type: string description: Credit card ID required: true - name: billing_address_id type: string - description: Billing address ID + description: Billing profile ID required: true + - name: description + type: string + description: Project description (deprecated) + default: "" + - name: environment + type: cloudv1.ProjectEnvironment + description: Project environment (deprecated) + default: cloudv1.PROJECT_ENVIRONMENT_DEVELOPMENT create: api-call: cloud.CreateProject @@ -59,16 +57,18 @@ actions: type: string description: Project name required: true + - name: billing_address_id + type: string + description: Billing profile ID + required: true - name: description type: string + description: Project description (deprecated) default: "" - name: environment type: cloudv1.ProjectEnvironment + description: Project environment (deprecated) default: cloudv1.PROJECT_ENVIRONMENT_DEVELOPMENT - required: true - - name: billing_address_id - type: string - required: true delete: api-call: cloud.DeleteProject diff --git a/pkg/generator/sub_command.go b/pkg/generator/sub_command.go index 063185b..ac0c167 100644 --- a/pkg/generator/sub_command.go +++ b/pkg/generator/sub_command.go @@ -185,8 +185,11 @@ func runCommand(name string, metadata SubcommandMetadata) []Code { variable := strcase.LowerCamelCase(name) + title(strcase.LowerCamelCase(param.Name)) var val *Statement if isEnumType(param.Type) && !isArrayType(param.Type) { - // Enum helper function call - if !param.Required { + // Enum helper function call. Use a pointer when the proto field + // is explicitly marked as optional (oneof/optional pointer type). + if param.Optional { + // Variable is shadowed and converted before the API call, + // take its address for the pointer proto field. val = Op("&").Id(variable) } else { val = Qual("github.com/G-PORTAL/gpcore-cli/pkg/protobuf", stripPackage(param.Type)+"ToProto").Call(Id(variable)) @@ -213,9 +216,11 @@ func runCommand(name string, metadata SubcommandMetadata) []Code { respC := make([]Code, 0) - // Special variables for pointer usage + // For enum params marked as optional, the proto field is a pointer type + // (oneof/optional). We need to convert the string to the enum value and + // take its address. for _, param := range metadata.Action.Params { - if isEnumType(param.Type) && !param.Required { + if isEnumType(param.Type) && param.Optional { variable := strcase.LowerCamelCase(name) + title(strcase.LowerCamelCase(param.Name)) respC = append(respC, Id(variable). Op(":=").