Onboard Argus (ACL): fix edge cases (#314)
* fix empty acl update/create, update CIDR validator * fix sigsegv in test, acl description * Split field mapping, better handle edge cases * Update stackit/internal/services/argus/instance/resource.go Co-authored-by: Vicente Pinto <vicente.pinto@freiheit.com> --------- Co-authored-by: Vicente Pinto <vicente.pinto@freiheit.com>
This commit is contained in:
parent
056c000acc
commit
394d5bf8d6
5 changed files with 99 additions and 24 deletions
|
|
@ -269,6 +269,71 @@ func TestAccResource(t *testing.T) {
|
|||
resource.TestCheckResourceAttrSet("stackit_argus_credential.credential", "password"),
|
||||
),
|
||||
},
|
||||
// Creation with empty ACL
|
||||
{
|
||||
Config: resourceConfig(
|
||||
utils.Ptr("[]"),
|
||||
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(`
|
||||
|
|
|
|||
|
|
@ -227,11 +227,17 @@ func (d *instanceDataSource) Read(ctx context.Context, req datasource.ReadReques
|
|||
return
|
||||
}
|
||||
|
||||
err = mapFields(ctx, instanceResponse, aclList, &model)
|
||||
// Map response body to schema
|
||||
err = mapFields(ctx, instanceResponse, &model)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading instance", fmt.Sprintf("Processing API payload: %v", err))
|
||||
return
|
||||
}
|
||||
err = mapACLField(aclList, &model)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating instance", fmt.Sprintf("Processing API response for the ACL: %v", err))
|
||||
return
|
||||
}
|
||||
diags = resp.State.Set(ctx, model)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
|
|
|
|||
|
|
@ -314,7 +314,7 @@ func (r *instanceResource) Create(ctx context.Context, req resource.CreateReques
|
|||
}
|
||||
|
||||
// Map response body to schema
|
||||
err = mapFields(ctx, waitResp, nil, &model)
|
||||
err = mapFields(ctx, waitResp, &model)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating instance", fmt.Sprintf("Processing API payload: %v", err))
|
||||
return
|
||||
|
|
@ -340,9 +340,9 @@ func (r *instanceResource) Create(ctx context.Context, req resource.CreateReques
|
|||
}
|
||||
|
||||
// Map response body to schema
|
||||
err = mapFields(ctx, waitResp, aclList, &model)
|
||||
err = mapACLField(aclList, &model)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating instance", fmt.Sprintf("Processing API response: %v", err))
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating instance", fmt.Sprintf("Processing API response for the ACL: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -381,12 +381,19 @@ func (r *instanceResource) Read(ctx context.Context, req resource.ReadRequest, r
|
|||
}
|
||||
|
||||
// Map response body to schema
|
||||
err = mapFields(ctx, instanceResp, aclList, &model)
|
||||
err = mapFields(ctx, instanceResp, &model)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading instance", fmt.Sprintf("Processing API payload: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
// Map response body to schema
|
||||
err = mapACLField(aclList, &model)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating instance", fmt.Sprintf("Processing API response for the ACL: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
// Set state to fully populated data
|
||||
diags = resp.State.Set(ctx, model)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
|
|
@ -442,7 +449,7 @@ func (r *instanceResource) Update(ctx context.Context, req resource.UpdateReques
|
|||
return
|
||||
}
|
||||
|
||||
err = mapFields(ctx, waitResp, nil, &model)
|
||||
err = mapFields(ctx, waitResp, &model)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating instance", fmt.Sprintf("Processing API payload: %v", err))
|
||||
return
|
||||
|
|
@ -466,9 +473,9 @@ func (r *instanceResource) Update(ctx context.Context, req resource.UpdateReques
|
|||
}
|
||||
|
||||
// Map response body to schema
|
||||
err = mapFields(ctx, waitResp, aclList, &model)
|
||||
err = mapACLField(aclList, &model)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating instance", fmt.Sprintf("Processing ACL API payload: %v", err))
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating instance", fmt.Sprintf("Processing API response for the ACL: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -528,7 +535,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, acl *argus.ListACLResponse, model *Model) error {
|
||||
func mapFields(ctx context.Context, r *argus.GetInstanceResponse, model *Model) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("response input is nil")
|
||||
}
|
||||
|
|
@ -594,24 +601,18 @@ func mapFields(ctx context.Context, r *argus.GetInstanceResponse, acl *argus.Lis
|
|||
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
|
||||
return fmt.Errorf("mapping ACL: nil API response")
|
||||
}
|
||||
|
||||
if aclList.Acl == nil || len(*aclList.Acl) == 0 {
|
||||
model.ACL = types.SetNull(types.StringType)
|
||||
if !(model.ACL.IsNull() || model.ACL.IsUnknown() || model.ACL.Equal(types.SetValueMust(types.StringType, []attr.Value{}))) {
|
||||
model.ACL = types.SetNull(types.StringType)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ func TestMapFields(t *testing.T) {
|
|||
&argus.GetInstanceResponse{
|
||||
Id: utils.Ptr("iid"),
|
||||
},
|
||||
nil,
|
||||
&argus.ListACLResponse{},
|
||||
Model{
|
||||
Id: types.StringValue("pid,iid"),
|
||||
ProjectId: types.StringValue("pid"),
|
||||
|
|
@ -139,14 +139,17 @@ func TestMapFields(t *testing.T) {
|
|||
t.Run(tt.description, func(t *testing.T) {
|
||||
state := &Model{
|
||||
ProjectId: tt.expected.ProjectId,
|
||||
ACL: types.SetNull(types.StringType),
|
||||
}
|
||||
err := mapFields(context.Background(), tt.instanceResp, tt.listACLResp, state)
|
||||
if !tt.isValid && err == nil {
|
||||
err := mapFields(context.Background(), tt.instanceResp, state)
|
||||
aclErr := mapACLField(tt.listACLResp, state)
|
||||
if !tt.isValid && err == nil && aclErr == nil {
|
||||
t.Fatalf("Should have failed")
|
||||
}
|
||||
if tt.isValid && err != nil {
|
||||
if tt.isValid && (err != nil || aclErr != nil) {
|
||||
t.Fatalf("Should not have failed: %v", err)
|
||||
}
|
||||
|
||||
if tt.isValid {
|
||||
diff := cmp.Diff(state, &tt.expected)
|
||||
if diff != "" {
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@ func CIDR() *Validator {
|
|||
if err != nil {
|
||||
resp.Diagnostics.Append(validatordiag.InvalidAttributeValueDiagnostic(
|
||||
req.Path,
|
||||
fmt.Sprintf("parsing value in CIDR notation: %s", err.Error()),
|
||||
"parsing value in CIDR notation: invalid CIDR address",
|
||||
req.ConfigValue.ValueString(),
|
||||
))
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue