Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions docs/data-sources/objectstorage_bucket.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,6 @@ data "stackit_objectstorage_bucket" "example" {
### Read-Only

- `id` (String) Terraform's internal data source identifier. It is structured as "`project_id`,`region`,`name`".
- `object_lock` (Boolean) Enable S3 Object Lock on this bucket. Can only be set at creation time. Requires an active project-level compliance lock.
- `url_path_style` (String)
- `url_virtual_hosted_style` (String)
14 changes: 14 additions & 0 deletions docs/resources/objectstorage_bucket.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,19 @@ resource "stackit_objectstorage_bucket" "example" {
name = "example-bucket"
}

## With compliance lock
resource "stackit_objectstorage_compliance_lock" "example_with_lock" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}

resource "stackit_objectstorage_bucket" "example_with_lock" {
depends_on = [stackit_objectstorage_compliance_lock.example_with_lock]
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
name = "example-bucket-with-lock"
object_lock = true
}


# Only use the import statement, if you want to import an existing objectstorage bucket
import {
to = stackit_objectstorage_bucket.import-example
Expand All @@ -35,6 +48,7 @@ import {

### Optional

- `object_lock` (Boolean) Enable S3 Object Lock on this bucket. Can only be set at creation time. Requires an active project-level compliance lock.
- `region` (String) The resource region. If not defined, the provider region is used.

### Read-Only
Expand Down
13 changes: 13 additions & 0 deletions examples/resources/stackit_objectstorage_bucket/resource.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,19 @@ resource "stackit_objectstorage_bucket" "example" {
name = "example-bucket"
}

## With compliance lock
resource "stackit_objectstorage_compliance_lock" "example_with_lock" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}

resource "stackit_objectstorage_bucket" "example_with_lock" {
depends_on = [stackit_objectstorage_compliance_lock.example_with_lock]
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
name = "example-bucket-with-lock"
object_lock = true
}


# Only use the import statement, if you want to import an existing objectstorage bucket
import {
to = stackit_objectstorage_bucket.import-example
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ func (r *bucketDataSource) Schema(_ context.Context, _ datasource.SchemaRequest,
"id": "Terraform's internal data source identifier. It is structured as \"`project_id`,`region`,`name`\".",
"name": "The bucket name. It must be DNS conform.",
"project_id": "STACKIT Project ID to which the bucket is associated.",
"object_lock": "Enable S3 Object Lock on this bucket. Can only be set at creation time. Requires an active project-level compliance lock.",
Comment thread
marceljk marked this conversation as resolved.
Outdated
"url_path_style": "URL in path style.",
"url_virtual_hosted_style": "URL in virtual hosted style.",
"region": "The resource region. If not defined, the provider region is used.",
Expand Down Expand Up @@ -90,6 +91,10 @@ func (r *bucketDataSource) Schema(_ context.Context, _ datasource.SchemaRequest,
validate.NoSeparator(),
},
},
"object_lock": schema.BoolAttribute{
Description: descriptions["object_lock"],
Computed: true,
},
"url_path_style": schema.StringAttribute{
Computed: true,
},
Expand Down
16 changes: 15 additions & 1 deletion stackit/internal/services/objectstorage/bucket/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"net/http"
"strings"

"github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier"
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion"
objectstorageUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/objectstorage/utils"

Expand Down Expand Up @@ -41,6 +43,7 @@ type Model struct {
URLPathStyle types.String `tfsdk:"url_path_style"`
URLVirtualHostedStyle types.String `tfsdk:"url_virtual_hosted_style"`
Region types.String `tfsdk:"region"`
ObjectLock types.Bool `tfsdk:"object_lock"`
}

// NewBucketResource is a helper function to simplify the provider implementation.
Expand Down Expand Up @@ -112,6 +115,7 @@ func (r *bucketResource) Schema(_ context.Context, _ resource.SchemaRequest, res
"id": "Terraform's internal resource identifier. It is structured as \"`project_id`,`region`,`name`\".",
"name": "The bucket name. It must be DNS conform.",
"project_id": "STACKIT Project ID to which the bucket is associated.",
"object_lock": "Enable S3 Object Lock on this bucket. Can only be set at creation time. Requires an active project-level compliance lock.",
"url_path_style": "URL in path style.",
"url_virtual_hosted_style": "URL in virtual hosted style.",
"region": "The resource region. If not defined, the provider region is used.",
Expand Down Expand Up @@ -150,6 +154,15 @@ func (r *bucketResource) Schema(_ context.Context, _ resource.SchemaRequest, res
validate.NoSeparator(),
},
},
"object_lock": schema.BoolAttribute{
Description: descriptions["object_lock"],
Optional: true,
Computed: true,
Default: booldefault.StaticBool(false),
PlanModifiers: []planmodifier.Bool{
boolplanmodifier.RequiresReplace(),
},
},
"url_path_style": schema.StringAttribute{
Computed: true,
},
Expand Down Expand Up @@ -196,7 +209,7 @@ func (r *bucketResource) Create(ctx context.Context, req resource.CreateRequest,
}

// Create new bucket
_, err = r.client.CreateBucket(ctx, projectId, region, bucketName).Execute()
_, err = r.client.CreateBucket(ctx, projectId, region, bucketName).ObjectLockEnabled(model.ObjectLock.ValueBool()).Execute()
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating bucket", fmt.Sprintf("Calling API: %v", err))
return
Expand Down Expand Up @@ -367,6 +380,7 @@ func mapFields(bucketResp *objectstorage.GetBucketResponse, model *Model, region
model.URLPathStyle = types.StringPointerValue(bucket.UrlPathStyle)
model.URLVirtualHostedStyle = types.StringPointerValue(bucket.UrlVirtualHostedStyle)
model.Region = types.StringValue(region)
model.ObjectLock = types.BoolPointerValue(bucket.ObjectLockEnabled)
return nil
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,14 @@ func TestMapFields(t *testing.T) {
Bucket: &objectstorage.Bucket{
UrlPathStyle: utils.Ptr("url/path/style"),
UrlVirtualHostedStyle: utils.Ptr("url/virtual/hosted/style"),
ObjectLockEnabled: utils.Ptr(true),
},
},
Model{
Id: types.StringValue(id),
Name: types.StringValue("bname"),
ProjectId: types.StringValue("pid"),
ObjectLock: types.BoolValue(true),
URLPathStyle: types.StringValue("url/path/style"),
URLVirtualHostedStyle: types.StringValue("url/virtual/hosted/style"),
Region: types.StringValue("eu01"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ var testConfigVarsMin = config.Variables{
"objectstorage_bucket_name": config.StringVariable(fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(20, acctest.CharSetAlpha))),
"objectstorage_credentials_group_name": config.StringVariable(fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(20, acctest.CharSetAlpha))),
"expiration_timestamp": config.StringVariable(fmt.Sprintf("%d-01-02T03:04:05Z", time.Now().Year()+1)),

"objectstorage_bucket_name_with_lock": config.StringVariable(fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(20, acctest.CharSetAlpha))),
"object_lock": config.BoolVariable(true),
}

func TestAccObjectStorageResourceMin(t *testing.T) {
Expand All @@ -46,6 +49,7 @@ func TestAccObjectStorageResourceMin(t *testing.T) {
resource.TestCheckResourceAttr("stackit_objectstorage_bucket.bucket", "name", testutil.ConvertConfigVariable(testConfigVarsMin["objectstorage_bucket_name"])),
resource.TestCheckResourceAttrSet("stackit_objectstorage_bucket.bucket", "url_path_style"),
resource.TestCheckResourceAttrSet("stackit_objectstorage_bucket.bucket", "url_virtual_hosted_style"),
resource.TestCheckResourceAttr("stackit_objectstorage_bucket.bucket", "object_lock", "false"),

// Credentials group data
resource.TestCheckResourceAttr("stackit_objectstorage_credentials_group.credentials_group", "project_id", testutil.ConvertConfigVariable(testConfigVarsMin["project_id"])),
Expand Down Expand Up @@ -85,6 +89,13 @@ func TestAccObjectStorageResourceMin(t *testing.T) {
// compliance lock
resource.TestCheckResourceAttr("stackit_objectstorage_compliance_lock.compliance_lock", "project_id", testutil.ConvertConfigVariable(testConfigVarsMin["project_id"])),
resource.TestCheckResourceAttrSet("stackit_objectstorage_compliance_lock.compliance_lock", "max_retention_days"),

// object storage with object lock enabled
resource.TestCheckResourceAttr("stackit_objectstorage_bucket.bucket_object_lock", "project_id", testutil.ConvertConfigVariable(testConfigVarsMin["project_id"])),
resource.TestCheckResourceAttr("stackit_objectstorage_bucket.bucket_object_lock", "name", testutil.ConvertConfigVariable(testConfigVarsMin["objectstorage_bucket_name_with_lock"])),
resource.TestCheckResourceAttrSet("stackit_objectstorage_bucket.bucket_object_lock", "url_path_style"),
resource.TestCheckResourceAttrSet("stackit_objectstorage_bucket.bucket_object_lock", "url_virtual_hosted_style"),
resource.TestCheckResourceAttr("stackit_objectstorage_bucket.bucket_object_lock", "object_lock", testutil.ConvertConfigVariable(testConfigVarsMin["object_lock"])),
),
},
// Data source
Expand Down Expand Up @@ -116,6 +127,10 @@ func TestAccObjectStorageResourceMin(t *testing.T) {
}
data "stackit_objectstorage_compliance_lock" "compliance_lock" {
project_id = stackit_objectstorage_compliance_lock.compliance_lock.project_id
}
data "stackit_objectstorage_bucket" "bucket_object_lock" {
project_id = stackit_objectstorage_bucket.bucket_object_lock.project_id
name = stackit_objectstorage_bucket.bucket_object_lock.name
}`,
testutil.ObjectStorageProviderConfig()+resourceMinConfig,
),
Expand All @@ -134,6 +149,10 @@ func TestAccObjectStorageResourceMin(t *testing.T) {
"stackit_objectstorage_bucket.bucket", "url_virtual_hosted_style",
"data.stackit_objectstorage_bucket.bucket", "url_virtual_hosted_style",
),
resource.TestCheckResourceAttrPair(
"stackit_objectstorage_bucket.bucket", "object_lock",
"data.stackit_objectstorage_bucket.bucket", "object_lock",
),

// Credentials group data
resource.TestCheckResourceAttr("data.stackit_objectstorage_credentials_group.credentials_group", "project_id", testutil.ConvertConfigVariable(testConfigVarsMin["project_id"])),
Expand Down Expand Up @@ -197,6 +216,25 @@ func TestAccObjectStorageResourceMin(t *testing.T) {
// Compliance lock
resource.TestCheckResourceAttr("data.stackit_objectstorage_compliance_lock.compliance_lock", "project_id", testutil.ConvertConfigVariable(testConfigVarsMin["project_id"])),
resource.TestCheckResourceAttrSet("data.stackit_objectstorage_compliance_lock.compliance_lock", "max_retention_days"),

// Bucket data with object lock
resource.TestCheckResourceAttr("data.stackit_objectstorage_bucket.bucket_object_lock", "project_id", testutil.ConvertConfigVariable(testConfigVarsMin["project_id"])),
resource.TestCheckResourceAttrPair(
"stackit_objectstorage_bucket.bucket_object_lock", "name",
"data.stackit_objectstorage_bucket.bucket_object_lock", "name",
),
resource.TestCheckResourceAttrPair(
"stackit_objectstorage_bucket.bucket_object_lock", "url_path_style",
"data.stackit_objectstorage_bucket.bucket_object_lock", "url_path_style",
),
resource.TestCheckResourceAttrPair(
"stackit_objectstorage_bucket.bucket_object_lock", "url_virtual_hosted_style",
"data.stackit_objectstorage_bucket.bucket_object_lock", "url_virtual_hosted_style",
),
resource.TestCheckResourceAttrPair(
"stackit_objectstorage_bucket.bucket_object_lock", "object_lock",
"data.stackit_objectstorage_bucket.bucket_object_lock", "object_lock",
),
),
},
// Import
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ variable "objectstorage_bucket_name" {}
variable "objectstorage_credentials_group_name" {}
variable "expiration_timestamp" {}

variable "objectstorage_bucket_name_with_lock" {}
variable "object_lock" {}

resource "stackit_objectstorage_bucket" "bucket" {
project_id = var.project_id
name = var.objectstorage_bucket_name
Expand All @@ -27,4 +30,11 @@ resource "stackit_objectstorage_credential" "credential_time" {

resource "stackit_objectstorage_compliance_lock" "compliance_lock" {
project_id = var.project_id
}

resource "stackit_objectstorage_bucket" "bucket_object_lock" {
depends_on = [stackit_objectstorage_compliance_lock.compliance_lock]
project_id = var.project_id
name = var.objectstorage_bucket_name_with_lock
object_lock = var.object_lock
}
Loading