feat: add new attributes to git resource and datasource (#890)
* feat: add new attributes to git resource and datasource Signed-off-by: Mauritz Uphoff <mauritz.uphoff@stackit.cloud> * review changes Signed-off-by: Mauritz Uphoff <mauritz.uphoff@stackit.cloud> * review changes 2 Signed-off-by: Mauritz Uphoff <mauritz.uphoff@stackit.cloud> --------- Signed-off-by: Mauritz Uphoff <mauritz.uphoff@stackit.cloud>
This commit is contained in:
parent
3c5c8e0a6c
commit
2dda93bb76
9 changed files with 570 additions and 95 deletions
|
|
@ -32,6 +32,11 @@ data "stackit_git" "git" {
|
|||
|
||||
### Read-Only
|
||||
|
||||
- `acl` (List of String) Restricted ACL for instance access.
|
||||
- `consumed_disk` (String) How many bytes of disk space is consumed.
|
||||
- `consumed_object_storage` (String) How many bytes of Object Storage is consumed.
|
||||
- `created` (String) Instance creation timestamp in RFC3339 format.
|
||||
- `flavor` (String) Instance flavor. If not provided, defaults to git-100. For a list of available flavors, refer to our API documentation: `https://docs.api.stackit.cloud/documentation/git/version/v1beta`
|
||||
- `id` (String) Terraform's internal resource ID, structured as "`project_id`,`instance_id`".
|
||||
- `name` (String) Unique name linked to the git instance.
|
||||
- `url` (String) Url linked to the git instance.
|
||||
|
|
|
|||
|
|
@ -4,14 +4,14 @@ page_title: "stackit_git Resource - stackit"
|
|||
subcategory: ""
|
||||
description: |-
|
||||
Git Instance resource schema.
|
||||
~> This resource is in beta and may be subject to breaking changes in the future. Use with caution. See our guide https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/guides/opting_into_beta_resources for how to opt-in to use beta resources.
|
||||
~> This resource is in beta and may be subject to breaking changes in the future. Use with caution. See our guide https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/guides/opting_into_beta_resources for how to opt-in to use beta resources. This resource currently does not support updates. Changing the ACLs, flavor, or name will trigger resource recreation. Update functionality will be added soon. In the meantime, please proceed with caution. To update these attributes, please open a support ticket.
|
||||
---
|
||||
|
||||
# stackit_git (Resource)
|
||||
|
||||
Git Instance resource schema.
|
||||
|
||||
~> This resource is in beta and may be subject to breaking changes in the future. Use with caution. See our [guide](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/guides/opting_into_beta_resources) for how to opt-in to use beta resources.
|
||||
~> This resource is in beta and may be subject to breaking changes in the future. Use with caution. See our [guide](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/guides/opting_into_beta_resources) for how to opt-in to use beta resources. This resource currently does not support updates. Changing the ACLs, flavor, or name will trigger resource recreation. Update functionality will be added soon. In the meantime, please proceed with caution. To update these attributes, please open a support ticket.
|
||||
|
||||
## Example Usage
|
||||
|
||||
|
|
@ -20,6 +20,15 @@ resource "stackit_git" "git" {
|
|||
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
name = "git-example-instance"
|
||||
}
|
||||
|
||||
resource "stackit_git" "git" {
|
||||
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
name = "git-example-instance"
|
||||
acl = [
|
||||
"0.0.0.0/0"
|
||||
]
|
||||
flavor = "git-100"
|
||||
}
|
||||
```
|
||||
|
||||
<!-- schema generated by tfplugindocs -->
|
||||
|
|
@ -30,8 +39,16 @@ resource "stackit_git" "git" {
|
|||
- `name` (String) Unique name linked to the git instance.
|
||||
- `project_id` (String) STACKIT project ID to which the git instance is associated.
|
||||
|
||||
### Optional
|
||||
|
||||
- `acl` (List of String) Restricted ACL for instance access.
|
||||
- `flavor` (String) Instance flavor. If not provided, defaults to git-100. For a list of available flavors, refer to our API documentation: `https://docs.api.stackit.cloud/documentation/git/version/v1beta`
|
||||
|
||||
### Read-Only
|
||||
|
||||
- `consumed_disk` (String) How many bytes of disk space is consumed.
|
||||
- `consumed_object_storage` (String) How many bytes of Object Storage is consumed.
|
||||
- `created` (String) Instance creation timestamp in RFC3339 format.
|
||||
- `id` (String) Terraform's internal resource ID, structured as "`project_id`,`instance_id`".
|
||||
- `instance_id` (String) ID linked to the git instance.
|
||||
- `url` (String) Url linked to the git instance.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,13 @@
|
|||
resource "stackit_git" "git" {
|
||||
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
name = "git-example-instance"
|
||||
}
|
||||
|
||||
resource "stackit_git" "git" {
|
||||
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
name = "git-example-instance"
|
||||
acl = [
|
||||
"0.0.0.0/0"
|
||||
]
|
||||
flavor = "git-100"
|
||||
}
|
||||
|
|
@ -19,46 +19,74 @@ import (
|
|||
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/testutil"
|
||||
)
|
||||
|
||||
//go:embed testdata/resource.tf
|
||||
var resourceConfig string
|
||||
//go:embed testdata/resource-min.tf
|
||||
var resourceMin string
|
||||
|
||||
var name = fmt.Sprintf("git-%s-instance", acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum))
|
||||
var nameUpdated = fmt.Sprintf("git-%s-instance", acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum))
|
||||
//go:embed testdata/resource-max.tf
|
||||
var resourceMax string
|
||||
|
||||
var testConfigVars = config.Variables{
|
||||
var nameMin = fmt.Sprintf("git-min-%s-instance", acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum))
|
||||
var nameMinUpdated = fmt.Sprintf("git-min-%s-instance", acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum))
|
||||
var nameMax = fmt.Sprintf("git-max-%s-instance", acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum))
|
||||
var nameMaxUpdated = fmt.Sprintf("git-max-%s-instance", acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum))
|
||||
var aclUpdated = "192.168.1.0/32"
|
||||
|
||||
var testConfigVarsMin = config.Variables{
|
||||
"project_id": config.StringVariable(testutil.ProjectId),
|
||||
"name": config.StringVariable(name),
|
||||
"name": config.StringVariable(nameMin),
|
||||
}
|
||||
|
||||
func testConfigVarsUpdated() config.Variables {
|
||||
tempConfig := make(config.Variables, len(testConfigVars))
|
||||
maps.Copy(tempConfig, testConfigVars)
|
||||
var testConfigVarsMax = config.Variables{
|
||||
"project_id": config.StringVariable(testutil.ProjectId),
|
||||
"name": config.StringVariable(nameMax),
|
||||
"acl": config.StringVariable("192.168.0.0/16"),
|
||||
"flavor": config.StringVariable("git-100"),
|
||||
}
|
||||
|
||||
func testConfigVarsMinUpdated() config.Variables {
|
||||
tempConfig := make(config.Variables, len(testConfigVarsMin))
|
||||
maps.Copy(tempConfig, testConfigVarsMin)
|
||||
// update git instance to a new name
|
||||
// should trigger creating a new instance
|
||||
tempConfig["name"] = config.StringVariable(nameUpdated)
|
||||
tempConfig["name"] = config.StringVariable(nameMinUpdated)
|
||||
return tempConfig
|
||||
}
|
||||
|
||||
func TestGitInstance(t *testing.T) {
|
||||
func testConfigVarsMaxUpdated() config.Variables {
|
||||
tempConfig := make(config.Variables, len(testConfigVarsMax))
|
||||
maps.Copy(tempConfig, testConfigVarsMax)
|
||||
// update git instance to a new name
|
||||
// should trigger creating a new instance
|
||||
tempConfig["name"] = config.StringVariable(nameMaxUpdated)
|
||||
tempConfig["acl"] = config.StringVariable(aclUpdated)
|
||||
|
||||
return tempConfig
|
||||
}
|
||||
|
||||
func TestAccGitMin(t *testing.T) {
|
||||
resource.Test(t, resource.TestCase{
|
||||
ProtoV6ProviderFactories: testutil.TestAccProtoV6ProviderFactories,
|
||||
CheckDestroy: testAccCheckGitInstanceDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
// Creation
|
||||
{
|
||||
ConfigVariables: testConfigVars,
|
||||
Config: testutil.GitProviderConfig() + resourceConfig,
|
||||
ConfigVariables: testConfigVarsMin,
|
||||
Config: testutil.GitProviderConfig() + resourceMin,
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
resource.TestCheckResourceAttr("stackit_git.git", "project_id", testutil.ConvertConfigVariable(testConfigVars["project_id"])),
|
||||
resource.TestCheckResourceAttr("stackit_git.git", "name", testutil.ConvertConfigVariable(testConfigVars["name"])),
|
||||
resource.TestCheckResourceAttr("stackit_git.git", "project_id", testutil.ConvertConfigVariable(testConfigVarsMin["project_id"])),
|
||||
resource.TestCheckResourceAttr("stackit_git.git", "name", testutil.ConvertConfigVariable(testConfigVarsMin["name"])),
|
||||
resource.TestCheckResourceAttrSet("stackit_git.git", "url"),
|
||||
resource.TestCheckResourceAttrSet("stackit_git.git", "version"),
|
||||
resource.TestCheckResourceAttrSet("stackit_git.git", "instance_id"),
|
||||
resource.TestCheckResourceAttrSet("stackit_git.git", "created"),
|
||||
resource.TestCheckResourceAttrSet("stackit_git.git", "consumed_object_storage"),
|
||||
resource.TestCheckResourceAttrSet("stackit_git.git", "consumed_disk"),
|
||||
resource.TestCheckResourceAttrSet("stackit_git.git", "flavor"),
|
||||
),
|
||||
},
|
||||
// Data source
|
||||
{
|
||||
ConfigVariables: testConfigVars,
|
||||
ConfigVariables: testConfigVarsMin,
|
||||
Config: fmt.Sprintf(`
|
||||
%s
|
||||
|
||||
|
|
@ -66,11 +94,11 @@ func TestGitInstance(t *testing.T) {
|
|||
project_id = stackit_git.git.project_id
|
||||
instance_id = stackit_git.git.instance_id
|
||||
}
|
||||
`, testutil.GitProviderConfig()+resourceConfig,
|
||||
`, testutil.GitProviderConfig()+resourceMin,
|
||||
),
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
// Instance
|
||||
resource.TestCheckResourceAttr("data.stackit_git.git", "project_id", testutil.ConvertConfigVariable(testConfigVars["project_id"])),
|
||||
resource.TestCheckResourceAttr("data.stackit_git.git", "project_id", testutil.ConvertConfigVariable(testConfigVarsMin["project_id"])),
|
||||
resource.TestCheckResourceAttrPair(
|
||||
"stackit_git.git", "project_id",
|
||||
"data.stackit_git.git", "project_id",
|
||||
|
|
@ -91,11 +119,27 @@ func TestGitInstance(t *testing.T) {
|
|||
"stackit_git.git", "version",
|
||||
"data.stackit_git.git", "version",
|
||||
),
|
||||
resource.TestCheckResourceAttrPair(
|
||||
"stackit_git.git", "created",
|
||||
"data.stackit_git.git", "created",
|
||||
),
|
||||
resource.TestCheckResourceAttrPair(
|
||||
"stackit_git.git", "consumed_object_storage",
|
||||
"data.stackit_git.git", "consumed_object_storage",
|
||||
),
|
||||
resource.TestCheckResourceAttrPair(
|
||||
"stackit_git.git", "consumed_disk",
|
||||
"data.stackit_git.git", "consumed_disk",
|
||||
),
|
||||
resource.TestCheckResourceAttrPair(
|
||||
"stackit_git.git", "flavor",
|
||||
"data.stackit_git.git", "flavor",
|
||||
),
|
||||
),
|
||||
},
|
||||
// Import
|
||||
{
|
||||
ConfigVariables: testConfigVars,
|
||||
ConfigVariables: testConfigVarsMin,
|
||||
ResourceName: "stackit_git.git",
|
||||
ImportStateIdFunc: func(s *terraform.State) (string, error) {
|
||||
r, ok := s.RootModule().Resources["stackit_git.git"]
|
||||
|
|
@ -113,14 +157,137 @@ func TestGitInstance(t *testing.T) {
|
|||
},
|
||||
// Update
|
||||
{
|
||||
ConfigVariables: testConfigVarsUpdated(),
|
||||
Config: testutil.GitProviderConfig() + resourceConfig,
|
||||
ConfigVariables: testConfigVarsMinUpdated(),
|
||||
Config: testutil.GitProviderConfig() + resourceMin,
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
resource.TestCheckResourceAttr("stackit_git.git", "project_id", testutil.ConvertConfigVariable(testConfigVars["project_id"])),
|
||||
resource.TestCheckResourceAttr("stackit_git.git", "name", testutil.ConvertConfigVariable(testConfigVarsUpdated()["name"])),
|
||||
resource.TestCheckResourceAttr("stackit_git.git", "project_id", testutil.ConvertConfigVariable(testConfigVarsMinUpdated()["project_id"])),
|
||||
resource.TestCheckResourceAttr("stackit_git.git", "name", testutil.ConvertConfigVariable(testConfigVarsMinUpdated()["name"])),
|
||||
resource.TestCheckResourceAttrSet("stackit_git.git", "url"),
|
||||
resource.TestCheckResourceAttrSet("stackit_git.git", "version"),
|
||||
resource.TestCheckResourceAttrSet("stackit_git.git", "instance_id"),
|
||||
resource.TestCheckResourceAttrSet("stackit_git.git", "created"),
|
||||
resource.TestCheckResourceAttrSet("stackit_git.git", "consumed_object_storage"),
|
||||
resource.TestCheckResourceAttrSet("stackit_git.git", "consumed_disk"),
|
||||
resource.TestCheckResourceAttrSet("stackit_git.git", "flavor"),
|
||||
),
|
||||
},
|
||||
// Deletion is done by the framework implicitly
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccGitMax(t *testing.T) {
|
||||
resource.Test(t, resource.TestCase{
|
||||
ProtoV6ProviderFactories: testutil.TestAccProtoV6ProviderFactories,
|
||||
CheckDestroy: testAccCheckGitInstanceDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
// Creation
|
||||
{
|
||||
ConfigVariables: testConfigVarsMax,
|
||||
Config: testutil.GitProviderConfig() + resourceMax,
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
resource.TestCheckResourceAttr("stackit_git.git", "project_id", testutil.ConvertConfigVariable(testConfigVarsMax["project_id"])),
|
||||
resource.TestCheckResourceAttr("stackit_git.git", "name", testutil.ConvertConfigVariable(testConfigVarsMax["name"])),
|
||||
resource.TestCheckResourceAttr("stackit_git.git", "flavor", testutil.ConvertConfigVariable(testConfigVarsMax["flavor"])),
|
||||
resource.TestCheckResourceAttr("stackit_git.git", "acl.0", testutil.ConvertConfigVariable(testConfigVarsMax["acl"])),
|
||||
resource.TestCheckResourceAttrSet("stackit_git.git", "url"),
|
||||
resource.TestCheckResourceAttrSet("stackit_git.git", "version"),
|
||||
resource.TestCheckResourceAttrSet("stackit_git.git", "instance_id"),
|
||||
resource.TestCheckResourceAttrSet("stackit_git.git", "created"),
|
||||
resource.TestCheckResourceAttrSet("stackit_git.git", "consumed_object_storage"),
|
||||
resource.TestCheckResourceAttrSet("stackit_git.git", "consumed_disk"),
|
||||
),
|
||||
},
|
||||
// Data source
|
||||
{
|
||||
ConfigVariables: testConfigVarsMax,
|
||||
Config: fmt.Sprintf(`
|
||||
%s
|
||||
|
||||
data "stackit_git" "git" {
|
||||
project_id = stackit_git.git.project_id
|
||||
instance_id = stackit_git.git.instance_id
|
||||
}
|
||||
`, testutil.GitProviderConfig()+resourceMax,
|
||||
),
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
// Instance
|
||||
resource.TestCheckResourceAttr("data.stackit_git.git", "project_id", testutil.ConvertConfigVariable(testConfigVarsMax["project_id"])),
|
||||
resource.TestCheckResourceAttrPair(
|
||||
"stackit_git.git", "project_id",
|
||||
"data.stackit_git.git", "project_id",
|
||||
),
|
||||
resource.TestCheckResourceAttrPair(
|
||||
"stackit_git.git", "instance_id",
|
||||
"data.stackit_git.git", "instance_id",
|
||||
),
|
||||
resource.TestCheckResourceAttrPair(
|
||||
"stackit_git.git", "name",
|
||||
"data.stackit_git.git", "name",
|
||||
),
|
||||
resource.TestCheckResourceAttrPair(
|
||||
"stackit_git.git", "url",
|
||||
"data.stackit_git.git", "url",
|
||||
),
|
||||
resource.TestCheckResourceAttrPair(
|
||||
"stackit_git.git", "version",
|
||||
"data.stackit_git.git", "version",
|
||||
),
|
||||
resource.TestCheckResourceAttrPair(
|
||||
"stackit_git.git", "created",
|
||||
"data.stackit_git.git", "created",
|
||||
),
|
||||
resource.TestCheckResourceAttrPair(
|
||||
"stackit_git.git", "consumed_object_storage",
|
||||
"data.stackit_git.git", "consumed_object_storage",
|
||||
),
|
||||
resource.TestCheckResourceAttrPair(
|
||||
"stackit_git.git", "consumed_disk",
|
||||
"data.stackit_git.git", "consumed_disk",
|
||||
),
|
||||
resource.TestCheckResourceAttrPair(
|
||||
"stackit_git.git", "flavor",
|
||||
"data.stackit_git.git", "flavor",
|
||||
),
|
||||
resource.TestCheckResourceAttrPair(
|
||||
"stackit_git.git", "acl",
|
||||
"data.stackit_git.git", "acl",
|
||||
),
|
||||
),
|
||||
},
|
||||
// Import
|
||||
{
|
||||
ConfigVariables: testConfigVarsMax,
|
||||
ResourceName: "stackit_git.git",
|
||||
ImportStateIdFunc: func(s *terraform.State) (string, error) {
|
||||
r, ok := s.RootModule().Resources["stackit_git.git"]
|
||||
if !ok {
|
||||
return "", fmt.Errorf("couldn't find resource stackit_git.git")
|
||||
}
|
||||
instanceId, ok := r.Primary.Attributes["instance_id"]
|
||||
if !ok {
|
||||
return "", fmt.Errorf("couldn't find attribute instance_id")
|
||||
}
|
||||
return fmt.Sprintf("%s,%s", testutil.ProjectId, instanceId), nil
|
||||
},
|
||||
ImportState: true,
|
||||
ImportStateVerify: true,
|
||||
},
|
||||
// Update
|
||||
{
|
||||
ConfigVariables: testConfigVarsMaxUpdated(),
|
||||
Config: testutil.GitProviderConfig() + resourceMax,
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
resource.TestCheckResourceAttr("stackit_git.git", "project_id", testutil.ConvertConfigVariable(testConfigVarsMaxUpdated()["project_id"])),
|
||||
resource.TestCheckResourceAttr("stackit_git.git", "name", testutil.ConvertConfigVariable(testConfigVarsMaxUpdated()["name"])),
|
||||
resource.TestCheckResourceAttr("stackit_git.git", "flavor", testutil.ConvertConfigVariable(testConfigVarsMaxUpdated()["flavor"])),
|
||||
resource.TestCheckResourceAttr("stackit_git.git", "acl.0", testutil.ConvertConfigVariable(testConfigVarsMaxUpdated()["acl"])),
|
||||
resource.TestCheckResourceAttrSet("stackit_git.git", "url"),
|
||||
resource.TestCheckResourceAttrSet("stackit_git.git", "version"),
|
||||
resource.TestCheckResourceAttrSet("stackit_git.git", "instance_id"),
|
||||
resource.TestCheckResourceAttrSet("stackit_git.git", "created"),
|
||||
resource.TestCheckResourceAttrSet("stackit_git.git", "consumed_object_storage"),
|
||||
resource.TestCheckResourceAttrSet("stackit_git.git", "consumed_disk"),
|
||||
),
|
||||
},
|
||||
// Deletion is done by the framework implicitly
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import (
|
|||
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
"github.com/hashicorp/terraform-plugin-log/tflog"
|
||||
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
|
||||
"github.com/stackitcloud/stackit-sdk-go/services/git"
|
||||
|
|
@ -86,6 +87,27 @@ func (g *gitDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, re
|
|||
validate.NoSeparator(),
|
||||
},
|
||||
},
|
||||
"acl": schema.ListAttribute{
|
||||
Description: descriptions["acl"],
|
||||
Computed: true,
|
||||
ElementType: types.StringType,
|
||||
},
|
||||
"consumed_disk": schema.StringAttribute{
|
||||
Description: descriptions["consumed_disk"],
|
||||
Computed: true,
|
||||
},
|
||||
"consumed_object_storage": schema.StringAttribute{
|
||||
Description: descriptions["consumed_object_storage"],
|
||||
Computed: true,
|
||||
},
|
||||
"created": schema.StringAttribute{
|
||||
Description: descriptions["created"],
|
||||
Computed: true,
|
||||
},
|
||||
"flavor": schema.StringAttribute{
|
||||
Description: descriptions["flavor"],
|
||||
Computed: true,
|
||||
},
|
||||
"name": schema.StringAttribute{
|
||||
Description: descriptions["name"],
|
||||
Computed: true,
|
||||
|
|
@ -127,7 +149,7 @@ func (g *gitDataSource) Read(ctx context.Context, req datasource.ReadRequest, re
|
|||
return
|
||||
}
|
||||
|
||||
err = mapFields(gitInstanceResp, &model)
|
||||
err = mapFields(ctx, gitInstanceResp, &model)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading git instance", fmt.Sprintf("Processing API response: %v", err))
|
||||
return
|
||||
|
|
|
|||
|
|
@ -7,15 +7,12 @@ import (
|
|||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils"
|
||||
|
||||
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion"
|
||||
gitUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/git/utils"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
|
||||
|
|
@ -24,8 +21,11 @@ import (
|
|||
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
|
||||
"github.com/stackitcloud/stackit-sdk-go/services/git"
|
||||
"github.com/stackitcloud/stackit-sdk-go/services/git/wait"
|
||||
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion"
|
||||
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core"
|
||||
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/features"
|
||||
gitUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/git/utils"
|
||||
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils"
|
||||
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/validate"
|
||||
)
|
||||
|
||||
|
|
@ -38,12 +38,17 @@ var (
|
|||
|
||||
// Model represents the schema for the git resource.
|
||||
type Model struct {
|
||||
Id types.String `tfsdk:"id"` // Required by Terraform
|
||||
ProjectId types.String `tfsdk:"project_id"` // ProjectId associated with the git instance
|
||||
InstanceId types.String `tfsdk:"instance_id"` // InstanceId associated with the git instance
|
||||
Name types.String `tfsdk:"name"` // Name linked to the git instance
|
||||
Url types.String `tfsdk:"url"` // Url linked to the git instance
|
||||
Version types.String `tfsdk:"version"` // Version linked to the git instance
|
||||
Id types.String `tfsdk:"id"` // Required by Terraform
|
||||
ACL types.List `tfsdk:"acl"`
|
||||
ConsumedDisk types.String `tfsdk:"consumed_disk"`
|
||||
ConsumedObjectStorage types.String `tfsdk:"consumed_object_storage"`
|
||||
Created types.String `tfsdk:"created"`
|
||||
Flavor types.String `tfsdk:"flavor"`
|
||||
InstanceId types.String `tfsdk:"instance_id"`
|
||||
Name types.String `tfsdk:"name"`
|
||||
ProjectId types.String `tfsdk:"project_id"`
|
||||
Url types.String `tfsdk:"url"`
|
||||
Version types.String `tfsdk:"version"`
|
||||
}
|
||||
|
||||
// NewGitResource is a helper function to create a new git resource instance.
|
||||
|
|
@ -58,12 +63,17 @@ type gitResource struct {
|
|||
|
||||
// descriptions for the attributes in the Schema
|
||||
var descriptions = map[string]string{
|
||||
"id": "Terraform's internal resource ID, structured as \"`project_id`,`instance_id`\".",
|
||||
"project_id": "STACKIT project ID to which the git instance is associated.",
|
||||
"instance_id": "ID linked to the git instance.",
|
||||
"name": "Unique name linked to the git instance.",
|
||||
"url": "Url linked to the git instance.",
|
||||
"version": "Version linked to the git instance.",
|
||||
"id": "Terraform's internal resource ID, structured as \"`project_id`,`instance_id`\".",
|
||||
"acl": "Restricted ACL for instance access.",
|
||||
"consumed_disk": "How many bytes of disk space is consumed.",
|
||||
"consumed_object_storage": "How many bytes of Object Storage is consumed.",
|
||||
"created": "Instance creation timestamp in RFC3339 format.",
|
||||
"flavor": "Instance flavor. If not provided, defaults to git-100. For a list of available flavors, refer to our API documentation: `https://docs.api.stackit.cloud/documentation/git/version/v1beta`",
|
||||
"instance_id": "ID linked to the git instance.",
|
||||
"name": "Unique name linked to the git instance.",
|
||||
"project_id": "STACKIT project ID to which the git instance is associated.",
|
||||
"url": "Url linked to the git instance.",
|
||||
"version": "Version linked to the git instance.",
|
||||
}
|
||||
|
||||
// Configure sets up the API client for the git instance resource.
|
||||
|
|
@ -94,8 +104,12 @@ func (g *gitResource) Metadata(_ context.Context, req resource.MetadataRequest,
|
|||
// Schema defines the schema for the resource.
|
||||
func (g *gitResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
|
||||
resp.Schema = schema.Schema{
|
||||
MarkdownDescription: features.AddBetaDescription("Git Instance resource schema.", core.Resource),
|
||||
Description: "Git Instance resource schema.",
|
||||
MarkdownDescription: fmt.Sprintf(
|
||||
"%s %s",
|
||||
features.AddBetaDescription("Git Instance resource schema.", core.Resource),
|
||||
"This resource currently does not support updates. Changing the ACLs, flavor, or name will trigger resource recreation. Update functionality will be added soon. In the meantime, please proceed with caution. To update these attributes, please open a support ticket.",
|
||||
),
|
||||
Description: "Git Instance resource schema.",
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": schema.StringAttribute{
|
||||
Description: descriptions["id"],
|
||||
|
|
@ -120,6 +134,35 @@ func (g *gitResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *
|
|||
validate.NoSeparator(),
|
||||
},
|
||||
},
|
||||
"acl": schema.ListAttribute{
|
||||
Description: descriptions["acl"],
|
||||
PlanModifiers: []planmodifier.List{
|
||||
listplanmodifier.RequiresReplace(),
|
||||
},
|
||||
ElementType: types.StringType,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
"consumed_disk": schema.StringAttribute{
|
||||
Description: descriptions["consumed_disk"],
|
||||
Computed: true,
|
||||
},
|
||||
"consumed_object_storage": schema.StringAttribute{
|
||||
Description: descriptions["consumed_object_storage"],
|
||||
Computed: true,
|
||||
},
|
||||
"created": schema.StringAttribute{
|
||||
Description: descriptions["created"],
|
||||
Computed: true,
|
||||
},
|
||||
"flavor": schema.StringAttribute{
|
||||
Description: descriptions["flavor"],
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.RequiresReplace(),
|
||||
},
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
"name": schema.StringAttribute{
|
||||
Description: descriptions["name"],
|
||||
Required: true,
|
||||
|
|
@ -158,9 +201,15 @@ func (g *gitResource) Create(ctx context.Context, req resource.CreateRequest, re
|
|||
ctx = tflog.SetField(ctx, "project_id", projectId)
|
||||
ctx = tflog.SetField(ctx, "instance_name", instanceName)
|
||||
|
||||
payload, diags := toCreatePayload(ctx, &model)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
// Create the new git instance via the API client.
|
||||
gitInstanceResp, err := g.client.CreateInstance(ctx, projectId).
|
||||
CreateInstancePayload(git.CreateInstancePayload{Name: &instanceName}).
|
||||
CreateInstancePayload(payload).
|
||||
Execute()
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating git instance", fmt.Sprintf("Calling API: %v", err))
|
||||
|
|
@ -174,7 +223,7 @@ func (g *gitResource) Create(ctx context.Context, req resource.CreateRequest, re
|
|||
return
|
||||
}
|
||||
|
||||
err = mapFields(gitInstanceResp, &model)
|
||||
err = mapFields(ctx, gitInstanceResp, &model)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating git instance", fmt.Sprintf("Mapping fields: %v", err))
|
||||
return
|
||||
|
|
@ -216,7 +265,7 @@ func (g *gitResource) Read(ctx context.Context, req resource.ReadRequest, resp *
|
|||
return
|
||||
}
|
||||
|
||||
err = mapFields(gitInstanceResp, &model)
|
||||
err = mapFields(ctx, gitInstanceResp, &model)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading git instance", fmt.Sprintf("Processing API response: %v", err))
|
||||
return
|
||||
|
|
@ -295,7 +344,7 @@ func (g *gitResource) ImportState(ctx context.Context, req resource.ImportStateR
|
|||
}
|
||||
|
||||
// mapFields maps a Git response to the model.
|
||||
func mapFields(resp *git.Instance, model *Model) error {
|
||||
func mapFields(ctx context.Context, resp *git.Instance, model *Model) error {
|
||||
if resp == nil {
|
||||
return fmt.Errorf("response input is nil")
|
||||
}
|
||||
|
|
@ -307,12 +356,58 @@ func mapFields(resp *git.Instance, model *Model) error {
|
|||
return fmt.Errorf("git instance id not present")
|
||||
}
|
||||
|
||||
aclList := types.ListNull(types.StringType)
|
||||
var diags diag.Diagnostics
|
||||
if resp.Acl != nil && len(*resp.Acl) > 0 {
|
||||
aclList, diags = types.ListValueFrom(ctx, types.StringType, resp.Acl)
|
||||
if diags.HasError() {
|
||||
return fmt.Errorf("mapping ACL: %w", core.DiagsToError(diags))
|
||||
}
|
||||
}
|
||||
|
||||
model.Created = types.StringNull()
|
||||
if resp.Created != nil && resp.Created.String() != "" {
|
||||
model.Created = types.StringValue(resp.Created.String())
|
||||
}
|
||||
|
||||
// Build the ID by combining the project ID and instance id and assign the model's fields.
|
||||
model.Id = utils.BuildInternalTerraformId(model.ProjectId.ValueString(), *resp.Id)
|
||||
model.Url = types.StringPointerValue(resp.Url)
|
||||
model.Name = types.StringPointerValue(resp.Name)
|
||||
model.ACL = aclList
|
||||
model.ConsumedDisk = types.StringPointerValue(resp.ConsumedDisk)
|
||||
model.ConsumedObjectStorage = types.StringPointerValue(resp.ConsumedObjectStorage)
|
||||
model.Flavor = types.StringPointerValue(resp.Flavor)
|
||||
model.InstanceId = types.StringPointerValue(resp.Id)
|
||||
model.Name = types.StringPointerValue(resp.Name)
|
||||
model.Url = types.StringPointerValue(resp.Url)
|
||||
model.Version = types.StringPointerValue(resp.Version)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// toCreatePayload creates the payload to create a git instance
|
||||
func toCreatePayload(ctx context.Context, model *Model) (git.CreateInstancePayload, diag.Diagnostics) {
|
||||
diags := diag.Diagnostics{}
|
||||
|
||||
if model == nil {
|
||||
return git.CreateInstancePayload{}, diags
|
||||
}
|
||||
|
||||
payload := git.CreateInstancePayload{
|
||||
Name: model.Name.ValueStringPointer(),
|
||||
}
|
||||
|
||||
if !(model.ACL.IsNull() || model.ACL.IsUnknown()) {
|
||||
var acl []string
|
||||
aclDiags := model.ACL.ElementsAs(ctx, &acl, false)
|
||||
diags.Append(aclDiags...)
|
||||
if !aclDiags.HasError() {
|
||||
payload.Acl = &acl
|
||||
}
|
||||
}
|
||||
|
||||
if !(model.Flavor.IsNull() || model.Flavor.IsUnknown()) {
|
||||
payload.Flavor = model.Flavor.ValueStringPointer()
|
||||
}
|
||||
|
||||
return payload, diags
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,79 +1,225 @@
|
|||
package instance
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/uuid"
|
||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
"github.com/stackitcloud/stackit-sdk-go/core/utils"
|
||||
"github.com/stackitcloud/stackit-sdk-go/services/git"
|
||||
)
|
||||
|
||||
var (
|
||||
testInstanceId = uuid.New().String()
|
||||
testProjectId = uuid.New().String()
|
||||
)
|
||||
|
||||
func TestMapFields(t *testing.T) {
|
||||
createdTime, err := time.Parse("2006-01-02 15:04:05 -0700 MST", "2025-01-01 00:00:00 +0000 UTC")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to parse test time: %v", err)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
description string
|
||||
input *git.Instance
|
||||
expected Model
|
||||
expected *Model
|
||||
isValid bool
|
||||
}{
|
||||
{
|
||||
"default_values",
|
||||
&git.Instance{
|
||||
Created: nil,
|
||||
Id: utils.Ptr("id"),
|
||||
Name: utils.Ptr("foo"),
|
||||
Url: utils.Ptr("https://foo.com"),
|
||||
Version: utils.Ptr("v0.0.1"),
|
||||
description: "minimal_input_name_only",
|
||||
input: &git.Instance{
|
||||
Id: utils.Ptr(testInstanceId),
|
||||
Name: utils.Ptr("git-min-instance"),
|
||||
},
|
||||
Model{
|
||||
Id: types.StringValue("pid,id"),
|
||||
ProjectId: types.StringValue("pid"),
|
||||
InstanceId: types.StringValue("id"),
|
||||
Name: types.StringValue("foo"),
|
||||
Url: types.StringValue("https://foo.com"),
|
||||
Version: types.StringValue("v0.0.1"),
|
||||
expected: &Model{
|
||||
Id: types.StringValue(fmt.Sprintf("%s,%s", testProjectId, testInstanceId)),
|
||||
ProjectId: types.StringValue(testProjectId),
|
||||
InstanceId: types.StringValue(testInstanceId),
|
||||
Name: types.StringValue("git-min-instance"),
|
||||
ACL: types.ListNull(types.StringType),
|
||||
Flavor: types.StringNull(),
|
||||
Url: types.StringNull(),
|
||||
Version: types.StringNull(),
|
||||
Created: types.StringNull(),
|
||||
ConsumedDisk: types.StringNull(),
|
||||
ConsumedObjectStorage: types.StringNull(),
|
||||
},
|
||||
true,
|
||||
isValid: true,
|
||||
},
|
||||
{
|
||||
"nil_response",
|
||||
nil,
|
||||
Model{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"nil_response_2",
|
||||
&git.Instance{},
|
||||
Model{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"no_id",
|
||||
&git.Instance{
|
||||
Name: utils.Ptr("foo"),
|
||||
description: "full_input_with_acl_and_flavor",
|
||||
input: &git.Instance{
|
||||
Acl: &[]string{"192.168.0.0/24"},
|
||||
ConsumedDisk: utils.Ptr("1.00 GB"),
|
||||
ConsumedObjectStorage: utils.Ptr("2.00 GB"),
|
||||
Created: &createdTime,
|
||||
Flavor: utils.Ptr("git-100"),
|
||||
Id: utils.Ptr(testInstanceId),
|
||||
Name: utils.Ptr("git-full-instance"),
|
||||
Url: utils.Ptr("https://git-full-instance.git.onstackit.cloud"),
|
||||
Version: utils.Ptr("v1.9.1"),
|
||||
},
|
||||
Model{},
|
||||
false,
|
||||
expected: &Model{
|
||||
Id: types.StringValue(fmt.Sprintf("%s,%s", testProjectId, testInstanceId)),
|
||||
ProjectId: types.StringValue(testProjectId),
|
||||
InstanceId: types.StringValue(testInstanceId),
|
||||
Name: types.StringValue("git-full-instance"),
|
||||
ACL: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("192.168.0.0/24")}),
|
||||
Flavor: types.StringValue("git-100"),
|
||||
Url: types.StringValue("https://git-full-instance.git.onstackit.cloud"),
|
||||
Version: types.StringValue("v1.9.1"),
|
||||
Created: types.StringValue("2025-01-01 00:00:00 +0000 UTC"),
|
||||
ConsumedDisk: types.StringValue("1.00 GB"),
|
||||
ConsumedObjectStorage: types.StringValue("2.00 GB"),
|
||||
},
|
||||
isValid: true,
|
||||
},
|
||||
{
|
||||
description: "empty_acls",
|
||||
input: &git.Instance{
|
||||
Id: utils.Ptr(testInstanceId),
|
||||
Name: utils.Ptr("git-empty-acl"),
|
||||
Acl: &[]string{},
|
||||
},
|
||||
expected: &Model{
|
||||
Id: types.StringValue(fmt.Sprintf("%s,%s", testProjectId, testInstanceId)),
|
||||
ProjectId: types.StringValue(testProjectId),
|
||||
InstanceId: types.StringValue(testInstanceId),
|
||||
Name: types.StringValue("git-empty-acl"),
|
||||
ACL: types.ListNull(types.StringType),
|
||||
Flavor: types.StringNull(),
|
||||
Url: types.StringNull(),
|
||||
Version: types.StringNull(),
|
||||
Created: types.StringNull(),
|
||||
ConsumedDisk: types.StringNull(),
|
||||
ConsumedObjectStorage: types.StringNull(),
|
||||
},
|
||||
isValid: true,
|
||||
},
|
||||
{
|
||||
description: "nil_instance",
|
||||
input: nil,
|
||||
expected: nil,
|
||||
isValid: false,
|
||||
},
|
||||
{
|
||||
description: "empty_instance",
|
||||
input: &git.Instance{},
|
||||
expected: nil,
|
||||
isValid: false,
|
||||
},
|
||||
{
|
||||
description: "missing_id",
|
||||
input: &git.Instance{
|
||||
Name: utils.Ptr("git-missing-id"),
|
||||
},
|
||||
expected: nil,
|
||||
isValid: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.description, func(t *testing.T) {
|
||||
state := &Model{
|
||||
ProjectId: tt.expected.ProjectId,
|
||||
}
|
||||
err := mapFields(tt.input, state)
|
||||
if !tt.isValid && err == nil {
|
||||
t.Fatalf("Should have failed")
|
||||
state := &Model{}
|
||||
if tt.expected != nil {
|
||||
state.ProjectId = tt.expected.ProjectId
|
||||
}
|
||||
err := mapFields(context.Background(), tt.input, state)
|
||||
|
||||
if tt.isValid && err != nil {
|
||||
t.Fatalf("Should not have failed: %v", err)
|
||||
t.Fatalf("expected success, got error: %v", err)
|
||||
}
|
||||
if !tt.isValid && err == nil {
|
||||
t.Fatalf("expected error, got nil")
|
||||
}
|
||||
if tt.isValid {
|
||||
diff := cmp.Diff(state, &tt.expected)
|
||||
if diff != "" {
|
||||
t.Fatalf("Data does not match: %s", diff)
|
||||
if diff := cmp.Diff(tt.expected, state); diff != "" {
|
||||
t.Errorf("unexpected diff (-want +got):\n%s", diff)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestToCreatePayload(t *testing.T) {
|
||||
tests := []struct {
|
||||
description string
|
||||
input *Model
|
||||
expected git.CreateInstancePayload
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
description: "default values",
|
||||
input: &Model{
|
||||
Name: types.StringValue("example-instance"),
|
||||
Flavor: types.StringNull(),
|
||||
ACL: types.ListNull(types.StringType),
|
||||
},
|
||||
expected: git.CreateInstancePayload{
|
||||
Name: utils.Ptr("example-instance"),
|
||||
},
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
description: "simple values with ACL and Flavor",
|
||||
input: &Model{
|
||||
Name: types.StringValue("my-instance"),
|
||||
Flavor: types.StringValue("git-100"),
|
||||
ACL: types.ListValueMust(types.StringType, []attr.Value{
|
||||
types.StringValue("10.0.0.1"),
|
||||
types.StringValue("10.0.0.2"),
|
||||
}),
|
||||
},
|
||||
expected: git.CreateInstancePayload{
|
||||
Name: utils.Ptr("my-instance"),
|
||||
Flavor: utils.Ptr("git-100"),
|
||||
Acl: &[]string{"10.0.0.1", "10.0.0.2"},
|
||||
},
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
description: "empty ACL still valid",
|
||||
input: &Model{
|
||||
Name: types.StringValue("my-instance"),
|
||||
Flavor: types.StringValue("git-101"),
|
||||
ACL: types.ListValueMust(types.StringType, []attr.Value{}),
|
||||
},
|
||||
expected: git.CreateInstancePayload{
|
||||
Name: utils.Ptr("my-instance"),
|
||||
Flavor: utils.Ptr("git-101"),
|
||||
Acl: &[]string{},
|
||||
},
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
description: "nil input model",
|
||||
input: nil,
|
||||
expected: git.CreateInstancePayload{},
|
||||
expectError: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.description, func(t *testing.T) {
|
||||
output, diags := toCreatePayload(context.Background(), tt.input)
|
||||
|
||||
if tt.expectError && !diags.HasError() {
|
||||
t.Fatalf("expected diagnostics error but got none")
|
||||
}
|
||||
|
||||
if !tt.expectError && diags.HasError() {
|
||||
t.Fatalf("unexpected diagnostics error: %v", diags)
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(tt.expected, output); diff != "" {
|
||||
t.Fatalf("unexpected payload (-want +got):\n%s", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
14
stackit/internal/services/git/testdata/resource-max.tf
vendored
Normal file
14
stackit/internal/services/git/testdata/resource-max.tf
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
variable "project_id" {}
|
||||
variable "name" {}
|
||||
variable "acl" {}
|
||||
variable "flavor" {}
|
||||
|
||||
resource "stackit_git" "git" {
|
||||
project_id = var.project_id
|
||||
name = var.name
|
||||
acl = [
|
||||
var.acl
|
||||
]
|
||||
flavor = var.flavor
|
||||
}
|
||||
|
|
@ -4,5 +4,5 @@ variable "name" {}
|
|||
|
||||
resource "stackit_git" "git" {
|
||||
project_id = var.project_id
|
||||
name = var.name
|
||||
name = var.name
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue