Onboard Argus ACL (#304)
* resource create and schema/model * consider empty value in resource creation * Address issue in mapfields that came up in testing * Unit testing the mapFields func * extend update * extend read * extend datasource.go * update example * extended acceptance tests and generated docs * update description and comments * improve messages and var names, fix update acceptance test * extend acceptance tests, improve error messages
This commit is contained in:
parent
8eb14a1136
commit
c2389be47b
7 changed files with 379 additions and 22 deletions
|
|
@ -29,6 +29,7 @@ data "stackit_argus_instance" "example" {
|
|||
|
||||
### Read-Only
|
||||
|
||||
- `acl` (Set of String) The access control list for this instance. Each entry is an IP or IP range that is permitted to access, in CIDR notation.
|
||||
- `alerting_url` (String) Specifies Alerting URL.
|
||||
- `dashboard_url` (String) Specifies Argus instance dashboard URL.
|
||||
- `grafana_initial_admin_password` (String, Sensitive) Specifies an initial Grafana admin password.
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ resource "stackit_argus_instance" "example" {
|
|||
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
name = "example-instance"
|
||||
plan_name = "Monitoring-Medium-EU01"
|
||||
acl = ["1.1.1.1/32", "2.2.2.2/32"]
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -31,6 +32,7 @@ resource "stackit_argus_instance" "example" {
|
|||
|
||||
### Optional
|
||||
|
||||
- `acl` (Set of String) The access control list for this instance. Each entry is an IP or IP range that is permitted to access, in CIDR notation.
|
||||
- `parameters` (Map of String) Additional parameters.
|
||||
|
||||
### Read-Only
|
||||
|
|
|
|||
|
|
@ -2,4 +2,5 @@ resource "stackit_argus_instance" "example" {
|
|||
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
name = "example-instance"
|
||||
plan_name = "Monitoring-Medium-EU01"
|
||||
acl = ["1.1.1.1/32", "2.2.2.2/32"]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@ var instanceResource = map[string]string{
|
|||
"name": testutil.ResourceNameWithDateTime("argus"),
|
||||
"plan_name": "Monitoring-Basic-EU01",
|
||||
"new_plan_name": "Monitoring-Medium-EU01",
|
||||
"acl-0": "1.2.3.4/32",
|
||||
"acl-1": "111.222.111.222/32",
|
||||
"acl-1-updated": "111.222.111.125/32",
|
||||
}
|
||||
|
||||
var scrapeConfigResource = map[string]string{
|
||||
|
|
@ -39,8 +42,9 @@ var credentialResource = map[string]string{
|
|||
"project_id": testutil.ProjectId,
|
||||
}
|
||||
|
||||
func resourceConfig(instanceName, planName, target, saml2EnableUrlParameters string) string {
|
||||
return fmt.Sprintf(`
|
||||
func resourceConfig(acl *string, instanceName, planName, target, saml2EnableUrlParameters string) string {
|
||||
if acl == nil {
|
||||
return fmt.Sprintf(`
|
||||
%s
|
||||
|
||||
resource "stackit_argus_instance" "instance" {
|
||||
|
|
@ -68,10 +72,52 @@ func resourceConfig(instanceName, planName, target, saml2EnableUrlParameters str
|
|||
}
|
||||
|
||||
`,
|
||||
testutil.ArgusProviderConfig(),
|
||||
instanceResource["project_id"],
|
||||
instanceName,
|
||||
planName,
|
||||
scrapeConfigResource["name"],
|
||||
scrapeConfigResource["metrics_path"],
|
||||
target,
|
||||
scrapeConfigResource["scrape_interval"],
|
||||
scrapeConfigResource["sample_limit"],
|
||||
saml2EnableUrlParameters,
|
||||
)
|
||||
}
|
||||
return fmt.Sprintf(`
|
||||
%s
|
||||
|
||||
resource "stackit_argus_instance" "instance" {
|
||||
project_id = "%s"
|
||||
name = "%s"
|
||||
plan_name = "%s"
|
||||
acl = %s
|
||||
}
|
||||
|
||||
resource "stackit_argus_scrapeconfig" "scrapeconfig" {
|
||||
project_id = stackit_argus_instance.instance.project_id
|
||||
instance_id = stackit_argus_instance.instance.instance_id
|
||||
name = "%s"
|
||||
metrics_path = "%s"
|
||||
targets = [%s]
|
||||
scrape_interval = "%s"
|
||||
sample_limit = %s
|
||||
saml2 = {
|
||||
enable_url_parameters = %s
|
||||
}
|
||||
}
|
||||
|
||||
resource "stackit_argus_credential" "credential" {
|
||||
project_id = stackit_argus_instance.instance.project_id
|
||||
instance_id = stackit_argus_instance.instance.instance_id
|
||||
}
|
||||
|
||||
`,
|
||||
testutil.ArgusProviderConfig(),
|
||||
instanceResource["project_id"],
|
||||
instanceName,
|
||||
planName,
|
||||
*acl,
|
||||
scrapeConfigResource["name"],
|
||||
scrapeConfigResource["metrics_path"],
|
||||
target,
|
||||
|
|
@ -88,7 +134,18 @@ func TestAccResource(t *testing.T) {
|
|||
Steps: []resource.TestStep{
|
||||
// Creation
|
||||
{
|
||||
Config: resourceConfig(instanceResource["name"], instanceResource["plan_name"], scrapeConfigResource["urls"], scrapeConfigResource["saml2_enable_url_parameters"]),
|
||||
Config: resourceConfig(
|
||||
utils.Ptr(fmt.Sprintf(
|
||||
"[%q, %q, %q]",
|
||||
instanceResource["acl-0"],
|
||||
instanceResource["acl-1"],
|
||||
instanceResource["acl-1"],
|
||||
)),
|
||||
instanceResource["name"],
|
||||
instanceResource["plan_name"],
|
||||
scrapeConfigResource["urls"],
|
||||
scrapeConfigResource["saml2_enable_url_parameters"],
|
||||
),
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
// Instance data
|
||||
resource.TestCheckResourceAttr("stackit_argus_instance.instance", "project_id", instanceResource["project_id"]),
|
||||
|
|
@ -115,6 +172,11 @@ func TestAccResource(t *testing.T) {
|
|||
resource.TestCheckResourceAttrSet("stackit_argus_instance.instance", "otlp_traces_url"),
|
||||
resource.TestCheckResourceAttrSet("stackit_argus_instance.instance", "zipkin_spans_url"),
|
||||
|
||||
// ACL
|
||||
resource.TestCheckResourceAttr("stackit_argus_instance.instance", "acl.#", "2"),
|
||||
resource.TestCheckResourceAttr("stackit_argus_instance.instance", "acl.0", instanceResource["acl-0"]),
|
||||
resource.TestCheckResourceAttr("stackit_argus_instance.instance", "acl.1", instanceResource["acl-1"]),
|
||||
|
||||
// scrape config data
|
||||
resource.TestCheckResourceAttrPair(
|
||||
"stackit_argus_instance.instance", "project_id",
|
||||
|
|
@ -141,7 +203,73 @@ func TestAccResource(t *testing.T) {
|
|||
resource.TestCheckResourceAttrSet("stackit_argus_credential.credential", "username"),
|
||||
resource.TestCheckResourceAttrSet("stackit_argus_credential.credential", "password"),
|
||||
),
|
||||
}, {
|
||||
},
|
||||
// Creation without ACL
|
||||
{
|
||||
Config: resourceConfig(
|
||||
nil,
|
||||
instanceResource["name"],
|
||||
instanceResource["plan_name"],
|
||||
scrapeConfigResource["urls"],
|
||||
scrapeConfigResource["saml2_enable_url_parameters"],
|
||||
),
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
// Instance data
|
||||
resource.TestCheckResourceAttr("stackit_argus_instance.instance", "project_id", instanceResource["project_id"]),
|
||||
resource.TestCheckResourceAttrSet("stackit_argus_instance.instance", "instance_id"),
|
||||
resource.TestCheckResourceAttr("stackit_argus_instance.instance", "name", instanceResource["name"]),
|
||||
resource.TestCheckResourceAttr("stackit_argus_instance.instance", "plan_name", instanceResource["plan_name"]),
|
||||
resource.TestCheckResourceAttrSet("stackit_argus_instance.instance", "dashboard_url"),
|
||||
resource.TestCheckResourceAttrSet("stackit_argus_instance.instance", "is_updatable"),
|
||||
resource.TestCheckResourceAttrSet("stackit_argus_instance.instance", "grafana_public_read_access"),
|
||||
resource.TestCheckResourceAttrSet("stackit_argus_instance.instance", "grafana_url"),
|
||||
resource.TestCheckResourceAttrSet("stackit_argus_instance.instance", "grafana_initial_admin_user"),
|
||||
resource.TestCheckResourceAttrSet("stackit_argus_instance.instance", "grafana_initial_admin_password"),
|
||||
resource.TestCheckResourceAttrSet("stackit_argus_instance.instance", "metrics_retention_days"),
|
||||
resource.TestCheckResourceAttrSet("stackit_argus_instance.instance", "metrics_retention_days_5m_downsampling"),
|
||||
resource.TestCheckResourceAttrSet("stackit_argus_instance.instance", "metrics_retention_days_1h_downsampling"),
|
||||
resource.TestCheckResourceAttrSet("stackit_argus_instance.instance", "metrics_url"),
|
||||
resource.TestCheckResourceAttrSet("stackit_argus_instance.instance", "metrics_push_url"),
|
||||
resource.TestCheckResourceAttrSet("stackit_argus_instance.instance", "targets_url"),
|
||||
resource.TestCheckResourceAttrSet("stackit_argus_instance.instance", "alerting_url"),
|
||||
resource.TestCheckResourceAttrSet("stackit_argus_instance.instance", "logs_url"),
|
||||
resource.TestCheckResourceAttrSet("stackit_argus_instance.instance", "logs_push_url"),
|
||||
resource.TestCheckResourceAttrSet("stackit_argus_instance.instance", "jaeger_traces_url"),
|
||||
resource.TestCheckResourceAttrSet("stackit_argus_instance.instance", "jaeger_ui_url"),
|
||||
resource.TestCheckResourceAttrSet("stackit_argus_instance.instance", "otlp_traces_url"),
|
||||
resource.TestCheckResourceAttrSet("stackit_argus_instance.instance", "zipkin_spans_url"),
|
||||
|
||||
// ACL
|
||||
resource.TestCheckResourceAttr("stackit_argus_instance.instance", "acl.#", "0"),
|
||||
|
||||
// scrape config data
|
||||
resource.TestCheckResourceAttrPair(
|
||||
"stackit_argus_instance.instance", "project_id",
|
||||
"stackit_argus_scrapeconfig.scrapeconfig", "project_id",
|
||||
),
|
||||
resource.TestCheckResourceAttrPair(
|
||||
"stackit_argus_instance.instance", "instance_id",
|
||||
"stackit_argus_scrapeconfig.scrapeconfig", "instance_id",
|
||||
),
|
||||
resource.TestCheckResourceAttr("stackit_argus_scrapeconfig.scrapeconfig", "name", scrapeConfigResource["name"]),
|
||||
resource.TestCheckResourceAttr("stackit_argus_scrapeconfig.scrapeconfig", "targets.0.urls.#", "2"),
|
||||
resource.TestCheckResourceAttr("stackit_argus_scrapeconfig.scrapeconfig", "metrics_path", scrapeConfigResource["metrics_path"]),
|
||||
resource.TestCheckResourceAttr("stackit_argus_scrapeconfig.scrapeconfig", "scheme", scrapeConfigResource["scheme"]),
|
||||
resource.TestCheckResourceAttr("stackit_argus_scrapeconfig.scrapeconfig", "scrape_interval", scrapeConfigResource["scrape_interval"]),
|
||||
resource.TestCheckResourceAttr("stackit_argus_scrapeconfig.scrapeconfig", "sample_limit", scrapeConfigResource["sample_limit"]),
|
||||
resource.TestCheckResourceAttr("stackit_argus_scrapeconfig.scrapeconfig", "saml2.enable_url_parameters", scrapeConfigResource["saml2_enable_url_parameters"]),
|
||||
|
||||
// credentials
|
||||
resource.TestCheckResourceAttr("stackit_argus_credential.credential", "project_id", credentialResource["project_id"]),
|
||||
resource.TestCheckResourceAttrPair(
|
||||
"stackit_argus_instance.instance", "instance_id",
|
||||
"stackit_argus_credential.credential", "instance_id",
|
||||
),
|
||||
resource.TestCheckResourceAttrSet("stackit_argus_credential.credential", "username"),
|
||||
resource.TestCheckResourceAttrSet("stackit_argus_credential.credential", "password"),
|
||||
),
|
||||
},
|
||||
{
|
||||
// Data source
|
||||
Config: fmt.Sprintf(`
|
||||
%s
|
||||
|
|
@ -157,7 +285,16 @@ func TestAccResource(t *testing.T) {
|
|||
name = stackit_argus_scrapeconfig.scrapeconfig.name
|
||||
}
|
||||
`,
|
||||
resourceConfig(instanceResource["name"], instanceResource["plan_name"], scrapeConfigResource["urls"], scrapeConfigResource["saml2_enable_url_parameters"]),
|
||||
resourceConfig(utils.Ptr(fmt.Sprintf(
|
||||
"[%q, %q]",
|
||||
instanceResource["acl-0"],
|
||||
instanceResource["acl-1"],
|
||||
)),
|
||||
instanceResource["name"],
|
||||
instanceResource["plan_name"],
|
||||
scrapeConfigResource["urls"],
|
||||
scrapeConfigResource["saml2_enable_url_parameters"],
|
||||
),
|
||||
),
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
// Instance data
|
||||
|
|
@ -165,6 +302,9 @@ func TestAccResource(t *testing.T) {
|
|||
resource.TestCheckResourceAttrSet("data.stackit_argus_instance.instance", "instance_id"),
|
||||
resource.TestCheckResourceAttr("data.stackit_argus_instance.instance", "name", instanceResource["name"]),
|
||||
resource.TestCheckResourceAttr("data.stackit_argus_instance.instance", "plan_name", instanceResource["plan_name"]),
|
||||
resource.TestCheckResourceAttr("data.stackit_argus_instance.instance", "acl.#", "2"),
|
||||
resource.TestCheckResourceAttr("data.stackit_argus_instance.instance", "acl.0", instanceResource["acl-0"]),
|
||||
resource.TestCheckResourceAttr("data.stackit_argus_instance.instance", "acl.1", instanceResource["acl-1"]),
|
||||
resource.TestCheckResourceAttrPair(
|
||||
"stackit_argus_instance.instance", "project_id",
|
||||
"data.stackit_argus_instance.instance", "project_id",
|
||||
|
|
@ -236,13 +376,25 @@ func TestAccResource(t *testing.T) {
|
|||
},
|
||||
// Update
|
||||
{
|
||||
Config: resourceConfig(fmt.Sprintf("%s-new", instanceResource["name"]), instanceResource["new_plan_name"], "", "true"),
|
||||
Config: resourceConfig(utils.Ptr(fmt.Sprintf(
|
||||
"[%q, %q]",
|
||||
instanceResource["acl-0"],
|
||||
instanceResource["acl-1-updated"],
|
||||
)),
|
||||
fmt.Sprintf("%s-new", instanceResource["name"]),
|
||||
instanceResource["new_plan_name"],
|
||||
"",
|
||||
"true",
|
||||
),
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
// Instance
|
||||
resource.TestCheckResourceAttr("stackit_argus_instance.instance", "project_id", instanceResource["project_id"]),
|
||||
resource.TestCheckResourceAttrSet("stackit_argus_instance.instance", "instance_id"),
|
||||
resource.TestCheckResourceAttr("stackit_argus_instance.instance", "name", instanceResource["name"]+"-new"),
|
||||
resource.TestCheckResourceAttr("stackit_argus_instance.instance", "plan_name", instanceResource["new_plan_name"]),
|
||||
resource.TestCheckResourceAttr("stackit_argus_instance.instance", "acl.#", "2"),
|
||||
resource.TestCheckResourceAttr("stackit_argus_instance.instance", "acl.0", instanceResource["acl-0"]),
|
||||
resource.TestCheckResourceAttr("stackit_argus_instance.instance", "acl.1", instanceResource["acl-1-updated"]),
|
||||
|
||||
// Scrape Config
|
||||
resource.TestCheckResourceAttr("stackit_argus_scrapeconfig.scrapeconfig", "name", scrapeConfigResource["name"]),
|
||||
|
|
@ -300,6 +452,9 @@ func TestAccResource(t *testing.T) {
|
|||
resource.TestCheckResourceAttr("stackit_argus_instance.instance", "name", instanceResource["name"]),
|
||||
resource.TestCheckResourceAttr("stackit_argus_instance.instance", "plan_name", instanceResource["new_plan_name"]),
|
||||
|
||||
// ACL
|
||||
resource.TestCheckResourceAttr("stackit_argus_instance.instance", "acl.#", "0"),
|
||||
|
||||
// Scrape Config
|
||||
resource.TestCheckResourceAttr("stackit_argus_scrapeconfig.scrapeconfig", "name", scrapeConfigResource["name"]),
|
||||
resource.TestCheckResourceAttr("stackit_argus_scrapeconfig.scrapeconfig", "targets.#", "1"),
|
||||
|
|
@ -307,8 +462,8 @@ func TestAccResource(t *testing.T) {
|
|||
resource.TestCheckResourceAttr("stackit_argus_scrapeconfig.scrapeconfig", "scheme", scrapeConfigResource["scheme"]),
|
||||
resource.TestCheckResourceAttr("stackit_argus_scrapeconfig.scrapeconfig", "scrape_interval", scrapeConfigResource["scrape_interval"]),
|
||||
resource.TestCheckResourceAttr("stackit_argus_scrapeconfig.scrapeconfig", "sample_limit", scrapeConfigResource["sample_limit"]),
|
||||
resource.TestCheckResourceAttr("stackit_argus_scrapeconfig.scrapeconfig", "saml2.%", "0"),
|
||||
resource.TestCheckNoResourceAttr("stackit_argus_scrapeconfig.scrapeconfig", "saml2.enable_url_parameters"),
|
||||
resource.TestCheckResourceAttr("stackit_argus_scrapeconfig.scrapeconfig", "saml2.%", "1"),
|
||||
resource.TestCheckResourceAttr("stackit_argus_scrapeconfig.scrapeconfig", "saml2.enable_url_parameters", "false"),
|
||||
),
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -196,6 +196,11 @@ func (d *instanceDataSource) Schema(_ context.Context, _ datasource.SchemaReques
|
|||
"zipkin_spans_url": schema.StringAttribute{
|
||||
Computed: true,
|
||||
},
|
||||
"acl": schema.SetAttribute{
|
||||
Description: "The access control list for this instance. Each entry is a single IP address that is permitted to access, in CIDR notation (/32).",
|
||||
ElementType: types.StringType,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -216,7 +221,13 @@ func (d *instanceDataSource) Read(ctx context.Context, req datasource.ReadReques
|
|||
return
|
||||
}
|
||||
|
||||
err = mapFields(ctx, instanceResponse, &model)
|
||||
aclList, err := d.client.ListACL(ctx, instanceId, projectId).Execute()
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading instance", fmt.Sprintf("Calling API to list ACL data: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
err = mapFields(ctx, instanceResponse, aclList, &model)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading instance", fmt.Sprintf("Processing API payload: %v", err))
|
||||
return
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/setvalidator"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||
|
|
@ -17,6 +18,7 @@ import (
|
|||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
"github.com/hashicorp/terraform-plugin-log/tflog"
|
||||
"github.com/stackitcloud/stackit-sdk-go/core/config"
|
||||
"github.com/stackitcloud/stackit-sdk-go/core/utils"
|
||||
"github.com/stackitcloud/stackit-sdk-go/services/argus"
|
||||
"github.com/stackitcloud/stackit-sdk-go/services/argus/wait"
|
||||
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion"
|
||||
|
|
@ -58,6 +60,7 @@ type Model struct {
|
|||
JaegerUIURL types.String `tfsdk:"jaeger_ui_url"`
|
||||
OtlpTracesURL types.String `tfsdk:"otlp_traces_url"`
|
||||
ZipkinSpansURL types.String `tfsdk:"zipkin_spans_url"`
|
||||
ACL types.Set `tfsdk:"acl"`
|
||||
}
|
||||
|
||||
// NewInstanceResource is a helper function to simplify the provider implementation.
|
||||
|
|
@ -250,6 +253,16 @@ func (r *instanceResource) Schema(_ context.Context, _ resource.SchemaRequest, r
|
|||
"zipkin_spans_url": schema.StringAttribute{
|
||||
Computed: true,
|
||||
},
|
||||
"acl": schema.SetAttribute{
|
||||
Description: "The access control list for this instance. Each entry is a single IP address that is permitted to access, in CIDR notation (/32).",
|
||||
ElementType: types.StringType,
|
||||
Optional: true,
|
||||
Validators: []validator.Set{
|
||||
setvalidator.ValueStringsAre(
|
||||
validate.CIDR(),
|
||||
),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -264,6 +277,15 @@ func (r *instanceResource) Create(ctx context.Context, req resource.CreateReques
|
|||
return
|
||||
}
|
||||
|
||||
acl := []string{}
|
||||
if !(model.ACL.IsNull() || model.ACL.IsUnknown()) {
|
||||
diags = model.ACL.ElementsAs(ctx, &acl, false)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
projectId := model.ProjectId.ValueString()
|
||||
ctx = tflog.SetField(ctx, "project_id", projectId)
|
||||
|
||||
|
|
@ -273,12 +295,12 @@ func (r *instanceResource) Create(ctx context.Context, req resource.CreateReques
|
|||
return
|
||||
}
|
||||
// Generate API request body from model
|
||||
payload, err := toCreatePayload(&model)
|
||||
createPayload, err := toCreatePayload(&model)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating instance", fmt.Sprintf("Creating API payload: %v", err))
|
||||
return
|
||||
}
|
||||
createResp, err := r.client.CreateInstance(ctx, projectId).CreateInstancePayload(*payload).Execute()
|
||||
createResp, err := r.client.CreateInstance(ctx, projectId).CreateInstancePayload(*createPayload).Execute()
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating instance", fmt.Sprintf("Calling API: %v", err))
|
||||
return
|
||||
|
|
@ -292,11 +314,38 @@ func (r *instanceResource) Create(ctx context.Context, req resource.CreateReques
|
|||
}
|
||||
|
||||
// Map response body to schema
|
||||
err = mapFields(ctx, waitResp, &model)
|
||||
err = mapFields(ctx, waitResp, nil, &model)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating instance", fmt.Sprintf("Processing API payload: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
// Set state to instance populated data
|
||||
diags = resp.State.Set(ctx, model)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
// Create ACL
|
||||
err = updateACL(ctx, projectId, *instanceId, acl, r.client)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating instance", fmt.Sprintf("Creating ACL: %v", err))
|
||||
return
|
||||
}
|
||||
aclList, err := r.client.ListACL(ctx, *instanceId, projectId).Execute()
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating instance", fmt.Sprintf("Calling API to list ACL data: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
// Map response body to schema
|
||||
err = mapFields(ctx, waitResp, aclList, &model)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating instance", fmt.Sprintf("Processing API response: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
// Set state to fully populated data
|
||||
diags = resp.State.Set(ctx, model)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
|
|
@ -325,19 +374,27 @@ func (r *instanceResource) Read(ctx context.Context, req resource.ReadRequest, r
|
|||
return
|
||||
}
|
||||
|
||||
aclList, err := r.client.ListACL(ctx, instanceId, projectId).Execute()
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading instance", fmt.Sprintf("Calling API for ACL data: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
// Map response body to schema
|
||||
err = mapFields(ctx, instanceResp, &model)
|
||||
err = mapFields(ctx, instanceResp, aclList, &model)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading instance", fmt.Sprintf("Processing API payload: %v", err))
|
||||
return
|
||||
}
|
||||
// Set refreshed model
|
||||
|
||||
// Set state to fully populated data
|
||||
diags = resp.State.Set(ctx, model)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
tflog.Info(ctx, "Argus instance created")
|
||||
|
||||
tflog.Info(ctx, "Argus instance read")
|
||||
}
|
||||
|
||||
// Update updates the resource and sets the updated Terraform state on success.
|
||||
|
|
@ -352,6 +409,15 @@ func (r *instanceResource) Update(ctx context.Context, req resource.UpdateReques
|
|||
projectId := model.ProjectId.ValueString()
|
||||
instanceId := model.InstanceId.ValueString()
|
||||
|
||||
acl := []string{}
|
||||
if !(model.ACL.IsNull() || model.ACL.IsUnknown()) {
|
||||
diags = model.ACL.ElementsAs(ctx, &acl, false)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
err := r.loadPlanId(ctx, &model)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating instance", fmt.Sprintf("Loading service plan: %v", err))
|
||||
|
|
@ -376,7 +442,7 @@ func (r *instanceResource) Update(ctx context.Context, req resource.UpdateReques
|
|||
return
|
||||
}
|
||||
|
||||
err = mapFields(ctx, waitResp, &model)
|
||||
err = mapFields(ctx, waitResp, nil, &model)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating instance", fmt.Sprintf("Processing API payload: %v", err))
|
||||
return
|
||||
|
|
@ -386,6 +452,33 @@ func (r *instanceResource) Update(ctx context.Context, req resource.UpdateReques
|
|||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
// Update ACL
|
||||
err = updateACL(ctx, projectId, instanceId, acl, r.client)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating instance", fmt.Sprintf("Updating ACL: %v", err))
|
||||
return
|
||||
}
|
||||
aclList, err := r.client.ListACL(ctx, instanceId, projectId).Execute()
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating instance", fmt.Sprintf("Calling API to list ACL data: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
// Map response body to schema
|
||||
err = mapFields(ctx, waitResp, aclList, &model)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating instance", fmt.Sprintf("Processing ACL API payload: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
// Set state to ACL populated data
|
||||
diags = resp.State.Set(ctx, model)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
tflog.Info(ctx, "Argus instance updated")
|
||||
}
|
||||
|
||||
|
|
@ -435,7 +528,7 @@ func (r *instanceResource) ImportState(ctx context.Context, req resource.ImportS
|
|||
tflog.Info(ctx, "Argus instance state imported")
|
||||
}
|
||||
|
||||
func mapFields(ctx context.Context, r *argus.GetInstanceResponse, model *Model) error {
|
||||
func mapFields(ctx context.Context, r *argus.GetInstanceResponse, acl *argus.ListACLResponse, model *Model) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("response input is nil")
|
||||
}
|
||||
|
|
@ -500,6 +593,37 @@ func mapFields(ctx context.Context, r *argus.GetInstanceResponse, model *Model)
|
|||
model.OtlpTracesURL = types.StringPointerValue(i.OtlpTracesUrl)
|
||||
model.ZipkinSpansURL = types.StringPointerValue(i.ZipkinSpansUrl)
|
||||
}
|
||||
|
||||
err := mapACLField(acl, model)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func mapACLField(aclList *argus.ListACLResponse, model *Model) error {
|
||||
if aclList == nil {
|
||||
if model.ACL.IsNull() || model.ACL.IsUnknown() {
|
||||
model.ACL = types.SetNull(types.StringType)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if aclList.Acl == nil || len(*aclList.Acl) == 0 {
|
||||
model.ACL = types.SetNull(types.StringType)
|
||||
return nil
|
||||
}
|
||||
|
||||
acl := []attr.Value{}
|
||||
for _, cidr := range *aclList.Acl {
|
||||
acl = append(acl, types.StringValue(cidr))
|
||||
}
|
||||
aclTF, diags := types.SetValue(types.StringType, acl)
|
||||
if diags.HasError() {
|
||||
return fmt.Errorf("mapping ACL: %w", core.DiagsToError(diags))
|
||||
}
|
||||
model.ACL = aclTF
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -519,6 +643,19 @@ func toCreatePayload(model *Model) (*argus.CreateInstancePayload, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
func updateACL(ctx context.Context, projectId, instanceId string, acl []string, client *argus.APIClient) error {
|
||||
payload := argus.UpdateACLPayload{
|
||||
Acl: utils.Ptr(acl),
|
||||
}
|
||||
|
||||
_, err := client.UpdateACL(ctx, instanceId, projectId).UpdateACLPayload(payload).Execute()
|
||||
if err != nil {
|
||||
return fmt.Errorf("updating ACL: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func toUpdatePayload(model *Model) (*argus.UpdateInstancePayload, error) {
|
||||
if model == nil {
|
||||
return nil, fmt.Errorf("nil model")
|
||||
|
|
|
|||
|
|
@ -14,16 +14,18 @@ import (
|
|||
|
||||
func TestMapFields(t *testing.T) {
|
||||
tests := []struct {
|
||||
description string
|
||||
input *argus.GetInstanceResponse
|
||||
expected Model
|
||||
isValid bool
|
||||
description string
|
||||
instanceResp *argus.GetInstanceResponse
|
||||
listACLResp *argus.ListACLResponse
|
||||
expected Model
|
||||
isValid bool
|
||||
}{
|
||||
{
|
||||
"default_ok",
|
||||
&argus.GetInstanceResponse{
|
||||
Id: utils.Ptr("iid"),
|
||||
},
|
||||
nil,
|
||||
Model{
|
||||
Id: types.StringValue("pid,iid"),
|
||||
ProjectId: types.StringValue("pid"),
|
||||
|
|
@ -32,6 +34,7 @@ func TestMapFields(t *testing.T) {
|
|||
PlanName: types.StringNull(),
|
||||
Name: types.StringNull(),
|
||||
Parameters: types.MapNull(types.StringType),
|
||||
ACL: types.SetNull(types.StringType),
|
||||
},
|
||||
true,
|
||||
},
|
||||
|
|
@ -44,6 +47,12 @@ func TestMapFields(t *testing.T) {
|
|||
PlanId: utils.Ptr("planId"),
|
||||
Parameters: &map[string]string{"key": "value"},
|
||||
},
|
||||
&argus.ListACLResponse{
|
||||
Acl: &[]string{
|
||||
"1.1.1.1/32",
|
||||
},
|
||||
Message: utils.Ptr("message"),
|
||||
},
|
||||
Model{
|
||||
Id: types.StringValue("pid,iid"),
|
||||
ProjectId: types.StringValue("pid"),
|
||||
|
|
@ -52,6 +61,40 @@ func TestMapFields(t *testing.T) {
|
|||
PlanId: types.StringValue("planId"),
|
||||
PlanName: types.StringValue("plan1"),
|
||||
Parameters: toTerraformStringMapMust(context.Background(), map[string]string{"key": "value"}),
|
||||
ACL: types.SetValueMust(types.StringType, []attr.Value{
|
||||
types.StringValue("1.1.1.1/32"),
|
||||
}),
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"values_ok_multiple_acls",
|
||||
&argus.GetInstanceResponse{
|
||||
Id: utils.Ptr("iid"),
|
||||
Name: utils.Ptr("name"),
|
||||
PlanName: utils.Ptr("plan1"),
|
||||
PlanId: utils.Ptr("planId"),
|
||||
Parameters: &map[string]string{"key": "value"},
|
||||
},
|
||||
&argus.ListACLResponse{
|
||||
Acl: &[]string{
|
||||
"1.1.1.1/32",
|
||||
"8.8.8.8/32",
|
||||
},
|
||||
Message: utils.Ptr("message"),
|
||||
},
|
||||
Model{
|
||||
Id: types.StringValue("pid,iid"),
|
||||
ProjectId: types.StringValue("pid"),
|
||||
Name: types.StringValue("name"),
|
||||
InstanceId: types.StringValue("iid"),
|
||||
PlanId: types.StringValue("planId"),
|
||||
PlanName: types.StringValue("plan1"),
|
||||
Parameters: toTerraformStringMapMust(context.Background(), map[string]string{"key": "value"}),
|
||||
ACL: types.SetValueMust(types.StringType, []attr.Value{
|
||||
types.StringValue("1.1.1.1/32"),
|
||||
types.StringValue("8.8.8.8/32"),
|
||||
}),
|
||||
},
|
||||
true,
|
||||
},
|
||||
|
|
@ -61,6 +104,10 @@ func TestMapFields(t *testing.T) {
|
|||
Id: utils.Ptr("iid"),
|
||||
Name: nil,
|
||||
},
|
||||
&argus.ListACLResponse{
|
||||
Acl: &[]string{},
|
||||
Message: nil,
|
||||
},
|
||||
Model{
|
||||
Id: types.StringValue("pid,iid"),
|
||||
ProjectId: types.StringValue("pid"),
|
||||
|
|
@ -69,18 +116,21 @@ func TestMapFields(t *testing.T) {
|
|||
PlanName: types.StringNull(),
|
||||
Name: types.StringNull(),
|
||||
Parameters: types.MapNull(types.StringType),
|
||||
ACL: types.SetNull(types.StringType),
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"response_nil_fail",
|
||||
nil,
|
||||
nil,
|
||||
Model{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"no_resource_id",
|
||||
&argus.GetInstanceResponse{},
|
||||
nil,
|
||||
Model{},
|
||||
false,
|
||||
},
|
||||
|
|
@ -90,7 +140,7 @@ func TestMapFields(t *testing.T) {
|
|||
state := &Model{
|
||||
ProjectId: tt.expected.ProjectId,
|
||||
}
|
||||
err := mapFields(context.Background(), tt.input, state)
|
||||
err := mapFields(context.Background(), tt.instanceResp, tt.listACLResp, state)
|
||||
if !tt.isValid && err == nil {
|
||||
t.Fatalf("Should have failed")
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue