Skip to content
Merged
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
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 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 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 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 @@ -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 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