Support project UUID identifier in resource manager project (#161)

* Add projectId to resource manager project, fix value conversion error

* Support both uuid and container id, update acceptance tests

* Update docs

* Fix unit tests

* Adapt acc test names
This commit is contained in:
Vicente Pinto 2023-12-13 14:17:28 +00:00 committed by GitHub
parent dc3c3487c0
commit 62b6a1b3de
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 226 additions and 65 deletions

View file

@ -24,6 +24,9 @@ generate-docs:
@echo "Generating documentation with tfplugindocs"
@$(SCRIPTS_BASE)/tfplugindocs.sh
build:
@go build -o bin/terraform-provider-stackit
# TEST
test:
@echo "Running tests for the terraform provider"

View file

@ -3,12 +3,12 @@
page_title: "stackit_resourcemanager_project Data Source - stackit"
subcategory: ""
description: |-
Resource Manager project data source schema.
Resource Manager project data source schema. To identify the project, you need to provider either projectid or containerid. If you provide both, project_id will be used.
---
# stackit_resourcemanager_project (Data Source)
Resource Manager project data source schema.
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.
## Example Usage
@ -22,13 +22,14 @@ data "stackit_resourcemanager_project" "example" {
<!-- schema generated by tfplugindocs -->
## Schema
### Required
### Optional
- `container_id` (String) Project container ID.
- `container_id` (String) Project container ID. Globally unique, user-friendly identifier.
- `project_id` (String) Project UUID identifier. This is the ID that can be used in most of the other resources to identify the project.
### Read-Only
- `id` (String) Terraform's internal data source. ID. It is structured as "`container_id`".
- `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}
- `name` (String) Project name.
- `parent_container_id` (String) Parent container ID
- `parent_container_id` (String) Parent resource identifier. Both container ID (user-friendly) and UUID are supported

View file

@ -131,7 +131,7 @@ Using this flow is less secure since the token is long-lived. You can provide th
- `region` (String) Region will be used as the default location for regional services. Not all services require a region, some are global
- `resourcemanager_custom_endpoint` (String) Custom endpoint for the Resource Manager service
- `secretsmanager_custom_endpoint` (String) Custom endpoint for the Secrets Manager service
- `service_account_email` (String) Service account email. It can also be set using the environment variable STACKIT_SERVICE_ACCOUNT_EMAIL
- `service_account_email` (String) Service account email. It can also be set using the environment variable STACKIT_SERVICE_ACCOUNT_EMAIL. It is required if you want to use the resource manager project resource.
- `service_account_key` (String) Service account key used for authentication. If set alongside private key, the key flow will be used to authenticate all operations.
- `service_account_key_path` (String) Path for the service account key used for authentication. If set alongside the private key, the key flow will be used to authenticate all operations.
- `service_account_token` (String) Token used for authentication. If set, the token flow will be used to authenticate all operations.

View file

@ -3,12 +3,12 @@
page_title: "stackit_resourcemanager_project Resource - stackit"
subcategory: ""
description: |-
Resource Manager project resource schema.
Resource Manager project resource schema. To use this resource, it is required that you set the service account email in the provider configuration.
---
# stackit_resourcemanager_project (Resource)
Resource Manager project resource schema.
Resource Manager project resource schema. To use this resource, it is required that you set the service account email in the provider configuration.
## Example Usage
@ -31,7 +31,7 @@ resource "stackit_resourcemanager_project" "example" {
- `name` (String) Project name.
- `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.
- `parent_container_id` (String) Parent container ID
- `parent_container_id` (String) Parent resource identifier. Both container ID (user-friendly) and UUID are supported
### Optional
@ -41,3 +41,4 @@ resource "stackit_resourcemanager_project" "example" {
- `container_id` (String) Project container ID. Globally unique, user-friendly identifier.
- `id` (String) Terraform's internal resource ID. It is structured as "`container_id`".
- `project_id` (String) Project UUID identifier. This is the ID that can be used in most of the other resources to identify the project.

View file

@ -111,9 +111,12 @@ Optional:
Required:
- `allowed_cidrs` (List of String) Specify a list of CIDRs to whitelist.
- `enabled` (Boolean) Is ACL enabled?
Optional:
- `allowed_cidrs` (List of String) Specify a list of CIDRs to whitelist.
<a id="nestedatt--extensions--argus"></a>
### Nested Schema for `extensions.argus`

View file

@ -28,6 +28,7 @@ var (
type ModelData struct {
Id types.String `tfsdk:"id"` // needed by TF
ProjectId types.String `tfsdk:"project_id"`
ContainerId types.String `tfsdk:"container_id"`
ContainerParentId types.String `tfsdk:"parent_container_id"`
Name types.String `tfsdk:"name"`
@ -88,10 +89,11 @@ func (d *projectDataSource) Configure(ctx context.Context, req datasource.Config
// Schema defines the schema for the data source.
func (d *projectDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
descriptions := map[string]string{
"main": "Resource Manager project data source schema.",
"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.",
"id": "Terraform's internal data source. ID. It is structured as \"`container_id`\".",
"container_id": "Project container ID.",
"parent_container_id": "Parent container ID",
"project_id": "Project UUID identifier. This is the ID that can be used in most of the other resources to identify the project.",
"container_id": "Project container ID. Globally unique, user-friendly identifier.",
"parent_container_id": "Parent resource identifier. Both container ID (user-friendly) and UUID are supported",
"name": "Project name.",
"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}`,
}
@ -103,9 +105,16 @@ func (d *projectDataSource) Schema(_ context.Context, _ datasource.SchemaRequest
Description: descriptions["id"],
Computed: true,
},
"project_id": schema.StringAttribute{
Description: descriptions["project_id"],
Optional: true,
Validators: []validator.String{
validate.UUID(),
},
},
"container_id": schema.StringAttribute{
Description: descriptions["container_id"],
Required: true,
Optional: true,
Validators: []validator.String{
validate.NoSeparator(),
},
@ -154,10 +163,25 @@ func (d *projectDataSource) Read(ctx context.Context, req datasource.ReadRequest
if resp.Diagnostics.HasError() {
return
}
containerId := state.ContainerId.ValueString()
ctx = tflog.SetField(ctx, "project_id", containerId)
projectResp, err := d.client.GetProject(ctx, containerId).Execute()
projectId := state.ProjectId.ValueString()
ctx = tflog.SetField(ctx, "project_id", projectId)
containerId := state.ContainerId.ValueString()
ctx = tflog.SetField(ctx, "container_id", containerId)
if containerId == "" && projectId == "" {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading project", "Either container_id or project_id must be set")
return
}
// set project identifier. If projectId is provided, it takes precedence over containerId
var identifier = containerId
if projectId != "" {
identifier = projectId
}
projectResp, err := d.client.GetProject(ctx, identifier).Execute()
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading project", fmt.Sprintf("Calling API: %v", err))
return
@ -184,6 +208,15 @@ func mapDataFields(ctx context.Context, projectResp *resourcemanager.ProjectResp
return fmt.Errorf("model input is nil")
}
var projectId string
if model.ProjectId.ValueString() != "" {
projectId = model.ProjectId.ValueString()
} else if projectResp.ProjectId != nil {
projectId = *projectResp.ProjectId
} else {
return fmt.Errorf("project id not present")
}
var containerId string
if model.ContainerId.ValueString() != "" {
containerId = model.ContainerId.ValueString()
@ -204,6 +237,7 @@ func mapDataFields(ctx context.Context, projectResp *resourcemanager.ProjectResp
}
model.Id = types.StringValue(containerId)
model.ProjectId = types.StringValue(projectId)
model.ContainerId = types.StringValue(containerId)
model.ContainerParentId = types.StringPointerValue(projectResp.Parent.ContainerId)
model.Name = types.StringPointerValue(projectResp.Name)

View file

@ -6,6 +6,7 @@ import (
"regexp"
"strings"
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-framework-validators/mapvalidator"
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
@ -39,6 +40,7 @@ const (
type Model struct {
Id types.String `tfsdk:"id"` // needed by TF
ProjectId types.String `tfsdk:"project_id"`
ContainerId types.String `tfsdk:"container_id"`
ContainerParentId types.String `tfsdk:"parent_container_id"`
Name types.String `tfsdk:"name"`
@ -102,10 +104,11 @@ func (r *projectResource) Configure(ctx context.Context, req resource.ConfigureR
// Schema defines the schema for the resource.
func (r *projectResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
descriptions := map[string]string{
"main": "Resource Manager project resource schema.",
"main": "Resource Manager project resource schema. To use this resource, it is required that you set the service account email in the provider configuration.",
"id": "Terraform's internal resource ID. It is structured as \"`container_id`\".",
"project_id": "Project UUID identifier. This is the ID that can be used in most of the other resources to identify the project.",
"container_id": "Project container ID. Globally unique, user-friendly identifier.",
"parent_container_id": "Parent container ID",
"parent_container_id": "Parent resource identifier. Both container ID (user-friendly) and UUID are supported",
"name": "Project name.",
"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}",
"owner_email": "Email address of the owner of the project. This value is only considered during creation. Changing it afterwards will have no effect.",
@ -121,6 +124,16 @@ func (r *projectResource) Schema(_ context.Context, _ resource.SchemaRequest, re
stringplanmodifier.UseStateForUnknown(),
},
},
"project_id": schema.StringAttribute{
Description: descriptions["project_id"],
Computed: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
},
Validators: []validator.String{
validate.UUID(),
},
},
"container_id": schema.StringAttribute{
Description: descriptions["container_id"],
Computed: true,
@ -357,6 +370,15 @@ func mapFields(ctx context.Context, projectResp *resourcemanager.ProjectResponse
return fmt.Errorf("model input is nil")
}
var projectId string
if model.ProjectId.ValueString() != "" {
projectId = model.ProjectId.ValueString()
} else if projectResp.ProjectId != nil {
projectId = *projectResp.ProjectId
} else {
return fmt.Errorf("project id not present")
}
var containerId string
if model.ContainerId.ValueString() != "" {
containerId = model.ContainerId.ValueString()
@ -377,9 +399,16 @@ func mapFields(ctx context.Context, projectResp *resourcemanager.ProjectResponse
}
model.Id = types.StringValue(containerId)
model.ProjectId = types.StringValue(projectId)
model.ContainerId = types.StringValue(containerId)
if projectResp.Parent != nil {
model.ContainerParentId = types.StringPointerValue(projectResp.Parent.ContainerId)
if _, err := uuid.Parse(model.ContainerParentId.ValueString()); err == nil {
// the provided containerParentId is the UUID identifier
model.ContainerParentId = types.StringPointerValue(projectResp.Parent.Id)
} else {
// the provided containerParentId is the user-friendly container id
model.ContainerParentId = types.StringPointerValue(projectResp.Parent.ContainerId)
}
} else {
model.ContainerParentId = types.StringNull()
}

View file

@ -5,6 +5,7 @@ import (
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/stackitcloud/stackit-sdk-go/core/utils"
"github.com/stackitcloud/stackit-sdk-go/services/resourcemanager"
@ -12,21 +13,26 @@ import (
)
func TestMapFields(t *testing.T) {
testUUID := uuid.New().String()
tests := []struct {
description string
input *resourcemanager.ProjectResponseWithParents
expected Model
expectedLabels *map[string]string
isValid bool
description string
uuidContainerParentId bool
input *resourcemanager.ProjectResponseWithParents
expected Model
expectedLabels *map[string]string
isValid bool
}{
{
"default_ok",
false,
&resourcemanager.ProjectResponseWithParents{
ContainerId: utils.Ptr("cid"),
ProjectId: utils.Ptr("pid"),
},
Model{
Id: types.StringValue("cid"),
ContainerId: types.StringValue("cid"),
ProjectId: types.StringValue("pid"),
ContainerParentId: types.StringNull(),
Name: types.StringNull(),
},
@ -34,22 +40,55 @@ func TestMapFields(t *testing.T) {
true,
},
{
"values_ok",
"container_parent_id_ok",
false,
&resourcemanager.ProjectResponseWithParents{
ContainerId: utils.Ptr("cid"),
ProjectId: utils.Ptr("pid"),
Labels: &map[string]string{
"label1": "ref1",
"label2": "ref2",
},
Parent: &resourcemanager.Parent{
ContainerId: utils.Ptr("pid"),
ContainerId: utils.Ptr("parent_cid"),
Id: utils.Ptr("parent_pid"),
},
Name: utils.Ptr("name"),
},
Model{
Id: types.StringValue("cid"),
ContainerId: types.StringValue("cid"),
ContainerParentId: types.StringValue("pid"),
ProjectId: types.StringValue("pid"),
ContainerParentId: types.StringValue("parent_cid"),
Name: types.StringValue("name"),
},
&map[string]string{
"label1": "ref1",
"label2": "ref2",
},
true,
},
{
"uuid_parent_id_ok",
true,
&resourcemanager.ProjectResponseWithParents{
ContainerId: utils.Ptr("cid"),
ProjectId: utils.Ptr("pid"),
Labels: &map[string]string{
"label1": "ref1",
"label2": "ref2",
},
Parent: &resourcemanager.Parent{
ContainerId: utils.Ptr("parent_cid"),
Id: utils.Ptr(testUUID),
},
Name: utils.Ptr("name"),
},
Model{
Id: types.StringValue("cid"),
ContainerId: types.StringValue("cid"),
ProjectId: types.StringValue("pid"),
ContainerParentId: types.StringValue(testUUID),
Name: types.StringValue("name"),
},
&map[string]string{
@ -60,6 +99,7 @@ func TestMapFields(t *testing.T) {
},
{
"response_nil_fail",
false,
nil,
Model{},
nil,
@ -67,6 +107,7 @@ func TestMapFields(t *testing.T) {
},
{
"no_resource_id",
false,
&resourcemanager.ProjectResponseWithParents{},
Model{},
nil,
@ -84,8 +125,13 @@ func TestMapFields(t *testing.T) {
}
tt.expected.Labels = convertedLabels
}
var containerParentId = types.StringNull()
if tt.uuidContainerParentId {
containerParentId = types.StringValue(testUUID)
}
state := &Model{
ContainerId: tt.expected.ContainerId,
ContainerId: tt.expected.ContainerId,
ContainerParentId: containerParentId,
}
err := mapFields(context.Background(), tt.input, state)

View file

@ -19,6 +19,7 @@ import (
var projectResource = map[string]string{
"name": fmt.Sprintf("acc-pj-%s", acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)),
"parent_container_id": testutil.TestProjectParentContainerID,
"parent_uuid": testutil.TestProjectParentUUID,
"billing_reference": "TEST-REF",
"new_label": "a-label",
}
@ -29,16 +30,22 @@ func resourceConfig(name string, label *string) string {
labelConfig = fmt.Sprintf("new_label = %q", *label)
}
return fmt.Sprintf(`
%s
%[1]s
resource "stackit_resourcemanager_project" "project" {
parent_container_id = "%s"
name = "%s"
resource "stackit_resourcemanager_project" "parent_by_container" {
parent_container_id = "%[2]s"
name = "%[3]s"
labels = {
"billing_reference" = "%s"
%s
"billing_reference" = "%[4]s"
%[5]s
}
owner_email = "%s"
owner_email = "%[6]s"
}
resource "stackit_resourcemanager_project" "parent_by_uuid" {
parent_container_id = "%[7]s"
name = "%[3]s-uuid"
owner_email = "%[6]s"
}
`,
testutil.ResourceManagerProviderConfig(),
@ -47,6 +54,7 @@ func resourceConfig(name string, label *string) string {
projectResource["billing_reference"],
labelConfig,
testutil.TestProjectServiceAccountEmail,
projectResource["parent_uuid"],
)
}
@ -59,12 +67,19 @@ func TestAccResourceManagerResource(t *testing.T) {
{
Config: resourceConfig(projectResource["name"], nil),
Check: resource.ComposeAggregateTestCheckFunc(
// Project data
resource.TestCheckResourceAttrSet("stackit_resourcemanager_project.project", "container_id"),
resource.TestCheckResourceAttr("stackit_resourcemanager_project.project", "name", projectResource["name"]),
resource.TestCheckResourceAttr("stackit_resourcemanager_project.project", "parent_container_id", projectResource["parent_container_id"]),
resource.TestCheckResourceAttr("stackit_resourcemanager_project.project", "labels.%", "1"),
resource.TestCheckResourceAttr("stackit_resourcemanager_project.project", "labels.billing_reference", projectResource["billing_reference"]),
// Parent container id project data
resource.TestCheckResourceAttrSet("stackit_resourcemanager_project.parent_by_container", "container_id"),
resource.TestCheckResourceAttrSet("stackit_resourcemanager_project.parent_by_container", "project_id"),
resource.TestCheckResourceAttr("stackit_resourcemanager_project.parent_by_container", "name", projectResource["name"]),
resource.TestCheckResourceAttr("stackit_resourcemanager_project.parent_by_container", "parent_container_id", projectResource["parent_container_id"]),
resource.TestCheckResourceAttr("stackit_resourcemanager_project.parent_by_container", "labels.%", "1"),
resource.TestCheckResourceAttr("stackit_resourcemanager_project.parent_by_container", "labels.billing_reference", projectResource["billing_reference"]),
// Parent UUID project data
resource.TestCheckResourceAttrSet("stackit_resourcemanager_project.parent_by_uuid", "container_id"),
resource.TestCheckResourceAttrSet("stackit_resourcemanager_project.parent_by_uuid", "project_id"),
resource.TestCheckResourceAttr("stackit_resourcemanager_project.parent_by_uuid", "name", fmt.Sprintf("%s-uuid", projectResource["name"])),
resource.TestCheckResourceAttr("stackit_resourcemanager_project.parent_by_uuid", "parent_container_id", projectResource["parent_uuid"]),
),
},
// Data source
@ -72,30 +87,57 @@ func TestAccResourceManagerResource(t *testing.T) {
Config: fmt.Sprintf(`
%s
data "stackit_resourcemanager_project" "project" {
container_id = stackit_resourcemanager_project.project.container_id
}`,
data "stackit_resourcemanager_project" "project_by_container" {
container_id = stackit_resourcemanager_project.parent_by_container.container_id
}
data "stackit_resourcemanager_project" "project_by_uuid" {
project_id = stackit_resourcemanager_project.parent_by_container.project_id
}
data "stackit_resourcemanager_project" "project_by_both" {
container_id = stackit_resourcemanager_project.parent_by_container.container_id
project_id = stackit_resourcemanager_project.parent_by_container.project_id
}
`,
resourceConfig(projectResource["name"], nil),
),
Check: resource.ComposeAggregateTestCheckFunc(
// Project data
resource.TestCheckResourceAttrSet("data.stackit_resourcemanager_project.project", "id"),
resource.TestCheckResourceAttrSet("data.stackit_resourcemanager_project.project", "container_id"),
resource.TestCheckResourceAttr("data.stackit_resourcemanager_project.project", "name", projectResource["name"]),
resource.TestCheckResourceAttrSet("data.stackit_resourcemanager_project.project", "parent_container_id"),
resource.TestCheckResourceAttr("data.stackit_resourcemanager_project.project", "labels.%", "1"),
resource.TestCheckResourceAttr("data.stackit_resourcemanager_project.project", "labels.billing_reference", projectResource["billing_reference"]),
resource.TestCheckResourceAttrPair("data.stackit_resourcemanager_project.project", "project_id",
"stackit_resourcemanager_project.project", "project_id"),
// Container project data
resource.TestCheckResourceAttrSet("data.stackit_resourcemanager_project.project_by_container", "id"),
resource.TestCheckResourceAttrSet("data.stackit_resourcemanager_project.project_by_container", "container_id"),
resource.TestCheckResourceAttrSet("data.stackit_resourcemanager_project.project_by_container", "project_id"),
resource.TestCheckResourceAttr("data.stackit_resourcemanager_project.project_by_container", "name", projectResource["name"]),
resource.TestCheckResourceAttrSet("data.stackit_resourcemanager_project.project_by_container", "parent_container_id"),
resource.TestCheckResourceAttr("data.stackit_resourcemanager_project.project_by_container", "labels.%", "1"),
resource.TestCheckResourceAttr("data.stackit_resourcemanager_project.project_by_container", "labels.billing_reference", projectResource["billing_reference"]),
// UUID project data
resource.TestCheckResourceAttrSet("data.stackit_resourcemanager_project.project_by_uuid", "id"),
resource.TestCheckResourceAttrSet("data.stackit_resourcemanager_project.project_by_uuid", "container_id"),
resource.TestCheckResourceAttrSet("data.stackit_resourcemanager_project.project_by_uuid", "project_id"),
resource.TestCheckResourceAttr("data.stackit_resourcemanager_project.project_by_uuid", "name", projectResource["name"]),
resource.TestCheckResourceAttrSet("data.stackit_resourcemanager_project.project_by_uuid", "parent_container_id"),
resource.TestCheckResourceAttr("data.stackit_resourcemanager_project.project_by_uuid", "labels.%", "1"),
resource.TestCheckResourceAttr("data.stackit_resourcemanager_project.project_by_uuid", "labels.billing_reference", projectResource["billing_reference"]),
// Both project data
resource.TestCheckResourceAttrSet("data.stackit_resourcemanager_project.project_by_both", "id"),
resource.TestCheckResourceAttrSet("data.stackit_resourcemanager_project.project_by_both", "container_id"),
resource.TestCheckResourceAttrSet("data.stackit_resourcemanager_project.project_by_both", "project_id"),
resource.TestCheckResourceAttr("data.stackit_resourcemanager_project.project_by_both", "name", projectResource["name"]),
resource.TestCheckResourceAttrSet("data.stackit_resourcemanager_project.project_by_both", "parent_container_id"),
resource.TestCheckResourceAttr("data.stackit_resourcemanager_project.project_by_both", "labels.%", "1"),
resource.TestCheckResourceAttr("data.stackit_resourcemanager_project.project_by_both", "labels.billing_reference", projectResource["billing_reference"]),
),
},
// Import
{
ResourceName: "stackit_resourcemanager_project.project",
ResourceName: "stackit_resourcemanager_project.parent_by_container",
ImportStateIdFunc: func(s *terraform.State) (string, error) {
r, ok := s.RootModule().Resources["stackit_resourcemanager_project.project"]
r, ok := s.RootModule().Resources["stackit_resourcemanager_project.parent_by_container"]
if !ok {
return "", fmt.Errorf("couldn't find resource stackit_resourcemanager_project.project")
return "", fmt.Errorf("couldn't find resource stackit_resourcemanager_project.parent_by_container")
}
containerId, ok := r.Primary.Attributes["container_id"]
if !ok {
@ -115,12 +157,12 @@ func TestAccResourceManagerResource(t *testing.T) {
Config: resourceConfig(fmt.Sprintf("%s-new", projectResource["name"]), utils.Ptr("a-label")),
Check: resource.ComposeAggregateTestCheckFunc(
// Project data
resource.TestCheckResourceAttrSet("stackit_resourcemanager_project.project", "container_id"),
resource.TestCheckResourceAttr("stackit_resourcemanager_project.project", "name", fmt.Sprintf("%s-new", projectResource["name"])),
resource.TestCheckResourceAttr("stackit_resourcemanager_project.project", "parent_container_id", projectResource["parent_container_id"]),
resource.TestCheckResourceAttr("stackit_resourcemanager_project.project", "labels.%", "2"),
resource.TestCheckResourceAttr("stackit_resourcemanager_project.project", "labels.billing_reference", projectResource["billing_reference"]),
resource.TestCheckResourceAttr("stackit_resourcemanager_project.project", "labels.new_label", projectResource["new_label"]),
resource.TestCheckResourceAttrSet("stackit_resourcemanager_project.parent_by_container", "container_id"),
resource.TestCheckResourceAttr("stackit_resourcemanager_project.parent_by_container", "name", fmt.Sprintf("%s-new", projectResource["name"])),
resource.TestCheckResourceAttr("stackit_resourcemanager_project.parent_by_container", "parent_container_id", projectResource["parent_container_id"]),
resource.TestCheckResourceAttr("stackit_resourcemanager_project.parent_by_container", "labels.%", "2"),
resource.TestCheckResourceAttr("stackit_resourcemanager_project.parent_by_container", "labels.billing_reference", projectResource["billing_reference"]),
resource.TestCheckResourceAttr("stackit_resourcemanager_project.parent_by_container", "labels.new_label", projectResource["new_label"]),
),
},
// Deletion is done by the framework implicitly

View file

@ -30,8 +30,10 @@ var (
// ProjectId is the id of project used for tests
ProjectId = os.Getenv("TF_ACC_PROJECT_ID")
// TestProjectParentContainerID is the container id of the organization under which projects are created as part of the resource-manager acceptance tests
// TestProjectParentContainerID is the container id of the parent resource under which projects are created as part of the resource-manager acceptance tests
TestProjectParentContainerID = os.Getenv("TF_ACC_TEST_PROJECT_PARENT_CONTAINER_ID")
// TestProjectParentContainerID is the uuid of the parent resource under which projects are created as part of the resource-manager acceptance tests
TestProjectParentUUID = os.Getenv("TF_ACC_TEST_PROJECT_PARENT_UUID")
// TestProjectServiceAccountEmail is the e-mail of a service account with admin permissions on the organization under which projects are created as part of the resource-manager acceptance tests
TestProjectServiceAccountEmail = os.Getenv("TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_EMAIL")

View file

@ -107,7 +107,7 @@ func (p *Provider) Schema(_ context.Context, _ provider.SchemaRequest, resp *pro
"service_account_key": "Service account key used for authentication. If set alongside private key, the key flow will be used to authenticate all operations.",
"private_key_path": "Path for the private RSA key used for authentication. If set alongside the service account key, the key flow will be used to authenticate all operations.",
"private_key": "Private RSA key used for authentication. If set alongside the service account key, the key flow will be used to authenticate all operations.",
"service_account_email": "Service account email. It can also be set using the environment variable STACKIT_SERVICE_ACCOUNT_EMAIL",
"service_account_email": "Service account email. It can also be set using the environment variable STACKIT_SERVICE_ACCOUNT_EMAIL. It is required if you want to use the resource manager project resource.",
"region": "Region will be used as the default location for regional services. Not all services require a region, some are global",
"dns_custom_endpoint": "Custom endpoint for the DNS service",
"postgresql_custom_endpoint": "Custom endpoint for the PostgreSQL service",