From 39dc456df63c80f12980cfbe6723e4f36bdcc0ca Mon Sep 17 00:00:00 2001 From: krolik Date: Mon, 22 Apr 2024 12:19:38 +0200 Subject: [PATCH] feat: PC-12282 Introduce metadata annotations --- Makefile | 4 +- docs/resources/alert_policy.md | 1 + docs/resources/project.md | 1 + docs/resources/service.md | 1 + docs/resources/slo.md | 1 + nobl9/metadata_schema.go | 23 ++++++++++++ nobl9/resource_alert_policy.go | 9 +++++ nobl9/resource_alert_policy_test.go | 5 +++ nobl9/resource_project.go | 9 +++++ nobl9/resource_project_test.go | 5 +++ nobl9/resource_service.go | 9 +++++ nobl9/resource_service_test.go | 5 +++ nobl9/resource_slo.go | 8 ++++ nobl9/resource_slo_test.go | 57 +++++++++++++++++++++++++++++ 14 files changed, 136 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 973fc064..d67a9f26 100644 --- a/Makefile +++ b/Makefile @@ -42,9 +42,9 @@ define _print_check_step printf -- '------\n%s...\n' "${1}" endef -.PHONY: install +.PHONY: install/provider ## Install provider locally. -install: build +install/provider: build mkdir -p ~/.terraform.d/plugins/$(HOSTNAME)/$(NAMESPACE)/$(NAME)/$(VERSION)/$(OS_ARCH) mv $(BINARY) ~/.terraform.d/plugins/$(HOSTNAME)/$(NAMESPACE)/$(NAME)/$(VERSION)/$(OS_ARCH) diff --git a/docs/resources/alert_policy.md b/docs/resources/alert_policy.md index 217a11cd..5d420afe 100644 --- a/docs/resources/alert_policy.md +++ b/docs/resources/alert_policy.md @@ -99,6 +99,7 @@ resource "nobl9_alert_policy" "this" { ### Optional - `alert_method` (Block List) (see [below for nested schema](#nestedblock--alert_method)) +- `annotations` (Map of String) [Metadata annotations](https://docs.nobl9.com/Features/Labels/#metadata-annotations) attached to the resource. - `cooldown` (String) An interval measured from the last time stamp when all alert policy conditions were satisfied before alert is marked as resolved - `description` (String) Optional description of the resource. Here, you can add details about who is responsible for the integration (team/owner) or the purpose of creating it. - `display_name` (String) User-friendly display name of the resource. diff --git a/docs/resources/project.md b/docs/resources/project.md index b685721a..4cbb05be 100644 --- a/docs/resources/project.md +++ b/docs/resources/project.md @@ -44,6 +44,7 @@ resource "nobl9_project" "this" { ### Optional +- `annotations` (Map of String) [Metadata annotations](https://docs.nobl9.com/Features/Labels/#metadata-annotations) attached to the resource. - `description` (String) Optional description of the resource. Here, you can add details about who is responsible for the integration (team/owner) or the purpose of creating it. - `display_name` (String) User-friendly display name of the resource. - `label` (Block List) [Labels](https://docs.nobl9.com/Features/labels/) containing a single key and a list of values. (see [below for nested schema](#nestedblock--label)) diff --git a/docs/resources/service.md b/docs/resources/service.md index c70aba8e..809e9fac 100644 --- a/docs/resources/service.md +++ b/docs/resources/service.md @@ -50,6 +50,7 @@ resource "nobl9_service" "this" { ### Optional +- `annotations` (Map of String) [Metadata annotations](https://docs.nobl9.com/Features/Labels/#metadata-annotations) attached to the resource. - `description` (String) Optional description of the resource. Here, you can add details about who is responsible for the integration (team/owner) or the purpose of creating it. - `display_name` (String) User-friendly display name of the resource. - `label` (Block List) [Labels](https://docs.nobl9.com/Features/labels/) containing a single key and a list of values. (see [below for nested schema](#nestedblock--label)) diff --git a/docs/resources/slo.md b/docs/resources/slo.md index 844968b3..a2e37d41 100644 --- a/docs/resources/slo.md +++ b/docs/resources/slo.md @@ -155,6 +155,7 @@ resource "nobl9_slo" "this" { ### Optional - `alert_policies` (List of String) Alert Policies attached to SLO. +- `annotations` (Map of String) [Metadata annotations](https://docs.nobl9.com/Features/Labels/#metadata-annotations) attached to the resource. - `anomaly_config` (Block Set, Max: 1) Configuration for Anomalies. Currently supported Anomaly Type is NoData (see [below for nested schema](#nestedblock--anomaly_config)) - `attachment` (Block List, Max: 20) (see [below for nested schema](#nestedblock--attachment)) - `attachments` (Block List, Max: 20, Deprecated) (see [below for nested schema](#nestedblock--attachments)) diff --git a/nobl9/metadata_schema.go b/nobl9/metadata_schema.go index b5c1c095..46f3e094 100644 --- a/nobl9/metadata_schema.go +++ b/nobl9/metadata_schema.go @@ -66,6 +66,18 @@ func schemaLabels() *schema.Schema { } } +func schemaAnnotations() *schema.Schema { + return &schema.Schema{ + Type: schema.TypeMap, + Optional: true, + Description: "[Metadata annotations](https://docs.nobl9.com/Features/Labels/#metadata-annotations) attached to the resource.", + Elem: &schema.Schema{ + Type: schema.TypeString, + Optional: true, + }, + } +} + func validateNotEmptyString(variableName string) func(interface{}, string) ([]string, []error) { return func(valueRaw interface{}, _ string) ([]string, []error) { if valueRaw.(string) == "" { @@ -182,6 +194,17 @@ func getMarshaledLabels(d *schema.ResourceData) (v1alpha.Labels, diag.Diagnostic return marshalLabels(labels) } +func getMarshaledAnnotations(d *schema.ResourceData) v1alpha.MetadataAnnotations { + rawAnnotations := d.Get("annotations").(map[string]interface{}) + annotations := make(map[string]string, len(rawAnnotations)) + + for k, v := range rawAnnotations { + annotations[k] = v.(string) + } + + return annotations +} + func marshalLabels(labels []interface{}) (v1alpha.Labels, diag.Diagnostics) { var diags diag.Diagnostics labelsResult := make(v1alpha.Labels, len(labels)) diff --git a/nobl9/resource_alert_policy.go b/nobl9/resource_alert_policy.go index bd16fd52..22673ad6 100644 --- a/nobl9/resource_alert_policy.go +++ b/nobl9/resource_alert_policy.go @@ -19,6 +19,7 @@ func resourceAlertPolicy() *schema.Resource { "display_name": schemaDisplayName(), "project": schemaProject(), "description": schemaDescription(), + "annotations": schemaAnnotations(), "severity": { Type: schema.TypeString, Required: true, @@ -144,12 +145,15 @@ func marshalAlertPolicy(d *schema.ResourceData) (*v1alphaAlertPolicy.AlertPolicy return nil, diags } + annotationsMarshaled := getMarshaledAnnotations(d) + alertPolicy := v1alphaAlertPolicy.New( v1alphaAlertPolicy.Metadata{ Name: d.Get("name").(string), DisplayName: displayName, Project: d.Get("project").(string), Labels: labelsMarshaled, + Annotations: annotationsMarshaled, }, v1alphaAlertPolicy.Spec{ Description: d.Get("description").(string), @@ -236,6 +240,11 @@ func unmarshalAlertPolicy(d *schema.ResourceData, objects []v1alphaAlertPolicy.A diags = appendError(diags, err) } + if len(metadata.Annotations) > 0 { + err = d.Set("annotations", metadata.Annotations) + diags = appendError(diags, err) + } + spec := object.Spec err = d.Set("description", spec.Description) diags = appendError(diags, err) diff --git a/nobl9/resource_alert_policy_test.go b/nobl9/resource_alert_policy_test.go index f293f351..8a8c425c 100644 --- a/nobl9/resource_alert_policy_test.go +++ b/nobl9/resource_alert_policy_test.go @@ -72,6 +72,11 @@ resource "nobl9_alert_policy" "%s" { project = "%s" severity = "Medium" + annotations = { + env = "development" + name = "example annotation" + } + condition { measurement = "burnedBudget" value = 0.9 diff --git a/nobl9/resource_project.go b/nobl9/resource_project.go index cc3f17ff..7a594c87 100644 --- a/nobl9/resource_project.go +++ b/nobl9/resource_project.go @@ -18,6 +18,7 @@ func resourceProject() *schema.Resource { "display_name": schemaDisplayName(), "description": schemaDescription(), "label": schemaLabels(), + "annotations": schemaAnnotations(), }, CreateContext: resourceProjectApply, UpdateContext: resourceProjectApply, @@ -36,11 +37,14 @@ func marshalProject(d *schema.ResourceData) (*v1alphaProject.Project, diag.Diagn return nil, diags } + annotationsMarshaled := getMarshaledAnnotations(d) + project := v1alphaProject.New( v1alphaProject.Metadata{ Name: d.Get("name").(string), DisplayName: d.Get("display_name").(string), Labels: labelsMarshaled, + Annotations: annotationsMarshaled, }, v1alphaProject.Spec{ Description: d.Get("description").(string), @@ -68,6 +72,11 @@ func unmarshalProject(d *schema.ResourceData, objects []v1alphaProject.Project) diags = appendError(diags, err) } + if len(metadata.Annotations) > 0 { + err = d.Set("annotations", metadata.Annotations) + diags = appendError(diags, err) + } + spec := object.Spec err = d.Set("description", spec.Description) diags = appendError(diags, err) diff --git a/nobl9/resource_project_test.go b/nobl9/resource_project_test.go index 22283b8c..66fc1a1c 100644 --- a/nobl9/resource_project_test.go +++ b/nobl9/resource_project_test.go @@ -81,6 +81,11 @@ resource "nobl9_project" "%s" { key = "env" values = ["dev", "staging", "prod"] } + + annotations = { + env = "development" + name = "example annotation" + } } `, name, name, name) } diff --git a/nobl9/resource_service.go b/nobl9/resource_service.go index 42e4e9db..a442e714 100644 --- a/nobl9/resource_service.go +++ b/nobl9/resource_service.go @@ -19,6 +19,7 @@ func resourceService() *schema.Resource { "project": schemaProject(), "description": schemaDescription(), "label": schemaLabels(), + "annotations": schemaAnnotations(), "status": { Type: schema.TypeMap, Computed: true, @@ -50,12 +51,15 @@ func marshalService(d *schema.ResourceData) (*v1alphaService.Service, diag.Diagn return nil, diags } + annotationsMarshaled := getMarshaledAnnotations(d) + service := v1alphaService.New( v1alphaService.Metadata{ Name: d.Get("name").(string), DisplayName: displayName, Project: d.Get("project").(string), Labels: labelsMarshaled, + Annotations: annotationsMarshaled, }, v1alphaService.Spec{ Description: d.Get("description").(string), @@ -84,6 +88,11 @@ func unmarshalService(d *schema.ResourceData, objects []v1alphaService.Service) diags = appendError(diags, err) } + if len(metadata.Annotations) > 0 { + err = d.Set("annotations", metadata.Annotations) + diags = appendError(diags, err) + } + status := map[string]int{"sloCount": object.Status.SloCount} err = d.Set("status", status) diags = appendError(diags, err) diff --git a/nobl9/resource_service_test.go b/nobl9/resource_service_test.go index 0db64b2f..f09ac86b 100644 --- a/nobl9/resource_service_test.go +++ b/nobl9/resource_service_test.go @@ -40,6 +40,11 @@ resource "nobl9_service" "%s" { key = "dev" values = ["dev", "staging", "prod"] } + + annotations = { + env = "development" + name = "example annotation" + } } `, name, name, name, testProject) } diff --git a/nobl9/resource_slo.go b/nobl9/resource_slo.go index 2dcb923a..85b6841b 100644 --- a/nobl9/resource_slo.go +++ b/nobl9/resource_slo.go @@ -252,6 +252,7 @@ func schemaSLO() map[string]*schema.Schema { "project": schemaProject(), "description": schemaDescription(), "label": schemaLabels(), + "annotations": schemaAnnotations(), "composite": { Type: schema.TypeSet, Optional: true, @@ -573,6 +574,7 @@ func marshalSLO(d *schema.ResourceData) (*v1alphaSLO.SLO, diag.Diagnostics) { if diags.HasError() { return nil, diags } + annotationsMarshaled := getMarshaledAnnotations(d) slo := v1alphaSLO.New( v1alphaSLO.Metadata{ @@ -580,6 +582,7 @@ func marshalSLO(d *schema.ResourceData) (*v1alphaSLO.SLO, diag.Diagnostics) { DisplayName: displayName, Project: d.Get("project").(string), Labels: labelsMarshaled, + Annotations: annotationsMarshaled, }, v1alphaSLO.Spec{ Description: d.Get("description").(string), @@ -858,6 +861,11 @@ func unmarshalSLO(d *schema.ResourceData, objects []v1alphaSLO.SLO) diag.Diagnos diags = appendError(diags, err) } + if len(metadata.Annotations) > 0 { + err = d.Set("annotations", metadata.Annotations) + diags = appendError(diags, err) + } + spec := object.Spec err = d.Set("alert_policies", spec.AlertPolicies) diff --git a/nobl9/resource_slo_test.go b/nobl9/resource_slo_test.go index 824018f9..11e7c784 100644 --- a/nobl9/resource_slo_test.go +++ b/nobl9/resource_slo_test.go @@ -63,6 +63,7 @@ func TestAcc_Nobl9SLO(t *testing.T) { {"test-anomaly-config-different-project", testAnomalyConfigNoDataDifferentProject}, {"test-max-one-primary-objective", testMaxOnePrimaryObjective}, {"test-no-primary-objective", testNoPrimaryObjective}, + {"test-metadata-annotations", testMetadataAnnotations}, } for _, tc := range cases { @@ -3387,3 +3388,59 @@ resource "nobl9_slo" "%s" { } `, name, name, serviceName, testProject, agentName, testProject) } + +func testMetadataAnnotations(name string) string { + var serviceName = name + "-tf-service" + var agentName = name + "-tf-agent" + + config := testService(serviceName) + + testThousandEyesAgent(agentName) + ` + + resource "nobl9_slo" ":name" { + name = ":name" + display_name = ":name" + project = ":project" + service = nobl9_service.:serviceName.name + + annotations = { + env = "development" + name = "example annotation" + } + + budgeting_method = "Occurrences" + + objective { + display_name = "obj1" + name = "tf-objective-1" + target = 0.7 + value = 1 + op = "lt" + raw_metric { + query { + thousandeyes { + test_id = 11 + } + } + } + } + + time_window { + count = 10 + is_rolling = true + unit = "Minute" + } + + indicator { + name = nobl9_agent.:agentName.name + project = ":project" + kind = "Agent" + } + } +` + config = strings.ReplaceAll(config, ":name", name) + config = strings.ReplaceAll(config, ":serviceName", serviceName) + config = strings.ReplaceAll(config, ":agentName", agentName) + config = strings.ReplaceAll(config, ":project", testProject) + + return config +}