Skip to content
Merged
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ require (
github.com/stackitcloud/stackit-sdk-go/services/dns v0.2.0
github.com/stackitcloud/stackit-sdk-go/services/logme v0.2.0
github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.2.0
github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.3.0
github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.2.0
github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.2.0
github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.1.0
github.com/stackitcloud/stackit-sdk-go/services/postgresql v0.3.0
github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.2.0
Expand Down
6 changes: 4 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,10 @@ github.com/stackitcloud/stackit-sdk-go/services/logme v0.2.0 h1:DzG8h4irPUWUxa+s
github.com/stackitcloud/stackit-sdk-go/services/logme v0.2.0/go.mod h1:KkWI0vWfBHRepIrH0VT2e1xwf1WaaNb/zPfSTRXAXjs=
github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.2.0 h1:lnqYVQ1kjMDJSVvKJjZW8eY1adWXlCiX5jIXyn2lOzg=
github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.2.0/go.mod h1:uTotoums0lfsmlTQVP5bYz4wWmfWlLuFx9i1ZzAyAkA=
github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.3.0 h1:32mjinxJ7xfdlTKShmyvfMU7BXI11DiV+W4SdkRL63o=
github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.3.0/go.mod h1:syCy6+8GsJu9lHyhN0Qeg66AgTv5LjlgtppbOVFIaPc=
github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.2.0 h1:Nf7HFWSTrD/A1ZudSSu8LaaOYN+4607D1qWNRtZuo8Y=
github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.2.0/go.mod h1:H0B0VBzyW90ksuG+Bu9iqOan80paw+J6Ik9AZuiz9M0=
github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.2.0 h1:pONEMH+p9xR1ACDEH6E1Jl5dnU1DixoJGD2iPWQOVuI=
github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.2.0/go.mod h1:pTTPSxx/BpcAm0ttcH+g4AiovC+oT7lXqca2C1XOxzY=
github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.1.0 h1:vm3AgvTA6TaHd0WpmzKT6HY6fSLOJUNPslqeLByO5P4=
github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.1.0/go.mod h1:sPEBUNRxaEsyhVOQKZrUdebexVX/z1RbvUFXxXOrICo=
github.com/stackitcloud/stackit-sdk-go/services/postgresql v0.3.0 h1:svBOTZ4yOG3LFqBQbUoSkY1v4GWH9fG3VqyO5hQqGVQ=
Expand Down
1 change: 1 addition & 0 deletions stackit/internal/core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type ProviderData struct {
LogMeCustomEndpoint string
RabbitMQCustomEndpoint string
MariaDBCustomEndpoint string
ObjectStorageCustomEndpoint string
OpenSearchCustomEndpoint string
RedisCustomEndpoint string
ArgusCustomEndpoint string
Expand Down
150 changes: 150 additions & 0 deletions stackit/internal/services/objectstorage/bucket/datasource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
package objectstorage

import (
"context"
"fmt"

"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core"
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/validate"

"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/stackitcloud/stackit-sdk-go/core/config"
"github.com/stackitcloud/stackit-sdk-go/services/objectstorage"
)

// Ensure the implementation satisfies the expected interfaces.
var (
_ datasource.DataSource = &bucketDataSource{}
)

// NewBucketDataSource is a helper function to simplify the provider implementation.
func NewBucketDataSource() datasource.DataSource {
return &bucketDataSource{}
}

// bucketDataSource is the data source implementation.
type bucketDataSource struct {
client *objectstorage.APIClient
}

// Metadata returns the data source type name.
func (r *bucketDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_objectstorage_bucket"
}

// Configure adds the provider configured client to the data source.
func (r *bucketDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
// Prevent panic if the provider has not been configured.
if req.ProviderData == nil {
return
}

providerData, ok := req.ProviderData.(core.ProviderData)
if !ok {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error configuring API client", fmt.Sprintf("Expected configure type stackit.ProviderData, got %T", req.ProviderData))
return
}

var apiClient *objectstorage.APIClient
var err error
if providerData.ObjectStorageCustomEndpoint != "" {
apiClient, err = objectstorage.NewAPIClient(
config.WithCustomAuth(providerData.RoundTripper),
config.WithEndpoint(providerData.ObjectStorageCustomEndpoint),
)
} else {
apiClient, err = objectstorage.NewAPIClient(
config.WithCustomAuth(providerData.RoundTripper),
config.WithRegion(providerData.Region),
)
}

if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error configuring API client", fmt.Sprintf("Configuring client: %v", err))
return
}

r.client = apiClient
tflog.Info(ctx, "ObjectStorage bucket client configured")
}

// Schema defines the schema for the data source.
func (r *bucketDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
descriptions := map[string]string{
"main": "ObjectStorage credentials data source schema.",
"id": "Terraform's internal data source identifier. It is structured as \"`project_id`,`bucket_name`\".",
"bucket_name": "The bucket name. It must be DNS conform.",
"project_id": "STACKIT Project ID to which the bucket is associated.",
"url_path_style": "URL in path style.",
"url_virtual_hosted_style": "URL in virtual hosted style.",
}

resp.Schema = schema.Schema{
Description: descriptions["main"],
Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{
Description: descriptions["id"],
Computed: true,
},
"bucket_name": schema.StringAttribute{
Description: descriptions["bucket_name"],
Required: true,
Validators: []validator.String{
validate.NoSeparator(),
},
},
"project_id": schema.StringAttribute{
Description: descriptions["project_id"],
Required: true,
Validators: []validator.String{
validate.UUID(),
validate.NoSeparator(),
},
},
"url_path_style": schema.StringAttribute{
Computed: true,
},
"url_virtual_hosted_style": schema.StringAttribute{
Computed: true,
},
},
}
}

// Read refreshes the Terraform state with the latest data.
func (r *bucketDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { // nolint:gocritic // function signature required by Terraform
var model Model
diags := req.Config.Get(ctx, &model)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
projectId := model.ProjectId.ValueString()
bucketName := model.BucketName.ValueString()
ctx = tflog.SetField(ctx, "project_id", projectId)
ctx = tflog.SetField(ctx, "bucket_name", bucketName)

bucketResp, err := r.client.GetBucket(ctx, projectId, bucketName).Execute()
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading bucket", fmt.Sprintf("Calling API: %v", err))
return
}

// Map response body to schema
err = mapFields(bucketResp, &model)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading bucket", fmt.Sprintf("Processing API payload: %v", err))
return
}

// Set refreshed state
diags = resp.State.Set(ctx, model)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
tflog.Info(ctx, "ObjectStorage bucket read")
}
Loading