Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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