Skip to content
2 changes: 1 addition & 1 deletion docs/data-sources/opensearch_instance.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,4 @@ Read-Only:
- `sgw_acl` (String) Comma separated list of IP networks in CIDR notation which are allowed to access this instance.
- `syslog` (List of String) List of syslog servers to send logs to.
- `tls_ciphers` (List of String) List of TLS ciphers to use.
- `tls_protocols` (String) The TLS protocol to use.
- `tls_protocols` (List of String) List of TLS protocols to use.
1 change: 1 addition & 0 deletions golang-ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ linters:
- typeDefFirst
- ifElseChain
- dupImport # https://github.com/go-critic/go-critic/issues/845
- rangeValCopy
enabled-tags:
- performance
- style
Expand Down
14 changes: 12 additions & 2 deletions stackit/internal/conversion/conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,21 @@ func BoolValueToPointer(s basetypes.BoolValue) *bool {
// StringListToPointer converts basetypes.ListValue to a pointer to a list of strings.
// It returns nil if the value is null or unknown.
func StringListToPointer(list basetypes.ListValue) (*[]string, error) {
result, err := StringListToSlice(list)
if result == nil {
return nil, err
}
return &result, err
}

// StringListToSlice converts basetypes.ListValue to a list of strings.
// It returns nil if the value is null or unknown.
func StringListToSlice(list basetypes.ListValue) ([]string, error) {
if list.IsNull() || list.IsUnknown() {
return nil, nil
}

listStr := []string{}
var listStr []string
for i, el := range list.Elements() {
elStr, ok := el.(types.String)
if !ok {
Expand All @@ -144,7 +154,7 @@ func StringListToPointer(list basetypes.ListValue) (*[]string, error) {
listStr = append(listStr, elStr.ValueString())
}

return &listStr, nil
return listStr, nil
}

// StringSetToPointer converts basetypes.SetValue to a pointer to a list of strings.
Expand Down
56 changes: 56 additions & 0 deletions stackit/internal/conversion/conversion_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -449,3 +449,59 @@ func TestStringSetToSlice(t *testing.T) {
})
}
}

