Allow users to set Argus metrics storage retention policy (#393)

* implement crud commands

* resource testing

* acceptance tests

* move function to utils, cleanup tests

* fix linting

* use conversion pkg for int conversion, extend testing

* address PR comments

* address PR comments
This commit is contained in:
Diogo Ferrão 2024-06-06 16:54:03 +01:00 committed by GitHub
parent a86f2250ad
commit f941e53b15
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 553 additions and 116 deletions

View file

@ -33,6 +33,9 @@ resource "stackit_argus_instance" "example" {
### Optional
- `acl` (Set of String) The access control list for this instance. Each entry is an IP address range that is permitted to access, in CIDR notation.
- `metrics_retention_days` (Number) Specifies for how many days the raw metrics are kept.
- `metrics_retention_days_1h_downsampling` (Number) Specifies for how many days the 1h downsampled metrics are kept. must be less than the value of the 5m downsampling retention. Default is set to `0` (disabled).
- `metrics_retention_days_5m_downsampling` (Number) Specifies for how many days the 5m downsampled metrics are kept. must be less than the value of the general retention. Default is set to `0` (disabled).
- `parameters` (Map of String) Additional parameters.
### Read-Only
@ -51,9 +54,6 @@ resource "stackit_argus_instance" "example" {
- `logs_push_url` (String) Specifies URL for pushing logs.
- `logs_url` (String) Specifies Logs URL.
- `metrics_push_url` (String) Specifies URL for pushing metrics.
- `metrics_retention_days` (Number) Specifies for how many days the raw metrics are kept.
- `metrics_retention_days_1h_downsampling` (Number) Specifies for how many days the 1h downsampled metrics are kept. must be less than the value of the 5m downsampling retention. Default is set to `0` (disabled).
- `metrics_retention_days_5m_downsampling` (Number) Specifies for how many days the 5m downsampled metrics are kept. must be less than the value of the general retention. Default is set to `0` (disabled).
- `metrics_url` (String) Specifies metrics URL.
- `otlp_traces_url` (String)
- `plan_id` (String) The Argus plan ID.

View file

@ -18,13 +18,16 @@ import (
)
var instanceResource = map[string]string{
"project_id": testutil.ProjectId,
"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",
"project_id": testutil.ProjectId,
"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",
"metrics_retention_days": "60",
"metrics_retention_days_5m_downsampling": "30",
"metrics_retention_days_1h_downsampling": "15",
}
var scrapeConfigResource = map[string]string{
@ -42,59 +45,48 @@ var credentialResource = map[string]string{
"project_id": testutil.ProjectId,
}
func resourceConfig(acl *string, instanceName, planName, target, saml2EnableUrlParameters string) string {
if acl == nil {
return fmt.Sprintf(`
%s
func instanceResourceConfig(acl, metricsRetentionDays, metricsRetentionDays1hDownsampling, metricsRetentionDays5mDownsampling *string, instanceName, planName string) string {
var aclStr string
var metricsRetentionDaysStr string
var metricsRetentionDays1hDownsamplingStr string
var metricsRetentionDays5mDownsamplingStr string
resource "stackit_argus_instance" "instance" {
project_id = "%s"
name = "%s"
plan_name = "%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,
scrapeConfigResource["name"],
scrapeConfigResource["metrics_path"],
target,
scrapeConfigResource["scrape_interval"],
scrapeConfigResource["sample_limit"],
saml2EnableUrlParameters,
)
if acl != nil {
aclStr = fmt.Sprintf("acl = %s", *acl)
}
if metricsRetentionDays != nil {
metricsRetentionDaysStr = fmt.Sprintf("metrics_retention_days = %s", *metricsRetentionDays)
}
if metricsRetentionDays1hDownsampling != nil {
metricsRetentionDays1hDownsamplingStr = fmt.Sprintf("metrics_retention_days_1h_downsampling = %s", *metricsRetentionDays1hDownsampling)
}
if metricsRetentionDays5mDownsampling != nil {
metricsRetentionDays5mDownsamplingStr = fmt.Sprintf("metrics_retention_days_5m_downsampling = %s", *metricsRetentionDays5mDownsampling)
}
optionalsStr := strings.Join([]string{aclStr, metricsRetentionDaysStr, metricsRetentionDays1hDownsamplingStr, metricsRetentionDays5mDownsamplingStr}, "\n")
return fmt.Sprintf(`
%s
resource "stackit_argus_instance" "instance" {
project_id = "%s"
name = "%s"
plan_name = "%s"
%s
}
`,
instanceResource["project_id"],
instanceName,
planName,
optionalsStr,
)
}
resource "stackit_argus_instance" "instance" {
project_id = "%s"
name = "%s"
plan_name = "%s"
acl = %s
}
resource "stackit_argus_scrapeconfig" "scrapeconfig" {
func scrapeConfigResourceConfig(target, saml2EnableUrlParameters string) string {
return fmt.Sprintf(
`resource "stackit_argus_scrapeconfig" "scrapeconfig" {
project_id = stackit_argus_instance.instance.project_id
instance_id = stackit_argus_instance.instance.instance_id
name = "%s"
@ -105,19 +97,7 @@ func resourceConfig(acl *string, instanceName, planName, target, saml2EnableUrlP
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,
@ -127,6 +107,22 @@ func resourceConfig(acl *string, instanceName, planName, target, saml2EnableUrlP
)
}
func credentialResourceConfig() string {
return `resource "stackit_argus_credential" "credential" {
project_id = stackit_argus_instance.instance.project_id
instance_id = stackit_argus_instance.instance.instance_id
}`
}
func resourceConfig(acl, metricsRetentionDays, metricsRetentionDays1hDownsampling, metricsRetentionDays5mDownsampling *string, instanceName, planName, target, saml2EnableUrlParameters string) string {
return fmt.Sprintf("%s\n\n%s\n\n%s\n\n%s",
testutil.ArgusProviderConfig(),
instanceResourceConfig(acl, metricsRetentionDays, metricsRetentionDays1hDownsampling, metricsRetentionDays5mDownsampling, instanceName, planName),
scrapeConfigResourceConfig(target, saml2EnableUrlParameters),
credentialResourceConfig(),
)
}
func TestAccResource(t *testing.T) {
resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: testutil.TestAccProtoV6ProviderFactories,
@ -141,6 +137,9 @@ func TestAccResource(t *testing.T) {
instanceResource["acl-1"],
instanceResource["acl-1"],
)),
utils.Ptr(instanceResource["metrics_retention_days"]),
utils.Ptr(instanceResource["metrics_retention_days_1h_downsampling"]),
utils.Ptr(instanceResource["metrics_retention_days_5m_downsampling"]),
instanceResource["name"],
instanceResource["plan_name"],
scrapeConfigResource["urls"],
@ -158,9 +157,9 @@ func TestAccResource(t *testing.T) {
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.TestCheckResourceAttr("stackit_argus_instance.instance", "metrics_retention_days", instanceResource["metrics_retention_days"]),
resource.TestCheckResourceAttr("stackit_argus_instance.instance", "metrics_retention_days_5m_downsampling", instanceResource["metrics_retention_days_5m_downsampling"]),
resource.TestCheckResourceAttr("stackit_argus_instance.instance", "metrics_retention_days_1h_downsampling", instanceResource["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"),
@ -204,9 +203,12 @@ func TestAccResource(t *testing.T) {
resource.TestCheckResourceAttrSet("stackit_argus_credential.credential", "password"),
),
},
// Creation without ACL
// Creation without ACL and partial metrics retention days
{
Config: resourceConfig(
nil,
nil,
utils.Ptr(instanceResource["metrics_retention_days_1h_downsampling"]),
nil,
instanceResource["name"],
instanceResource["plan_name"],
@ -227,7 +229,7 @@ func TestAccResource(t *testing.T) {
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.TestCheckResourceAttr("stackit_argus_instance.instance", "metrics_retention_days_1h_downsampling", instanceResource["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"),
@ -273,6 +275,9 @@ func TestAccResource(t *testing.T) {
{
Config: resourceConfig(
utils.Ptr("[]"),
nil,
nil,
nil,
instanceResource["name"],
instanceResource["plan_name"],
scrapeConfigResource["urls"],
@ -350,11 +355,15 @@ func TestAccResource(t *testing.T) {
name = stackit_argus_scrapeconfig.scrapeconfig.name
}
`,
resourceConfig(utils.Ptr(fmt.Sprintf(
"[%q, %q]",
instanceResource["acl-0"],
instanceResource["acl-1"],
)),
resourceConfig(
utils.Ptr(fmt.Sprintf(
"[%q, %q]",
instanceResource["acl-0"],
instanceResource["acl-1"],
)),
utils.Ptr(instanceResource["metrics_retention_days"]),
utils.Ptr(instanceResource["metrics_retention_days_1h_downsampling"]),
utils.Ptr(instanceResource["metrics_retention_days_5m_downsampling"]),
instanceResource["name"],
instanceResource["plan_name"],
scrapeConfigResource["urls"],
@ -441,11 +450,15 @@ func TestAccResource(t *testing.T) {
},
// Update
{
Config: resourceConfig(utils.Ptr(fmt.Sprintf(
"[%q, %q]",
instanceResource["acl-0"],
instanceResource["acl-1-updated"],
)),
Config: resourceConfig(
utils.Ptr(fmt.Sprintf(
"[%q, %q]",
instanceResource["acl-0"],
instanceResource["acl-1-updated"],
)),
utils.Ptr(instanceResource["metrics_retention_days"]),
utils.Ptr(instanceResource["metrics_retention_days_1h_downsampling"]),
utils.Ptr(instanceResource["metrics_retention_days_5m_downsampling"]),
fmt.Sprintf("%s-new", instanceResource["name"]),
instanceResource["new_plan_name"],
"",

View file

@ -233,7 +233,7 @@ func (d *instanceDataSource) Read(ctx context.Context, req datasource.ReadReques
return
}
aclList, err := d.client.ListACL(ctx, instanceId, projectId).Execute()
aclListResp, 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
@ -245,11 +245,12 @@ func (d *instanceDataSource) Read(ctx context.Context, req datasource.ReadReques
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading instance", fmt.Sprintf("Processing API payload: %v", err))
return
}
err = mapACLField(aclList, &model)
err = mapACLField(aclListResp, &model)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating instance", fmt.Sprintf("Processing API response for the ACL: %v", err))
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading 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() {

View file

@ -4,6 +4,7 @@ import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/hashicorp/terraform-plugin-framework-validators/setvalidator"
@ -209,14 +210,17 @@ func (r *instanceResource) Schema(_ context.Context, _ resource.SchemaRequest, r
},
"metrics_retention_days": schema.Int64Attribute{
Description: "Specifies for how many days the raw metrics are kept.",
Optional: true,
Computed: true,
},
"metrics_retention_days_5m_downsampling": schema.Int64Attribute{
Description: "Specifies for how many days the 5m downsampled metrics are kept. must be less than the value of the general retention. Default is set to `0` (disabled).",
Optional: true,
Computed: true,
},
"metrics_retention_days_1h_downsampling": schema.Int64Attribute{
Description: "Specifies for how many days the 1h downsampled metrics are kept. must be less than the value of the 5m downsampling retention. Default is set to `0` (disabled).",
Optional: true,
Computed: true,
},
"metrics_url": schema.StringAttribute{
@ -288,6 +292,10 @@ func (r *instanceResource) Create(ctx context.Context, req resource.CreateReques
}
}
metricsRetentionDays := conversion.Int64ValueToPointer(model.MetricsRetentionDays)
metricsRetentionDays5mDownsampling := conversion.Int64ValueToPointer(model.MetricsRetentionDays5mDownsampling)
metricsRetentionDays1hDownsampling := conversion.Int64ValueToPointer(model.MetricsRetentionDays1hDownsampling)
projectId := model.ProjectId.ValueString()
ctx = tflog.SetField(ctx, "project_id", projectId)
@ -354,6 +362,49 @@ func (r *instanceResource) Create(ctx context.Context, req resource.CreateReques
if resp.Diagnostics.HasError() {
return
}
// If any of the metrics retention days are set, set the metrics retention policy
if metricsRetentionDays != nil || metricsRetentionDays5mDownsampling != nil || metricsRetentionDays1hDownsampling != nil {
// Need to get the metrics retention policy because update endpoint is a PUT and we need to send all fields
metricsResp, err := r.client.GetMetricsStorageRetentionExecute(ctx, *instanceId, projectId)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating instance", fmt.Sprintf("Getting metrics retention policy: %v", err))
return
}
metricsRetentionPayload, err := toUpdateMetricsStorageRetentionPayload(metricsRetentionDays, metricsRetentionDays5mDownsampling, metricsRetentionDays1hDownsampling, metricsResp)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating instance", fmt.Sprintf("Building metrics retention policy payload: %v", err))
return
}
_, err = r.client.UpdateMetricsStorageRetention(ctx, *instanceId, projectId).UpdateMetricsStorageRetentionPayload(*metricsRetentionPayload).Execute()
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating instance", fmt.Sprintf("Setting metrics retention policy: %v", err))
return
}
}
// Get metrics retention policy after update
metricsResp, err := r.client.GetMetricsStorageRetentionExecute(ctx, *instanceId, projectId)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating instance", fmt.Sprintf("Getting metrics retention policy: %v", err))
return
}
// Map response body to schema
err = mapMetricsRetentionField(metricsResp, &model)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating instance", fmt.Sprintf("Processing API response for the metrics retention: %v", err))
return
}
// 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")
}
@ -385,12 +436,18 @@ func (r *instanceResource) Read(ctx context.Context, req resource.ReadRequest, r
return
}
aclList, err := r.client.ListACL(ctx, instanceId, projectId).Execute()
aclListResp, 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
}
metricsRetentionResp, err := r.client.GetMetricsStorageRetention(ctx, instanceId, projectId).Execute()
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading instance", fmt.Sprintf("Calling API to get metrics retention: %v", err))
return
}
// Map response body to schema
err = mapFields(ctx, instanceResp, &model)
if err != nil {
@ -399,9 +456,16 @@ func (r *instanceResource) Read(ctx context.Context, req resource.ReadRequest, r
}
// Map response body to schema
err = mapACLField(aclList, &model)
err = mapACLField(aclListResp, &model)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating instance", fmt.Sprintf("Processing API response for the ACL: %v", err))
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading instance", fmt.Sprintf("Processing API response for the ACL: %v", err))
return
}
// Map response body to schema
err = mapMetricsRetentionField(metricsRetentionResp, &model)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading instance", fmt.Sprintf("Processing API response for the metrics retention: %v", err))
return
}
@ -436,6 +500,10 @@ func (r *instanceResource) Update(ctx context.Context, req resource.UpdateReques
}
}
metricsRetentionDays := conversion.Int64ValueToPointer(model.MetricsRetentionDays)
metricsRetentionDays5mDownsampling := conversion.Int64ValueToPointer(model.MetricsRetentionDays5mDownsampling)
metricsRetentionDays1hDownsampling := conversion.Int64ValueToPointer(model.MetricsRetentionDays1hDownsampling)
err := r.loadPlanId(ctx, &model)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating instance", fmt.Sprintf("Loading service plan: %v", err))
@ -497,6 +565,47 @@ func (r *instanceResource) Update(ctx context.Context, req resource.UpdateReques
return
}
// If any of the metrics retention days are set, set the metrics retention policy
if metricsRetentionDays != nil || metricsRetentionDays5mDownsampling != nil || metricsRetentionDays1hDownsampling != nil {
// Need to get the metrics retention policy because update endpoint is a PUT and we need to send all fields
metricsResp, err := r.client.GetMetricsStorageRetentionExecute(ctx, instanceId, projectId)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating instance", fmt.Sprintf("Getting metrics retention policy: %v", err))
return
}
metricsRetentionPayload, err := toUpdateMetricsStorageRetentionPayload(metricsRetentionDays, metricsRetentionDays5mDownsampling, metricsRetentionDays1hDownsampling, metricsResp)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating instance", fmt.Sprintf("Building metrics retention policy payload: %v", err))
return
}
_, err = r.client.UpdateMetricsStorageRetention(ctx, instanceId, projectId).UpdateMetricsStorageRetentionPayload(*metricsRetentionPayload).Execute()
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating instance", fmt.Sprintf("Setting metrics retention policy: %v", err))
return
}
}
// Get metrics retention policy after update
metricsResp, err := r.client.GetMetricsStorageRetentionExecute(ctx, instanceId, projectId)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating instance", fmt.Sprintf("Getting metrics retention policy: %v", err))
return
}
// Map response body to schema
err = mapMetricsRetentionField(metricsResp, &model)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating instance", fmt.Sprintf("Processing API response for the metrics retention %v", err))
return
}
// 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 updated")
}
@ -639,6 +748,42 @@ func mapACLField(aclList *argus.ListACLResponse, model *Model) error {
return nil
}
func mapMetricsRetentionField(r *argus.GetMetricsStorageRetentionResponse, model *Model) error {
if r == nil {
return fmt.Errorf("response input is nil")
}
if model == nil {
return fmt.Errorf("model input is nil")
}
if r.MetricsRetentionTimeRaw == nil || r.MetricsRetentionTime5m == nil || r.MetricsRetentionTime1h == nil {
return fmt.Errorf("metrics retention time is nil")
}
stripedMetricsRetentionDays := strings.TrimSuffix(*r.MetricsRetentionTimeRaw, "d")
metricsRetentionDays, err := strconv.ParseInt(stripedMetricsRetentionDays, 10, 64)
if err != nil {
return fmt.Errorf("parsing metrics retention days: %w", err)
}
model.MetricsRetentionDays = types.Int64Value(metricsRetentionDays)
stripedMetricsRetentionDays5m := strings.TrimSuffix(*r.MetricsRetentionTime5m, "d")
metricsRetentionDays5m, err := strconv.ParseInt(stripedMetricsRetentionDays5m, 10, 64)
if err != nil {
return fmt.Errorf("parsing metrics retention days 5m: %w", err)
}
model.MetricsRetentionDays5mDownsampling = types.Int64Value(metricsRetentionDays5m)
stripedMetricsRetentionDays1h := strings.TrimSuffix(*r.MetricsRetentionTime1h, "d")
metricsRetentionDays1h, err := strconv.ParseInt(stripedMetricsRetentionDays1h, 10, 64)
if err != nil {
return fmt.Errorf("parsing metrics retention days 1h: %w", err)
}
model.MetricsRetentionDays1hDownsampling = types.Int64Value(metricsRetentionDays1h)
return nil
}
func toCreatePayload(model *Model) (*argus.CreateInstancePayload, error) {
if model == nil {
return nil, fmt.Errorf("nil model")
@ -655,6 +800,40 @@ func toCreatePayload(model *Model) (*argus.CreateInstancePayload, error) {
}, nil
}
func toUpdateMetricsStorageRetentionPayload(retentionDaysRaw, retentionDays5m, retentionDays1h *int64, resp *argus.GetMetricsStorageRetentionResponse) (*argus.UpdateMetricsStorageRetentionPayload, error) {
var retentionTimeRaw string
var retentionTime5m string
var retentionTime1h string
if resp == nil || resp.MetricsRetentionTimeRaw == nil || resp.MetricsRetentionTime5m == nil || resp.MetricsRetentionTime1h == nil {
return nil, fmt.Errorf("nil response")
}
if retentionDaysRaw == nil {
retentionTimeRaw = *resp.MetricsRetentionTimeRaw
} else {
retentionTimeRaw = fmt.Sprintf("%dd", *retentionDaysRaw)
}
if retentionDays5m == nil {
retentionTime5m = *resp.MetricsRetentionTime5m
} else {
retentionTime5m = fmt.Sprintf("%dd", *retentionDays5m)
}
if retentionDays1h == nil {
retentionTime1h = *resp.MetricsRetentionTime1h
} else {
retentionTime1h = fmt.Sprintf("%dd", *retentionDays1h)
}
return &argus.UpdateMetricsStorageRetentionPayload{
MetricsRetentionTimeRaw: &retentionTimeRaw,
MetricsRetentionTime5m: &retentionTime5m,
MetricsRetentionTime1h: &retentionTime1h,
}, nil
}
func updateACL(ctx context.Context, projectId, instanceId string, acl []string, client *argus.APIClient) error {
payload := argus.UpdateACLPayload{
Acl: utils.Ptr(acl),

View file

@ -14,11 +14,12 @@ import (
func TestMapFields(t *testing.T) {
tests := []struct {
description string
instanceResp *argus.GetInstanceResponse
listACLResp *argus.ListACLResponse
expected Model
isValid bool
description string
instanceResp *argus.GetInstanceResponse
listACLResp *argus.ListACLResponse
getMetricsRetentionResp *argus.GetMetricsStorageRetentionResponse
expected Model
isValid bool
}{
{
"default_ok",
@ -26,15 +27,23 @@ func TestMapFields(t *testing.T) {
Id: utils.Ptr("iid"),
},
&argus.ListACLResponse{},
&argus.GetMetricsStorageRetentionResponse{
MetricsRetentionTimeRaw: utils.Ptr("60d"),
MetricsRetentionTime1h: utils.Ptr("30d"),
MetricsRetentionTime5m: utils.Ptr("7d"),
},
Model{
Id: types.StringValue("pid,iid"),
ProjectId: types.StringValue("pid"),
InstanceId: types.StringValue("iid"),
PlanId: types.StringNull(),
PlanName: types.StringNull(),
Name: types.StringNull(),
Parameters: types.MapNull(types.StringType),
ACL: types.SetNull(types.StringType),
Id: types.StringValue("pid,iid"),
ProjectId: types.StringValue("pid"),
InstanceId: types.StringValue("iid"),
PlanId: types.StringNull(),
PlanName: types.StringNull(),
Name: types.StringNull(),
Parameters: types.MapNull(types.StringType),
ACL: types.SetNull(types.StringType),
MetricsRetentionDays: types.Int64Value(60),
MetricsRetentionDays1hDownsampling: types.Int64Value(30),
MetricsRetentionDays5mDownsampling: types.Int64Value(7),
},
true,
},
@ -46,6 +55,11 @@ func TestMapFields(t *testing.T) {
PlanName: utils.Ptr("plan1"),
PlanId: utils.Ptr("planId"),
Parameters: &map[string]string{"key": "value"},
Instance: &argus.InstanceSensitiveData{
MetricsRetentionTimeRaw: utils.Ptr(int64(60)),
MetricsRetentionTime1h: utils.Ptr(int64(30)),
MetricsRetentionTime5m: utils.Ptr(int64(7)),
},
},
&argus.ListACLResponse{
Acl: &[]string{
@ -53,6 +67,11 @@ func TestMapFields(t *testing.T) {
},
Message: utils.Ptr("message"),
},
&argus.GetMetricsStorageRetentionResponse{
MetricsRetentionTimeRaw: utils.Ptr("60d"),
MetricsRetentionTime1h: utils.Ptr("30d"),
MetricsRetentionTime5m: utils.Ptr("7d"),
},
Model{
Id: types.StringValue("pid,iid"),
ProjectId: types.StringValue("pid"),
@ -64,6 +83,9 @@ func TestMapFields(t *testing.T) {
ACL: types.SetValueMust(types.StringType, []attr.Value{
types.StringValue("1.1.1.1/32"),
}),
MetricsRetentionDays: types.Int64Value(60),
MetricsRetentionDays1hDownsampling: types.Int64Value(30),
MetricsRetentionDays5mDownsampling: types.Int64Value(7),
},
true,
},
@ -83,6 +105,11 @@ func TestMapFields(t *testing.T) {
},
Message: utils.Ptr("message"),
},
&argus.GetMetricsStorageRetentionResponse{
MetricsRetentionTimeRaw: utils.Ptr("60d"),
MetricsRetentionTime1h: utils.Ptr("30d"),
MetricsRetentionTime5m: utils.Ptr("7d"),
},
Model{
Id: types.StringValue("pid,iid"),
ProjectId: types.StringValue("pid"),
@ -95,6 +122,9 @@ func TestMapFields(t *testing.T) {
types.StringValue("1.1.1.1/32"),
types.StringValue("8.8.8.8/32"),
}),
MetricsRetentionDays: types.Int64Value(60),
MetricsRetentionDays1hDownsampling: types.Int64Value(30),
MetricsRetentionDays5mDownsampling: types.Int64Value(7),
},
true,
},
@ -108,15 +138,23 @@ func TestMapFields(t *testing.T) {
Acl: &[]string{},
Message: nil,
},
&argus.GetMetricsStorageRetentionResponse{
MetricsRetentionTimeRaw: utils.Ptr("60d"),
MetricsRetentionTime1h: utils.Ptr("30d"),
MetricsRetentionTime5m: utils.Ptr("7d"),
},
Model{
Id: types.StringValue("pid,iid"),
ProjectId: types.StringValue("pid"),
InstanceId: types.StringValue("iid"),
PlanId: types.StringNull(),
PlanName: types.StringNull(),
Name: types.StringNull(),
Parameters: types.MapNull(types.StringType),
ACL: types.SetNull(types.StringType),
Id: types.StringValue("pid,iid"),
ProjectId: types.StringValue("pid"),
InstanceId: types.StringValue("iid"),
PlanId: types.StringNull(),
PlanName: types.StringNull(),
Name: types.StringNull(),
Parameters: types.MapNull(types.StringType),
ACL: types.SetNull(types.StringType),
MetricsRetentionDays: types.Int64Value(60),
MetricsRetentionDays1hDownsampling: types.Int64Value(30),
MetricsRetentionDays5mDownsampling: types.Int64Value(7),
},
true,
},
@ -124,6 +162,7 @@ func TestMapFields(t *testing.T) {
"response_nil_fail",
nil,
nil,
nil,
Model{},
false,
},
@ -131,9 +170,80 @@ func TestMapFields(t *testing.T) {
"no_resource_id",
&argus.GetInstanceResponse{},
nil,
nil,
Model{},
false,
},
{
"empty metrics retention",
&argus.GetInstanceResponse{
Id: utils.Ptr("iid"),
Name: nil,
},
&argus.ListACLResponse{
Acl: &[]string{},
Message: nil,
},
&argus.GetMetricsStorageRetentionResponse{},
Model{},
false,
},
{
"nil metrics retention",
&argus.GetInstanceResponse{
Id: utils.Ptr("iid"),
Name: nil,
},
&argus.ListACLResponse{
Acl: &[]string{},
Message: nil,
},
nil,
Model{},
false,
},
{
"update metrics retention",
&argus.GetInstanceResponse{
Id: utils.Ptr("iid"),
Name: utils.Ptr("name"),
PlanName: utils.Ptr("plan1"),
PlanId: utils.Ptr("planId"),
Parameters: &map[string]string{"key": "value"},
Instance: &argus.InstanceSensitiveData{
MetricsRetentionTimeRaw: utils.Ptr(int64(30)),
MetricsRetentionTime1h: utils.Ptr(int64(15)),
MetricsRetentionTime5m: utils.Ptr(int64(10)),
},
},
&argus.ListACLResponse{
Acl: &[]string{
"1.1.1.1/32",
},
Message: utils.Ptr("message"),
},
&argus.GetMetricsStorageRetentionResponse{
MetricsRetentionTimeRaw: utils.Ptr("60d"),
MetricsRetentionTime1h: utils.Ptr("30d"),
MetricsRetentionTime5m: utils.Ptr("7d"),
},
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"),
}),
MetricsRetentionDays: types.Int64Value(60),
MetricsRetentionDays1hDownsampling: types.Int64Value(30),
MetricsRetentionDays5mDownsampling: types.Int64Value(7),
},
true,
},
}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
@ -143,10 +253,11 @@ func TestMapFields(t *testing.T) {
}
err := mapFields(context.Background(), tt.instanceResp, state)
aclErr := mapACLField(tt.listACLResp, state)
if !tt.isValid && err == nil && aclErr == nil {
metricsErr := mapMetricsRetentionField(tt.getMetricsRetentionResp, state)
if !tt.isValid && err == nil && aclErr == nil && metricsErr == nil {
t.Fatalf("Should have failed")
}
if tt.isValid && (err != nil || aclErr != nil) {
if tt.isValid && (err != nil || aclErr != nil || metricsErr != nil) {
t.Fatalf("Should not have failed: %v", err)
}
@ -278,6 +389,139 @@ func TestToPayloadUpdate(t *testing.T) {
}
}
func TestToUpdateMetricsStorageRetentionPayload(t *testing.T) {
tests := []struct {
description string
retentionDaysRaw *int64
retentionDays1h *int64
retentionDays5m *int64
getMetricsResp *argus.GetMetricsStorageRetentionResponse
expected *argus.UpdateMetricsStorageRetentionPayload
isValid bool
}{
{
"basic_ok",
utils.Ptr(int64(120)),
utils.Ptr(int64(60)),
utils.Ptr(int64(14)),
&argus.GetMetricsStorageRetentionResponse{
MetricsRetentionTimeRaw: utils.Ptr("60d"),
MetricsRetentionTime1h: utils.Ptr("30d"),
MetricsRetentionTime5m: utils.Ptr("7d"),
},
&argus.UpdateMetricsStorageRetentionPayload{
MetricsRetentionTimeRaw: utils.Ptr("120d"),
MetricsRetentionTime1h: utils.Ptr("60d"),
MetricsRetentionTime5m: utils.Ptr("14d"),
},
true,
},
{
"only_raw_given",
utils.Ptr(int64(120)),
nil,
nil,
&argus.GetMetricsStorageRetentionResponse{
MetricsRetentionTimeRaw: utils.Ptr("60d"),
MetricsRetentionTime1h: utils.Ptr("30d"),
MetricsRetentionTime5m: utils.Ptr("7d"),
},
&argus.UpdateMetricsStorageRetentionPayload{
MetricsRetentionTimeRaw: utils.Ptr("120d"),
MetricsRetentionTime1h: utils.Ptr("30d"),
MetricsRetentionTime5m: utils.Ptr("7d"),
},
true,
},
{
"only_1h_given",
nil,
utils.Ptr(int64(60)),
nil,
&argus.GetMetricsStorageRetentionResponse{
MetricsRetentionTimeRaw: utils.Ptr("60d"),
MetricsRetentionTime1h: utils.Ptr("30d"),
MetricsRetentionTime5m: utils.Ptr("7d"),
},
&argus.UpdateMetricsStorageRetentionPayload{
MetricsRetentionTimeRaw: utils.Ptr("60d"),
MetricsRetentionTime1h: utils.Ptr("60d"),
MetricsRetentionTime5m: utils.Ptr("7d"),
},
true,
},
{
"only_5m_given",
nil,
nil,
utils.Ptr(int64(14)),
&argus.GetMetricsStorageRetentionResponse{
MetricsRetentionTimeRaw: utils.Ptr("60d"),
MetricsRetentionTime1h: utils.Ptr("30d"),
MetricsRetentionTime5m: utils.Ptr("7d"),
},
&argus.UpdateMetricsStorageRetentionPayload{
MetricsRetentionTimeRaw: utils.Ptr("60d"),
MetricsRetentionTime1h: utils.Ptr("30d"),
MetricsRetentionTime5m: utils.Ptr("14d"),
},
true,
},
{
"none_given",
nil,
nil,
nil,
&argus.GetMetricsStorageRetentionResponse{
MetricsRetentionTimeRaw: utils.Ptr("60d"),
MetricsRetentionTime1h: utils.Ptr("30d"),
MetricsRetentionTime5m: utils.Ptr("7d"),
},
&argus.UpdateMetricsStorageRetentionPayload{
MetricsRetentionTimeRaw: utils.Ptr("60d"),
MetricsRetentionTime1h: utils.Ptr("30d"),
MetricsRetentionTime5m: utils.Ptr("7d"),
},
true,
},
{
"nil_response",
nil,
nil,
nil,
nil,
nil,
false,
},
{
"empty_response",
nil,
nil,
nil,
&argus.GetMetricsStorageRetentionResponse{},
nil,
false,
},
}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
output, err := toUpdateMetricsStorageRetentionPayload(tt.retentionDaysRaw, tt.retentionDays5m, tt.retentionDays1h, tt.getMetricsResp)
if !tt.isValid && err == nil {
t.Fatalf("Should have failed")
}
if tt.isValid && err != nil {
t.Fatalf("Should not have failed: %v", err)
}
if tt.isValid {
diff := cmp.Diff(output, tt.expected)
if diff != "" {
t.Fatalf("Data does not match: %s", diff)
}
}
})
}
}
func makeTestMap(t *testing.T) basetypes.MapValue {
p := make(map[string]attr.Value, 1)
p["key"] = types.StringValue("value")