chore(edge): refactoring and migration to new SDK structure - #1503
chore(edge): refactoring and migration to new SDK structure#1503GokceGK wants to merge 3 commits into
Conversation
relates to STACKITCLI-357
relates to STACKITCLI-357
Merging this branch changes the coverage (11 decrease, 1 increase)
Coverage by fileChanged files (no unit tests)
Please note that the "Total", "Covered", and "Missed" counts above refer to code statements instead of lines of code. The value in brackets refers to the test coverage of that file in the old version of the code. Changed unit test files
|
rubenhoenle
left a comment
There was a problem hiding this comment.
Just a first glance, this thing is big. Will have to take a second look but I have to quit work for today.
| // Build request payload | ||
| payload := edge.CreateInstancePayload{ | ||
| DisplayName: &model.DisplayName, | ||
| DisplayName: *model.DisplayName, |
There was a problem hiding this comment.
Both the display name as the plan id are required flags. Why are they pointers in your inputModel struct then? I see only a risk for nil pointers here without any benefit 😅
| // Output result based on the configured output format | ||
| func outputResult(p *print.Printer, outputFormat string, async bool, projectLabel string, instance *edge.Instance) error { | ||
| func outputResult(p *print.Printer, model *inputModel, projectLabel string, instance *edge.Instance) error { | ||
| if instance == nil { |
There was a problem hiding this comment.
Move this nil check into the callback of p.OutputResult. The JSON/YAML output can handle nil values just fine.
| @@ -34,86 +27,17 @@ var ( | |||
| testPlanId = uuid.NewString() | |||
| testDescription = "Initial instance description" | |||
| if model.Async { | ||
| operationState = "Triggered deletion of" | ||
| } | ||
| params.Printer.Info("%s instance %q of project %q.\n", operationState, instanceLabel, projectLabel) |
There was a problem hiding this comment.
| params.Printer.Info("%s instance %q of project %q.\n", operationState, instanceLabel, projectLabel) | |
| params.Printer.Outputf("%s instance %q of project %q.\n", operationState, instanceLabel, projectLabel) |
I hope this is the last time I will have to comment this. Stderr vs. stdout. 😉
| // This is only to prevent nil pointer deref. | ||
| // As long as the API behaves as defined by it's spec, instance can not be empty (HTTP 200 with an empty body) | ||
| return commonErr.NewNoInstanceError("") | ||
| return fmt.Errorf("instance response is empty") |
There was a problem hiding this comment.
same here, move this nil check into the callback func please
| return string(kubeconfigYAML), nil | ||
| default: | ||
| return "", fmt.Errorf("%w: %s", commonErr.NewNoIdentifierError(""), format) | ||
| return "", fmt.Errorf("format is not JSON or YAML: %s", format) |
There was a problem hiding this comment.
can't we use p.OutputResult here?
| cmd := &cobra.Command{ | ||
| Use: "create", | ||
| Short: "Creates a token for an edge instance", | ||
| Use: fmt.Sprintf("create token for %s", instanceIdArg), |
There was a problem hiding this comment.
| Use: fmt.Sprintf("create token for %s", instanceIdArg), | |
| Use: fmt.Sprintf("create"), |
Same here. Furthermore we don't use arguments on create commands. The instance id would be a flag.
| "An expiration time can be set for the token. The expiration time is set in seconds(s), minutes(m), hours(h), days(d) or months(M). Default is 3600(1h) seconds.", | ||
| "Note: the format for the duration is <value><unit>, e.g. 30d for 30 days. You may not combine units."), | ||
| Args: args.NoArgs, | ||
| Args: args.SingleArg(instanceIdArg, nil), |
There was a problem hiding this comment.
- We don't do that by convention. Instance ID would have to be a flag.
- This is a breaking change.
| // Output result based on the configured output format | ||
| func outputResult(p *print.Printer, outputFormat string, token *edge.Token) error { | ||
| if token == nil || token.Token == nil { | ||
| if token == nil { |
There was a problem hiding this comment.
same as above, move this nil check into the callback for the pretty output
| tokenString := token.Token | ||
|
|
||
| return p.OutputResult(outputFormat, token, func() error { | ||
| p.Outputln(tokenString) |
There was a problem hiding this comment.
| p.Outputln(tokenString) | |
| p.Outputln(token.Token) |
Why a variable for everything?
| type inputModel struct { | ||
| *globalflags.GlobalFlagModel | ||
| DisplayName *string | ||
| Description string | ||
| PlanId *string | ||
| } |
There was a problem hiding this comment.
description is the only optional field in the API, so i think we should flip the pointers:
| type inputModel struct { | |
| *globalflags.GlobalFlagModel | |
| DisplayName *string | |
| Description string | |
| PlanId *string | |
| } | |
| type inputModel struct { | |
| *globalflags.GlobalFlagModel | |
| DisplayName string | |
| Description *string | |
| PlanId string | |
| } |
| descriptionValue := flags.FlagWithDefaultToStringValue(p, cmd, commonInstance.DescriptionFlag) | ||
| if err := commonInstance.ValidateDescription(descriptionValue); err != nil { | ||
| displayNameValue := flags.FlagToStringPointer(p, cmd, displayNameFlag) | ||
| planIdValue := flags.FlagToStringValue(p, cmd, planIdFlag) |
There was a problem hiding this comment.
Not sure if this is beyond the scope of this PR/ticket, but we could add validation of planId here, similar to what we have with flavorId for postgres for example
| if instance == nil { | ||
| // This is only to prevent nil pointer deref. | ||
| // As long as the API behaves as defined by it's spec, instance can not be empty (HTTP 200 with an empty body) | ||
| return commonErr.NewNoInstanceError("") | ||
| return fmt.Errorf("instance response is empty") | ||
| } |
There was a problem hiding this comment.
Let's move this into the OutputResult lambda function below to fix this output for JSON/YAML
| if instance == nil { | ||
| // This is only to prevent nil pointer deref. | ||
| // As long as the API behaves as defined by it's spec, instance can not be empty (HTTP 200 with an empty body) | ||
| return commonErr.NewNoInstanceError("") | ||
| return fmt.Errorf("instance response is empty") | ||
| } |
There was a problem hiding this comment.
same here, move this into the function below
|
|
||
| if err != nil { | ||
| return fmt.Errorf("wait for edge instance update: %w", err) | ||
| return fmt.Errorf("wait for SQLServer Flex instance update: %w", err) |
There was a problem hiding this comment.
| return fmt.Errorf("wait for SQLServer Flex instance update: %w", err) | |
| return fmt.Errorf("wait for edge cloud instance update: %w", err) |
| if respKubeconfig.Kubeconfig == nil { | ||
| return fmt.Errorf("no kubeconfig returned from the API") | ||
| } |
There was a problem hiding this comment.
I would check for the whole reply and not the map here, and let the outputResult function handle the nil map case
| if respKubeconfig.Kubeconfig == nil { | |
| return fmt.Errorf("no kubeconfig returned from the API") | |
| } | |
| if respKubeconfig == nil { | |
| return fmt.Errorf("no kubeconfig returned from the API") | |
| } |
| edge "github.com/stackitcloud/stackit-sdk-go/services/edge/v1beta1api" | ||
| ) | ||
|
|
||
| func GetInstanceName(ctx context.Context, apiClient edge.DefaultAPI, projectId, instanceId, region string) (string, error) { |
There was a problem hiding this comment.
Nitpick: swap region and instanceId argument to be in the same order as the APIs expect:
| func GetInstanceName(ctx context.Context, apiClient edge.DefaultAPI, projectId, instanceId, region string) (string, error) { | |
| func GetInstanceName(ctx context.Context, apiClient edge.DefaultAPI, projectId, region, instanceId string) (string, error) { |
Description
relates to STACKITCLI-357
Checklist
make fmtmake generate-docs(will be checked by CI)make test(will be checked by CI)make lint(will be checked by CI)