func TestStringListToSlice(t *testing.T) {
t.Parallel()
tests := []struct {
name string
in basetypes.ListValue
want []string
wantErr bool
}{
{
name: "unknown",
in: basetypes.NewListUnknown(types.StringType),
want: nil,
},
{
name: "null",
in: basetypes.NewListNull(types.StringType),
want: nil,
},
{
name: "invalid type",
in: basetypes.NewListValueMust(types.Int64Type, []attr.Value{types.Int64Value(123)}),
wantErr: true,
},
{
name: "some values",
in: basetypes.NewListValueMust(
types.StringType,
[]attr.Value{
types.StringValue("abc"),
types.StringValue("xyz"),
},
),
want: []string{
"abc",
"xyz",
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
got, err := StringListToSlice(tt.in)
if tt.wantErr && err == nil {
t.Fatal("expected error")
}
if !tt.wantErr && err != nil {
t.Fatalf("expected no error, got: %v", err)
}
if d := cmp.Diff(got, tt.want); d != "" {
t.Fatalf("no match, diff: %s", d)
}
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (

"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/stackitcloud/stackit-sdk-go/services/opensearch"
opensearch "github.com/stackitcloud/stackit-sdk-go/services/opensearch/v1api"
)

// Ensure the implementation satisfies the expected interfaces.
Expand Down Expand Up @@ -107,7 +107,7 @@ func (r *credentialDataSource) Schema(_ context.Context, _ datasource.SchemaRequ
Computed: true,
Sensitive: true,
},
"port": schema.Int64Attribute{
"port": schema.Int32Attribute{
Computed: true,
},
"scheme": schema.StringAttribute{
Expand Down Expand Up @@ -142,7 +142,7 @@ func (r *credentialDataSource) Read(ctx context.Context, req datasource.ReadRequ
ctx = tflog.SetField(ctx, "instance_id", instanceId)
ctx = tflog.SetField(ctx, "credential_id", credentialId)

recordSetResp, err := r.client.GetCredentials(ctx, projectId, instanceId, credentialId).Execute()
recordSetResp, err := r.client.DefaultAPI.GetCredentials(ctx, projectId, instanceId, credentialId).Execute()
if err != nil {
utils.LogError(
ctx,
Expand Down
58 changes: 25 additions & 33 deletions stackit/internal/services/opensearch/credential/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ import (
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
"github.com/stackitcloud/stackit-sdk-go/services/opensearch"
"github.com/stackitcloud/stackit-sdk-go/services/opensearch/wait"
opensearch "github.com/stackitcloud/stackit-sdk-go/services/opensearch/v1api"
"github.com/stackitcloud/stackit-sdk-go/services/opensearch/v1api/wait"
)

// Ensure the implementation satisfies the expected interfaces.
Expand All @@ -40,7 +40,7 @@ type Model struct {
Host types.String `tfsdk:"host"`
Hosts types.List `tfsdk:"hosts"`
Password types.String `tfsdk:"password"`
Port types.Int64 `tfsdk:"port"`
Port types.Int32 `tfsdk:"port"`
Scheme types.String `tfsdk:"scheme"`
Uri types.String `tfsdk:"uri"`
Username types.String `tfsdk:"username"`
Expand Down Expand Up @@ -142,7 +142,7 @@ func (r *credentialResource) Schema(_ context.Context, _ resource.SchemaRequest,
Computed: true,
Sensitive: true,
},
"port": schema.Int64Attribute{
"port": schema.Int32Attribute{
Computed: true,
},
"scheme": schema.StringAttribute{
Expand Down Expand Up @@ -176,26 +176,22 @@ func (r *credentialResource) Create(ctx context.Context, req resource.CreateRequ
ctx = tflog.SetField(ctx, "instance_id", instanceId)

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

ctx = core.LogResponse(ctx)

if credentialsResp.Id == nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating credential", "Got empty credential id")
return
}
credentialId := *credentialsResp.Id
credentialId := credentialsResp.Id
ctx = utils.SetAndLogStateFields(ctx, &resp.Diagnostics, &resp.State, map[string]any{
"project_id": projectId,
"instance_id": instanceId,
"credential_id": credentialId,
})

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

recordSetResp, err := r.client.GetCredentials(ctx, projectId, instanceId, credentialId).Execute()
recordSetResp, err := r.client.DefaultAPI.GetCredentials(ctx, projectId, instanceId, credentialId).Execute()
if err != nil {
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
if ok && oapiErr.StatusCode == http.StatusNotFound {
Expand Down Expand Up @@ -287,14 +283,14 @@ func (r *credentialResource) Delete(ctx context.Context, req resource.DeleteRequ
ctx = tflog.SetField(ctx, "credential_id", credentialId)

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

ctx = core.LogResponse(ctx)

_, err = wait.DeleteCredentialsWaitHandler(ctx, r.client, projectId, instanceId, credentialId).WaitWithContext(ctx)
_, err = wait.DeleteCredentialsWaitHandler(ctx, r.client.DefaultAPI, projectId, instanceId, credentialId).WaitWithContext(ctx)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error deleting credential", fmt.Sprintf("Instance deletion waiting: %v", err))
return
Expand Down Expand Up @@ -337,10 +333,8 @@ func mapFields(ctx context.Context, credentialsResp *opensearch.CredentialsRespo
var credentialId string
if model.CredentialId.ValueString() != "" {
credentialId = model.CredentialId.ValueString()
} else if credentialsResp.Id != nil {
credentialId = *credentialsResp.Id
} else {
return fmt.Errorf("credentials id not present")
credentialId = credentialsResp.Id
}

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

model.CredentialId = types.StringValue(credentialId)
model.Hosts = types.ListNull(types.StringType)
if credentials != nil {
if credentials.Hosts != nil {
respHosts := *credentials.Hosts
reconciledHosts := utils.ReconcileStringSlices(modelHosts, respHosts)
if credentials.Hosts != nil {
respHosts := credentials.Hosts
reconciledHosts := utils.ReconcileStringSlices(modelHosts, respHosts)

hostsTF, diags := types.ListValueFrom(ctx, types.StringType, reconciledHosts)
if diags.HasError() {
return fmt.Errorf("failed to map hosts: %w", core.DiagsToError(diags))
}

model.Hosts = hostsTF
hostsTF, diags := types.ListValueFrom(ctx, types.StringType, reconciledHosts)
if diags.HasError() {
return fmt.Errorf("failed to map hosts: %w", core.DiagsToError(diags))
}
model.Host = types.StringPointerValue(credentials.Host)
model.Password = types.StringPointerValue(credentials.Password)
model.Port = types.Int64PointerValue(credentials.Port)
model.Scheme = types.StringPointerValue(credentials.Scheme)
model.Uri = types.StringPointerValue(credentials.Uri)
model.Username = types.StringPointerValue(credentials.Username)

model.Hosts = hostsTF
}
model.Host = types.StringValue(credentials.Host)
model.Password = types.StringValue(credentials.Password)
model.Port = types.Int32PointerValue(credentials.Port)
model.Scheme = types.StringPointerValue(credentials.Scheme)
model.Uri = types.StringPointerValue(credentials.Uri)
model.Username = types.StringValue(credentials.Username)
return nil
}
Loading
Loading