Skip to content

Commit c902e6c

Browse files
authored
feat(sfs): onboard project lock resource (#1427)
relates to STACKITTPR-613
1 parent 79b9da8 commit c902e6c

10 files changed

Lines changed: 751 additions & 0 deletions

File tree

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "stackit_sfs_project_lock Data Source - stackit"
4+
subcategory: ""
5+
description: |-
6+
SFS project lock resource schema. Must have a region specified in the provider configuration. Always use only one project lock per project.
7+
---
8+
9+
# stackit_sfs_project_lock (Data Source)
10+
11+
SFS project lock resource schema. Must have a `region` specified in the provider configuration. Always use only one project lock per project.
12+
13+
## Example Usage
14+
15+
```terraform
16+
data "stackit_sfs_project_lock" "example" {
17+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
18+
}
19+
```
20+
21+
<!-- schema generated by tfplugindocs -->
22+
## Schema
23+
24+
### Required
25+
26+
- `project_id` (String) STACKIT Project ID to which the project lock is associated.
27+
28+
### Optional
29+
30+
- `region` (String) The resource region. If not defined, the provider region is used.
31+
32+
### Read-Only
33+
34+
- `id` (String) Terraform's internal resource identifier. It is structured as "`project_id`,`region`".
35+
- `lock_id` (String) ID of the lock.

docs/resources/sfs_project_lock.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "stackit_sfs_project_lock Resource - stackit"
4+
subcategory: ""
5+
description: |-
6+
SFS project lock resource schema. Must have a region specified in the provider configuration. Always use only one project lock per project.
7+
---
8+
9+
# stackit_sfs_project_lock (Resource)
10+
11+
SFS project lock resource schema. Must have a `region` specified in the provider configuration. Always use only one project lock per project.
12+
13+
## Example Usage
14+
15+
```terraform
16+
resource "stackit_sfs_project_lock" "example" {
17+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
18+
}
19+
20+
# Only use the import statement, if you want to import an existing project lock
21+
import {
22+
to = stackit_sfs_project_lock.example
23+
id = "${var.project_id},${var.region}"
24+
}
25+
```
26+
27+
<!-- schema generated by tfplugindocs -->
28+
## Schema
29+
30+
### Required
31+
32+
- `project_id` (String) STACKIT Project ID to which the project lock is associated.
33+
34+
### Optional
35+
36+
- `region` (String) The resource region. If not defined, the provider region is used.
37+
38+
### Read-Only
39+
40+
- `id` (String) Terraform's internal resource identifier. It is structured as "`project_id`,`region`".
41+
- `lock_id` (String) ID of the lock.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
data "stackit_sfs_project_lock" "example" {
2+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
3+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
resource "stackit_sfs_project_lock" "example" {
2+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
3+
}
4+
5+
# Only use the import statement, if you want to import an existing project lock
6+
import {
7+
to = stackit_sfs_project_lock.example
8+
id = "${var.project_id},${var.region}"
9+
}
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
package projectlock
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"net/http"
7+
8+
"github.com/hashicorp/terraform-plugin-framework/datasource"
9+
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
10+
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
11+
"github.com/hashicorp/terraform-plugin-log/tflog"
12+
sfs "github.com/stackitcloud/stackit-sdk-go/services/sfs/v1api"
13+
14+
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion"
15+
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core"
16+
sfsUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/sfs/utils"
17+
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils"
18+
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/validate"
19+
)
20+
21+
// Ensure the implementation satisfies the expected interfaces.
22+
var (
23+
_ datasource.DataSource = &projectlockDatasource{}
24+
_ datasource.DataSourceWithConfigure = &projectlockDatasource{}
25+
)
26+
27+
// NewProjectLockDatasource is a helper function to simplify the provider implementation.
28+
func NewProjectLockDatasource() datasource.DataSource {
29+
return &projectlockDatasource{}
30+
}
31+
32+
// projectlockDatasource is the resource implementation.
33+
type projectlockDatasource struct {
34+
client *sfs.APIClient
35+
providerData core.ProviderData
36+
}
37+
38+
// Configure adds the provider configured client to the resource.
39+
func (r *projectlockDatasource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
40+
var ok bool
41+
r.providerData, ok = conversion.ParseProviderData(ctx, req.ProviderData, &resp.Diagnostics)
42+
if !ok {
43+
return
44+
}
45+
46+
apiClient := sfsUtils.ConfigureClient(ctx, &r.providerData, &resp.Diagnostics)
47+
if resp.Diagnostics.HasError() {
48+
return
49+
}
50+
r.client = apiClient
51+
tflog.Info(ctx, "SFS client configured")
52+
}
53+
54+
// Metadata returns the resource type name.
55+
func (r *projectlockDatasource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
56+
resp.TypeName = req.ProviderTypeName + "_sfs_project_lock"
57+
}
58+
59+
// Schema defines the schema for the resource.
60+
func (r *projectlockDatasource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
61+
descriptions := map[string]string{
62+
"main": "SFS project lock resource schema. Must have a `region` specified in the provider configuration. Always use only one project lock per project.",
63+
"id": "Terraform's internal resource identifier. It is structured as \"`project_id`,`region`\".",
64+
"project_id": "STACKIT Project ID to which the project lock is associated.",
65+
"region": "The resource region. If not defined, the provider region is used.",
66+
"lock_id": "ID of the lock.",
67+
}
68+
69+
resp.Schema = schema.Schema{
70+
Description: descriptions["main"],
71+
Attributes: map[string]schema.Attribute{
72+
"id": schema.StringAttribute{
73+
Description: descriptions["id"],
74+
Computed: true,
75+
},
76+
"project_id": schema.StringAttribute{
77+
Description: descriptions["project_id"],
78+
Required: true,
79+
Validators: []validator.String{
80+
validate.UUID(),
81+
validate.NoSeparator(),
82+
},
83+
},
84+
"lock_id": schema.StringAttribute{
85+
Description: descriptions["lock_id"],
86+
Computed: true,
87+
},
88+
"region": schema.StringAttribute{
89+
Optional: true,
90+
// must be computed to allow for storing the override value from the provider
91+
Computed: true,
92+
Description: descriptions["region"],
93+
},
94+
},
95+
}
96+
}
97+
98+
// Read refreshes the Terraform state with the latest data.
99+
func (r *projectlockDatasource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { // nolint:gocritic // function signature required by Terraform
100+
var model Model
101+
resp.Diagnostics.Append(req.Config.Get(ctx, &model)...)
102+
if resp.Diagnostics.HasError() {
103+
return
104+
}
105+
106+
projectId := model.ProjectId.ValueString()
107+
region := r.providerData.GetRegionWithOverride(model.Region)
108+
109+
ctx = core.InitProviderContext(ctx)
110+
ctx = tflog.SetField(ctx, "project_id", projectId)
111+
ctx = tflog.SetField(ctx, "region", region)
112+
113+
projectResp, err := r.client.DefaultAPI.GetLock(ctx, region, projectId).Execute()
114+
if err != nil {
115+
utils.LogError(
116+
ctx,
117+
&resp.Diagnostics,
118+
err,
119+
"Reading project lock",
120+
fmt.Sprintf("Project lock does not exist in project %q.", projectId),
121+
map[int]string{
122+
http.StatusForbidden: fmt.Sprintf("Project with ID %q not found or forbidden access", projectId),
123+
},
124+
)
125+
resp.State.RemoveResource(ctx)
126+
return
127+
}
128+
129+
ctx = core.LogResponse(ctx)
130+
131+
// Map response body to schema
132+
err = mapFields(projectResp, &model, region)
133+
if err != nil {
134+
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading project lock", fmt.Sprintf("Processing API payload: %v", err))
135+
return
136+
}
137+
138+
// Set refreshed state
139+
resp.Diagnostics.Append(resp.State.Set(ctx, model)...)
140+
if resp.Diagnostics.HasError() {
141+
return
142+
}
143+
tflog.Info(ctx, "SFS project lock read")
144+
}

0 commit comments

Comments
 (0)