Skip to content

Commit a73706d

Browse files
authored
Add warning to project members fields and remove field from docs (#511)
1 parent cc3cf05 commit a73706d

5 files changed

Lines changed: 64 additions & 76 deletions

File tree

docs/data-sources/resourcemanager_project.md

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,28 +20,18 @@ data "stackit_resourcemanager_project" "example" {
2020
```
2121

2222
<!-- schema generated by tfplugindocs -->
23+
2324
## Schema
2425

2526
### Optional
2627

2728
- `container_id` (String) Project container ID. Globally unique, user-friendly identifier.
28-
- `owner_email` (String, Deprecated) Email address of the owner of the project. This value is only considered during creation. Changing it afterwards will have no effect.
29-
30-
!> The "owner_email" field has been deprecated in favor of the "members" field. Please use the "members" field to assign the owner role to a user, by setting the "role" field to `owner`.
29+
- `owner_email` (String) Email address of the owner of the project. This value is only considered during creation. Changing it afterwards will have no effect.
3130
- `project_id` (String) Project UUID identifier. This is the ID that can be used in most of the other resources to identify the project.
3231

3332
### Read-Only
3433

3534
- `id` (String) Terraform's internal data source. ID. It is structured as "`container_id`".
3635
- `labels` (Map of String) Labels are key-value string pairs which can be attached to a resource container. A label key must match the regex [A-ZÄÜÖa-zäüöß0-9_-]{1,64}. A label value must match the regex ^$|[A-ZÄÜÖa-zäüöß0-9_-]{1,64}
37-
- `members` (Attributes List) The members assigned to the project. At least one subject needs to be a user, and not a client or service account. (see [below for nested schema](#nestedatt--members))
3836
- `name` (String) Project name.
3937
- `parent_container_id` (String) Parent resource identifier. Both container ID (user-friendly) and UUID are supported
40-
41-
<a id="nestedatt--members"></a>
42-
### Nested Schema for `members`
43-
44-
Read-Only:
45-
46-
- `role` (String) The role of the member in the project. Legacy roles (`project.admin`, `project.auditor`, `project.member`, `project.owner`) are not supported.
47-
- `subject` (String) Unique identifier of the user, service account or client. This is usually the email address for users or service accounts, and the name in case of clients.

docs/resources/resourcemanager_project.md

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,12 @@ resource "stackit_resourcemanager_project" "example" {
1919
labels = {
2020
"Label 1" = "foo"
2121
}
22-
members = [
23-
{
24-
"subject" : "john.doe@stackit.cloud"
25-
"role" : "owner",
26-
},
27-
{
28-
"subject" : "some.engineer@stackit.cloud"
29-
"role" : "reader",
30-
},
31-
]
22+
owner_email = "john.doe@stackit.cloud"
3223
}
3324
```
3425

3526
<!-- schema generated by tfplugindocs -->
27+
3628
## Schema
3729

3830
### Required
@@ -43,21 +35,10 @@ resource "stackit_resourcemanager_project" "example" {
4335
### Optional
4436

4537
- `labels` (Map of String) Labels are key-value string pairs which can be attached to a resource container. A label key must match the regex [A-ZÄÜÖa-zäüöß0-9_-]{1,64}. A label value must match the regex ^$|[A-ZÄÜÖa-zäüöß0-9_-]{1,64}
46-
- `members` (Attributes List) The members assigned to the project. At least one subject needs to be a user, and not a client or service account. (see [below for nested schema](#nestedatt--members))
47-
- `owner_email` (String, Deprecated) Email address of the owner of the project. This value is only considered during creation. Changing it afterwards will have no effect.
48-
49-
!> The "owner_email" field has been deprecated in favor of the "members" field. Please use the "members" field to assign the owner role to a user, by setting the "role" field to `owner`.
38+
- `owner_email` (String) Email address of the owner of the project. This value is only considered during creation. Changing it afterwards will have no effect.
5039

5140
### Read-Only
5241

5342
- `container_id` (String) Project container ID. Globally unique, user-friendly identifier.
5443
- `id` (String) Terraform's internal resource ID. It is structured as "`container_id`".
5544
- `project_id` (String) Project UUID identifier. This is the ID that can be used in most of the other resources to identify the project.
56-
57-
<a id="nestedatt--members"></a>
58-
### Nested Schema for `members`
59-
60-
Required:
61-
62-
- `role` (String) The role of the member in the project. Possible values include, but are not limited to: `owner`, `editor`, `reader`. Legacy roles (`project.admin`, `project.auditor`, `project.member`, `project.owner`) are not supported.
63-
- `subject` (String) Unique identifier of the user, service account or client. This is usually the email address for users or service accounts, and the name in case of clients.

examples/resources/stackit_resourcemanager_project/resource.tf

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,5 @@ resource "stackit_resourcemanager_project" "example" {
44
labels = {
55
"Label 1" = "foo"
66
}
7-
members = [
8-
{
9-
"subject" : "john.doe@stackit.cloud"
10-
"role" : "owner",
11-
},
12-
{
13-
"subject" : "some.engineer@stackit.cloud"
14-
"role" : "reader",
15-
},
16-
]
7+
owner_email = "john.doe@stackit.cloud"
178
}

stackit/internal/services/resourcemanager/project/datasource.go

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -102,18 +102,17 @@ func (d *projectDataSource) Configure(ctx context.Context, req datasource.Config
102102
// Schema defines the schema for the data source.
103103
func (d *projectDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
104104
descriptions := map[string]string{
105-
"main": "Resource Manager project data source schema. To identify the project, you need to provider either project_id or container_id. If you provide both, project_id will be used.",
106-
"id": "Terraform's internal data source. ID. It is structured as \"`container_id`\".",
107-
"project_id": "Project UUID identifier. This is the ID that can be used in most of the other resources to identify the project.",
108-
"container_id": "Project container ID. Globally unique, user-friendly identifier.",
109-
"parent_container_id": "Parent resource identifier. Both container ID (user-friendly) and UUID are supported",
110-
"name": "Project name.",
111-
"labels": `Labels are key-value string pairs which can be attached to a resource container. A label key must match the regex [A-ZÄÜÖa-zäüöß0-9_-]{1,64}. A label value must match the regex ^$|[A-ZÄÜÖa-zäüöß0-9_-]{1,64}`,
112-
"owner_email": "Email address of the owner of the project. This value is only considered during creation. Changing it afterwards will have no effect.",
113-
"owner_email_deprecation_message": "The \"owner_email\" field has been deprecated in favor of the \"members\" field. Please use the \"members\" field to assign the owner role to a user, by setting the \"role\" field to `owner`.",
114-
"members": "The members assigned to the project. At least one subject needs to be a user, and not a client or service account.",
115-
"members.role": fmt.Sprintf("The role of the member in the project. Legacy roles (%s) are not supported.", strings.Join(utils.QuoteValues(utils.LegacyProjectRoles), ", ")),
116-
"members.subject": "Unique identifier of the user, service account or client. This is usually the email address for users or service accounts, and the name in case of clients.",
105+
"main": "Resource Manager project data source schema. To identify the project, you need to provider either project_id or container_id. If you provide both, project_id will be used.",
106+
"id": "Terraform's internal data source. ID. It is structured as \"`container_id`\".",
107+
"project_id": "Project UUID identifier. This is the ID that can be used in most of the other resources to identify the project.",
108+
"container_id": "Project container ID. Globally unique, user-friendly identifier.",
109+
"parent_container_id": "Parent resource identifier. Both container ID (user-friendly) and UUID are supported",
110+
"name": "Project name.",
111+
"labels": `Labels are key-value string pairs which can be attached to a resource container. A label key must match the regex [A-ZÄÜÖa-zäüöß0-9_-]{1,64}. A label value must match the regex ^$|[A-ZÄÜÖa-zäüöß0-9_-]{1,64}`,
112+
"owner_email": "Email address of the owner of the project. This value is only considered during creation. Changing it afterwards will have no effect.",
113+
"members": "The members assigned to the project. At least one subject needs to be a user, and not a client or service account.",
114+
"members.role": fmt.Sprintf("The role of the member in the project. Legacy roles (%s) are not supported.", strings.Join(utils.QuoteValues(utils.LegacyProjectRoles), ", ")),
115+
"members.subject": "Unique identifier of the user, service account or client. This is usually the email address for users or service accounts, and the name in case of clients.",
117116
}
118117

119118
resp.Schema = schema.Schema{
@@ -170,10 +169,8 @@ func (d *projectDataSource) Schema(_ context.Context, _ datasource.SchemaRequest
170169
},
171170
},
172171
"owner_email": schema.StringAttribute{
173-
Description: descriptions["owner_email"],
174-
DeprecationMessage: descriptions["owner_email_deprecation_message"],
175-
MarkdownDescription: fmt.Sprintf("%s\n\n!> %s", descriptions["owner_email"], descriptions["owner_email_deprecation_message"]),
176-
Optional: true,
172+
Description: descriptions["owner_email"],
173+
Optional: true,
177174
},
178175
"members": schema.ListNestedAttribute{
179176
Description: descriptions["members"],

stackit/internal/services/resourcemanager/project/resource.go

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -147,18 +147,17 @@ func (r *projectResource) Configure(ctx context.Context, req resource.ConfigureR
147147
// Schema defines the schema for the resource.
148148
func (r *projectResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
149149
descriptions := map[string]string{
150-
"main": "Resource Manager project resource schema. To use this resource, it is required that you set the service account email in the provider configuration.",
151-
"id": "Terraform's internal resource ID. It is structured as \"`container_id`\".",
152-
"project_id": "Project UUID identifier. This is the ID that can be used in most of the other resources to identify the project.",
153-
"container_id": "Project container ID. Globally unique, user-friendly identifier.",
154-
"parent_container_id": "Parent resource identifier. Both container ID (user-friendly) and UUID are supported",
155-
"name": "Project name.",
156-
"labels": "Labels are key-value string pairs which can be attached to a resource container. A label key must match the regex [A-ZÄÜÖa-zäüöß0-9_-]{1,64}. A label value must match the regex ^$|[A-ZÄÜÖa-zäüöß0-9_-]{1,64}",
157-
"owner_email": "Email address of the owner of the project. This value is only considered during creation. Changing it afterwards will have no effect.",
158-
"owner_email_deprecation_message": "The \"owner_email\" field has been deprecated in favor of the \"members\" field. Please use the \"members\" field to assign the owner role to a user, by setting the \"role\" field to `owner`.",
159-
"members": "The members assigned to the project. At least one subject needs to be a user, and not a client or service account.",
160-
"members.role": fmt.Sprintf("The role of the member in the project. Possible values include, but are not limited to: `owner`, `editor`, `reader`. Legacy roles (%s) are not supported.", strings.Join(utils.QuoteValues(utils.LegacyProjectRoles), ", ")),
161-
"members.subject": "Unique identifier of the user, service account or client. This is usually the email address for users or service accounts, and the name in case of clients.",
150+
"main": "Resource Manager project resource schema. To use this resource, it is required that you set the service account email in the provider configuration.",
151+
"id": "Terraform's internal resource ID. It is structured as \"`container_id`\".",
152+
"project_id": "Project UUID identifier. This is the ID that can be used in most of the other resources to identify the project.",
153+
"container_id": "Project container ID. Globally unique, user-friendly identifier.",
154+
"parent_container_id": "Parent resource identifier. Both container ID (user-friendly) and UUID are supported",
155+
"name": "Project name.",
156+
"labels": "Labels are key-value string pairs which can be attached to a resource container. A label key must match the regex [A-ZÄÜÖa-zäüöß0-9_-]{1,64}. A label value must match the regex ^$|[A-ZÄÜÖa-zäüöß0-9_-]{1,64}",
157+
"owner_email": "Email address of the owner of the project. This value is only considered during creation. Changing it afterwards will have no effect.",
158+
"members": "The members assigned to the project. At least one subject needs to be a user, and not a client or service account.",
159+
"members.role": fmt.Sprintf("The role of the member in the project. Possible values include, but are not limited to: `owner`, `editor`, `reader`. Legacy roles (%s) are not supported.", strings.Join(utils.QuoteValues(utils.LegacyProjectRoles), ", ")),
160+
"members.subject": "Unique identifier of the user, service account or client. This is usually the email address for users or service accounts, and the name in case of clients.",
162161
}
163162

164163
resp.Schema = schema.Schema{
@@ -224,16 +223,13 @@ func (r *projectResource) Schema(_ context.Context, _ resource.SchemaRequest, re
224223
},
225224
},
226225
"owner_email": schema.StringAttribute{
227-
Description: descriptions["owner_email"],
228-
DeprecationMessage: descriptions["owner_email_deprecation_message"],
229-
MarkdownDescription: fmt.Sprintf("%s\n\n!> %s", descriptions["owner_email"], descriptions["owner_email_deprecation_message"]),
226+
Description: descriptions["owner_email"],
230227
// When removing the owner_email field, we should mark the members field as required and add a listvalidator.SizeAtLeast(1) validator to it
231228
Optional: true,
232229
},
233230
"members": schema.ListNestedAttribute{
234231
Description: descriptions["members"],
235232
Optional: true,
236-
// Computed: true,
237233
NestedObject: schema.NestedAttributeObject{
238234
Attributes: map[string]schema.Attribute{
239235
"role": schema.StringAttribute{
@@ -254,6 +250,39 @@ func (r *projectResource) Schema(_ context.Context, _ resource.SchemaRequest, re
254250
}
255251
}
256252

253+
// ModifyPlan will be called in the Plan phase and will check if the members field is set
254+
func (r *projectResource) ModifyPlan(ctx context.Context, req resource.ModifyPlanRequest, resp *resource.ModifyPlanResponse) { // nolint:gocritic // function signature required by Terraform
255+
var model Model
256+
diags := req.Plan.Get(ctx, &model)
257+
if diags.HasError() {
258+
resp.Diagnostics.Append(diags...)
259+
return
260+
}
261+
262+
membersResp, err := r.authorizationClient.ListMembersExecute(ctx, projectResourceType, model.ProjectId.ValueString())
263+
if err != nil {
264+
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating project", fmt.Sprintf("Reading members: %v", err))
265+
return
266+
}
267+
268+
members := []string{}
269+
for _, m := range *membersResp.Members {
270+
if utils.IsLegacyProjectRole(*m.Role) {
271+
continue
272+
}
273+
members = append(members, fmt.Sprintf(" - %s (%s)", *m.Subject, *m.Role))
274+
}
275+
276+
if !(model.Members.IsNull() || model.Members.IsUnknown()) {
277+
core.LogAndAddWarning(ctx, &resp.Diagnostics, "The members set in the \"members\" field will override the current members in your project",
278+
fmt.Sprintf("%s\n%s\n%s\n\n%s",
279+
"The current members in your project will be removed and replaced with the members set in the \"members\" field.",
280+
"This might not be represented in the Terraform plan if you are migrating from the \"owner_email\" field, since the current members are not yet set in the state.",
281+
"Please make sure that the members in the \"members\" field are correct and complete.",
282+
fmt.Sprintf("Current members in your project:\n%v", strings.Join(members, "\n"))))
283+
}
284+
}
285+
257286
// ConfigValidators validates the resource configuration
258287
func (r *projectResource) ConfigValidators(_ context.Context) []resource.ConfigValidator {
259288
return []resource.ConfigValidator{

0 commit comments

Comments
 (0)