Skip to content

Commit f30f3f1

Browse files
Feat/stackittpr 567 opensearch sdk migration (#1349)
* fix(opensearch) make datasource schema match resource schema Acceptance tests failed because of tls_protocols being a list. * feat(opensearch) use versioned sdk * fix(opensearch) generate docs * fix(lint) disable rangeValCopy gocritic rule We have a short running process, memory pressure can be ignored. * fix(opensearch) fix tests * fix(conversion) return nil instead of &nil from StringListToPointer * fix(opensearch) also migrate test code to new sdk
1 parent db44fe3 commit f30f3f1

File tree

14 files changed

+270
-219
lines changed

14 files changed

+270
-219
lines changed

docs/data-sources/opensearch_instance.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,4 @@ Read-Only:
5959
- `sgw_acl` (String) Comma separated list of IP networks in CIDR notation which are allowed to access this instance.
6060
- `syslog` (List of String) List of syslog servers to send logs to.
6161
- `tls_ciphers` (List of String) List of TLS ciphers to use.
62-
- `tls_protocols` (String) The TLS protocol to use.
62+
- `tls_protocols` (List of String) List of TLS protocols to use.

golang-ci.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ linters:
4040
- typeDefFirst
4141
- ifElseChain
4242
- dupImport # https://github.com/go-critic/go-critic/issues/845
43+
- rangeValCopy
4344
enabled-tags:
4445
- performance
4546
- style

stackit/internal/conversion/conversion.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,11 +131,21 @@ func BoolValueToPointer(s basetypes.BoolValue) *bool {
131131
// StringListToPointer converts basetypes.ListValue to a pointer to a list of strings.
132132
// It returns nil if the value is null or unknown.
133133
func StringListToPointer(list basetypes.ListValue) (*[]string, error) {
134+
result, err := StringListToSlice(list)
135+
if result == nil {
136+
return nil, err
137+
}
138+
return &result, err
139+
}
140+
141+
// StringListToSlice converts basetypes.ListValue to a list of strings.
142+
// It returns nil if the value is null or unknown.
143+
func StringListToSlice(list basetypes.ListValue) ([]string, error) {
134144
if list.IsNull() || list.IsUnknown() {
135145
return nil, nil
136146
}
137147

138-
listStr := []string{}
148+
var listStr []string
139149
for i, el := range list.Elements() {
140150
elStr, ok := el.(types.String)
141151
if !ok {
@@ -144,7 +154,7 @@ func StringListToPointer(list basetypes.ListValue) (*[]string, error) {
144154
listStr = append(listStr, elStr.ValueString())
145155
}
146156

147-
return &listStr, nil
157+
return listStr, nil
148158
}
149159

150160
// StringSetToPointer converts basetypes.SetValue to a pointer to a list of strings.

stackit/internal/conversion/conversion_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,3 +449,59 @@ func TestStringSetToSlice(t *testing.T) {
449449
})
450450
}
451451
}
452+
453+
func TestStringListToSlice(t *testing.T) {
454+
t.Parallel()
455+
tests := []struct {
456+
name string
457+
in basetypes.ListValue
458+
want []string
459+
wantErr bool
460+
}{
461+
{
462+
name: "unknown",
463+
in: basetypes.NewListUnknown(types.StringType),
464+
want: nil,
465+
},
466+
{
467+
name: "null",
468+
in: basetypes.NewListNull(types.StringType),
469+
want: nil,
470+
},
471+
{
472+
name: "invalid type",
473+
in: basetypes.NewListValueMust(types.Int64Type, []attr.Value{types.Int64Value(123)}),
474+
wantErr: true,
475+
},
476+
{
477+
name: "some values",
478+
in: basetypes.NewListValueMust(
479+
types.StringType,
480+
[]attr.Value{
481+
types.StringValue("abc"),
482+
types.StringValue("xyz"),
483+
},
484+
),
485+
want: []string{
486+
"abc",
487+
"xyz",
488+
},
489+
},
490+
}
491+
492+
for _, tt := range tests {
493+
t.Run(tt.name, func(t *testing.T) {
494+
t.Parallel()
495+
got, err := StringListToSlice(tt.in)
496+
if tt.wantErr && err == nil {
497+
t.Fatal("expected error")
498+
}
499+
if !tt.wantErr && err != nil {
500+
t.Fatalf("expected no error, got: %v", err)
501+
}
502+
if d := cmp.Diff(got, tt.want); d != "" {
503+
t.Fatalf("no match, diff: %s", d)
504+
}
505+
})
506+
}
507+
}

stackit/internal/services/opensearch/credential/datasource.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import (
1717

1818
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
1919
"github.com/hashicorp/terraform-plugin-framework/types"
20-
"github.com/stackitcloud/stackit-sdk-go/services/opensearch"
20+
opensearch "github.com/stackitcloud/stackit-sdk-go/services/opensearch/v1api"
2121
)
2222

2323
// Ensure the implementation satisfies the expected interfaces.
@@ -107,7 +107,7 @@ func (r *credentialDataSource) Schema(_ context.Context, _ datasource.SchemaRequ
107107
Computed: true,
108108
Sensitive: true,
109109
},
110-
"port": schema.Int64Attribute{
110+
"port": schema.Int32Attribute{
111111
Computed: true,
112112
},
113113
"scheme": schema.StringAttribute{
@@ -142,7 +142,7 @@ func (r *credentialDataSource) Read(ctx context.Context, req datasource.ReadRequ
142142
ctx = tflog.SetField(ctx, "instance_id", instanceId)
143143
ctx = tflog.SetField(ctx, "credential_id", credentialId)
144144

145-
recordSetResp, err := r.client.GetCredentials(ctx, projectId, instanceId, credentialId).Execute()
145+
recordSetResp, err := r.client.DefaultAPI.GetCredentials(ctx, projectId, instanceId, credentialId).Execute()
146146
if err != nil {
147147
utils.LogError(
148148
ctx,

stackit/internal/services/opensearch/credential/resource.go

Lines changed: 25 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ import (
2121
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
2222
"github.com/hashicorp/terraform-plugin-framework/types"
2323
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
24-
"github.com/stackitcloud/stackit-sdk-go/services/opensearch"
25-
"github.com/stackitcloud/stackit-sdk-go/services/opensearch/wait"
24+
opensearch "github.com/stackitcloud/stackit-sdk-go/services/opensearch/v1api"
25+
"github.com/stackitcloud/stackit-sdk-go/services/opensearch/v1api/wait"
2626
)
2727

2828
// Ensure the implementation satisfies the expected interfaces.
@@ -40,7 +40,7 @@ type Model struct {
4040
Host types.String `tfsdk:"host"`
4141
Hosts types.List `tfsdk:"hosts"`
4242
Password types.String `tfsdk:"password"`
43-
Port types.Int64 `tfsdk:"port"`
43+
Port types.Int32 `tfsdk:"port"`
4444
Scheme types.String `tfsdk:"scheme"`
4545
Uri types.String `tfsdk:"uri"`
4646
Username types.String `tfsdk:"username"`
@@ -142,7 +142,7 @@ func (r *credentialResource) Schema(_ context.Context, _ resource.SchemaRequest,
142142
Computed: true,
143143
Sensitive: true,
144144
},
145-
"port": schema.Int64Attribute{
145+
"port": schema.Int32Attribute{
146146
Computed: true,
147147
},
148148
"scheme": schema.StringAttribute{
@@ -176,26 +176,22 @@ func (r *credentialResource) Create(ctx context.Context, req resource.CreateRequ
176176
ctx = tflog.SetField(ctx, "instance_id", instanceId)
177177

178178
// Create new recordset
179-
credentialsResp, err := r.client.CreateCredentials(ctx, projectId, instanceId).Execute()
179+
credentialsResp, err := r.client.DefaultAPI.CreateCredentials(ctx, projectId, instanceId).Execute()
180180
if err != nil {
181181
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating credential", fmt.Sprintf("Calling API: %v", err))
182182
return
183183
}
184184

185185
ctx = core.LogResponse(ctx)
186186

187-
if credentialsResp.Id == nil {
188-
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating credential", "Got empty credential id")
189-
return
190-
}
191-
credentialId := *credentialsResp.Id
187+
credentialId := credentialsResp.Id
192188
ctx = utils.SetAndLogStateFields(ctx, &resp.Diagnostics, &resp.State, map[string]any{
193189
"project_id": projectId,
194190
"instance_id": instanceId,
195191
"credential_id": credentialId,
196192
})
197193

198-
waitResp, err := wait.CreateCredentialsWaitHandler(ctx, r.client, projectId, instanceId, credentialId).WaitWithContext(ctx)
194+
waitResp, err := wait.CreateCredentialsWaitHandler(ctx, r.client.DefaultAPI, projectId, instanceId, credentialId).WaitWithContext(ctx)
199195
if err != nil {
200196
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating credential", fmt.Sprintf("Instance creation waiting: %v", err))
201197
return
@@ -233,7 +229,7 @@ func (r *credentialResource) Read(ctx context.Context, req resource.ReadRequest,
233229
ctx = tflog.SetField(ctx, "instance_id", instanceId)
234230
ctx = tflog.SetField(ctx, "credential_id", credentialId)
235231

236-
recordSetResp, err := r.client.GetCredentials(ctx, projectId, instanceId, credentialId).Execute()
232+
recordSetResp, err := r.client.DefaultAPI.GetCredentials(ctx, projectId, instanceId, credentialId).Execute()
237233
if err != nil {
238234
oapiErr, ok := err.(*oapierror.GenericOpenAPIError) //nolint:errorlint //complaining that error.As should be used to catch wrapped errors, but this error should not be wrapped
239235
if ok && oapiErr.StatusCode == http.StatusNotFound {
@@ -287,14 +283,14 @@ func (r *credentialResource) Delete(ctx context.Context, req resource.DeleteRequ
287283
ctx = tflog.SetField(ctx, "credential_id", credentialId)
288284

289285
// Delete existing record set
290-
err := r.client.DeleteCredentials(ctx, projectId, instanceId, credentialId).Execute()
286+
err := r.client.DefaultAPI.DeleteCredentials(ctx, projectId, instanceId, credentialId).Execute()
291287
if err != nil {
292288
core.LogAndAddError(ctx, &resp.Diagnostics, "Error deleting credential", fmt.Sprintf("Calling API: %v", err))
293289
}
294290

295291
ctx = core.LogResponse(ctx)
296292

297-
_, err = wait.DeleteCredentialsWaitHandler(ctx, r.client, projectId, instanceId, credentialId).WaitWithContext(ctx)
293+
_, err = wait.DeleteCredentialsWaitHandler(ctx, r.client.DefaultAPI, projectId, instanceId, credentialId).WaitWithContext(ctx)
298294
if err != nil {
299295
core.LogAndAddError(ctx, &resp.Diagnostics, "Error deleting credential", fmt.Sprintf("Instance deletion waiting: %v", err))
300296
return
@@ -337,10 +333,8 @@ func mapFields(ctx context.Context, credentialsResp *opensearch.CredentialsRespo
337333
var credentialId string
338334
if model.CredentialId.ValueString() != "" {
339335
credentialId = model.CredentialId.ValueString()
340-
} else if credentialsResp.Id != nil {
341-
credentialId = *credentialsResp.Id
342336
} else {
343-
return fmt.Errorf("credentials id not present")
337+
credentialId = credentialsResp.Id
344338
}
345339

346340
model.Id = utils.BuildInternalTerraformId(
@@ -354,24 +348,22 @@ func mapFields(ctx context.Context, credentialsResp *opensearch.CredentialsRespo
354348

355349
model.CredentialId = types.StringValue(credentialId)
356350
model.Hosts = types.ListNull(types.StringType)
357-
if credentials != nil {
358-
if credentials.Hosts != nil {
359-
respHosts := *credentials.Hosts
360-
reconciledHosts := utils.ReconcileStringSlices(modelHosts, respHosts)
351+
if credentials.Hosts != nil {
352+
respHosts := credentials.Hosts
353+
reconciledHosts := utils.ReconcileStringSlices(modelHosts, respHosts)
361354

362-
hostsTF, diags := types.ListValueFrom(ctx, types.StringType, reconciledHosts)
363-
if diags.HasError() {
364-
return fmt.Errorf("failed to map hosts: %w", core.DiagsToError(diags))
365-
}
366-
367-
model.Hosts = hostsTF
355+
hostsTF, diags := types.ListValueFrom(ctx, types.StringType, reconciledHosts)
356+
if diags.HasError() {
357+
return fmt.Errorf("failed to map hosts: %w", core.DiagsToError(diags))
368358
}
369-
model.Host = types.StringPointerValue(credentials.Host)
370-
model.Password = types.StringPointerValue(credentials.Password)
371-
model.Port = types.Int64PointerValue(credentials.Port)
372-
model.Scheme = types.StringPointerValue(credentials.Scheme)
373-
model.Uri = types.StringPointerValue(credentials.Uri)
374-
model.Username = types.StringPointerValue(credentials.Username)
359+
360+
model.Hosts = hostsTF
375361
}
362+
model.Host = types.StringValue(credentials.Host)
363+
model.Password = types.StringValue(credentials.Password)
364+
model.Port = types.Int32PointerValue(credentials.Port)
365+
model.Scheme = types.StringPointerValue(credentials.Scheme)
366+
model.Uri = types.StringPointerValue(credentials.Uri)
367+
model.Username = types.StringValue(credentials.Username)
376368
return nil
377369
}

0 commit comments

Comments
 (0)