From 2495dbfe6b92f7b43c537685a3b9f49357ae7722 Mon Sep 17 00:00:00 2001 From: Alfredo Molero Date: Tue, 24 Oct 2023 12:21:48 -0400 Subject: [PATCH 1/3] feat(changetracking): Support custom attributes JSON --- .tutone.yml | 2 + pkg/changetracking/changetracking_api.go | 13 +++- .../changetracking_api_integration_test.go | 19 +++-- pkg/changetracking/changetracking_types.go | 37 --------- pkg/changetracking/types.go | 77 +++++++++++++++++-- 5 files changed, 96 insertions(+), 52 deletions(-) delete mode 100644 pkg/changetracking/changetracking_types.go diff --git a/.tutone.yml b/.tutone.yml index 6cf685d39..30025a7c9 100644 --- a/.tutone.yml +++ b/.tutone.yml @@ -392,6 +392,8 @@ packages: - name: EntityGuid field_type_override: common.EntityGUID skip_type_create: true + - name: ChangeTrackingRawCustomAttributesMap + create_as: "map[string]interface{}" mutations: - name: changeTrackingCreateDeployment max_query_field_depth: 2 diff --git a/pkg/changetracking/changetracking_api.go b/pkg/changetracking/changetracking_api.go index 270d5cc49..44415bc88 100644 --- a/pkg/changetracking/changetracking_api.go +++ b/pkg/changetracking/changetracking_api.go @@ -3,24 +3,28 @@ package changetracking import "context" -// Creates a new deployment record in NRDB and associated deployment marker. +// Creates a new deployment record in NRDB and its associated deployment marker. func (a *Changetracking) ChangeTrackingCreateDeployment( + dataHandlingRules ChangeTrackingDataHandlingRules, deployment ChangeTrackingDeploymentInput, ) (*ChangeTrackingDeployment, error) { return a.ChangeTrackingCreateDeploymentWithContext(context.Background(), + dataHandlingRules, deployment, ) } -// Creates a new deployment record in NRDB and associated deployment marker. +// Creates a new deployment record in NRDB and its associated deployment marker. func (a *Changetracking) ChangeTrackingCreateDeploymentWithContext( ctx context.Context, + dataHandlingRules ChangeTrackingDataHandlingRules, deployment ChangeTrackingDeploymentInput, ) (*ChangeTrackingDeployment, error) { resp := ChangeTrackingCreateDeploymentQueryResponse{} vars := map[string]interface{}{ - "deployment": deployment, + "dataHandlingRules": dataHandlingRules, + "deployment": deployment, } if err := a.client.NerdGraphQueryWithContext(ctx, ChangeTrackingCreateDeploymentMutation, vars, &resp); err != nil { @@ -35,12 +39,15 @@ type ChangeTrackingCreateDeploymentQueryResponse struct { } const ChangeTrackingCreateDeploymentMutation = `mutation( + $dataHandlingRules: ChangeTrackingDataHandlingRules, $deployment: ChangeTrackingDeploymentInput!, ) { changeTrackingCreateDeployment( + dataHandlingRules: $dataHandlingRules, deployment: $deployment, ) { changelog commit + customAttributes deepLink deploymentId deploymentType diff --git a/pkg/changetracking/changetracking_api_integration_test.go b/pkg/changetracking/changetracking_api_integration_test.go index f32f9458f..cfe669487 100644 --- a/pkg/changetracking/changetracking_api_integration_test.go +++ b/pkg/changetracking/changetracking_api_integration_test.go @@ -4,6 +4,8 @@ package changetracking import ( + "encoding/json" + "log" "testing" "time" @@ -19,15 +21,22 @@ func TestChangeTrackingCreateDeployment_Basic(t *testing.T) { a := newIntegrationTestClient(t) - var customAttributes = map[string]string{ - "test": "123", - "test2": "456", + var customAttributes = map[string]interface{}{ + "a": 1, + "b": "two", + "c": 1.5, + "d": true, + } + attrs := make(map[string]interface{}) + err := json.Unmarshal([]byte(customAttributes), &attrs) + if err != nil { + log.Fatal(err) } input := ChangeTrackingDeploymentInput{ Changelog: "test", Commit: "12345a", - CustomAttributes: &customAttributes, + CustomAttributes: attrs, DeepLink: "newrelic-client-go", DeploymentType: ChangeTrackingDeploymentTypeTypes.BASIC, Description: "This is a test description", @@ -38,7 +47,7 @@ func TestChangeTrackingCreateDeployment_Basic(t *testing.T) { Version: "0.0.1", } - res, err := a.ChangeTrackingCreateDeployment(input) + res, err := a.ChangeTrackingCreateDeployment([]ChangeTrackingValidationFlag{ChangeTrackingValidationFlagTypes.FAIL_ON_FIELD_LENGTH}, input) require.NoError(t, err) require.NotNil(t, res) diff --git a/pkg/changetracking/changetracking_types.go b/pkg/changetracking/changetracking_types.go deleted file mode 100644 index 64877a81c..000000000 --- a/pkg/changetracking/changetracking_types.go +++ /dev/null @@ -1,37 +0,0 @@ -package changetracking - -import ( - "github.com/newrelic/newrelic-client-go/v2/pkg/common" - "github.com/newrelic/newrelic-client-go/v2/pkg/nrtime" -) - -/* -Since we can't yet generate the CustomAttributes type with Tutone, -defer ChangeTrackingDeploymentInput placement into types.go until CustomAttributes GA. -*/ - -// ChangeTrackingDeploymentInput - A deployment. -type ChangeTrackingDeploymentInput struct { - // A URL for the changelog or list of changes if not linkable. - Changelog string `json:"changelog,omitempty"` - // The commit identifier, for example, a Git commit SHA. - Commit string `json:"commit,omitempty"` - // A list of key:value attribute pairs - CustomAttributes *map[string]string `json:"customAttributes,omitempty"` - // A link back to the system generating the deployment. - DeepLink string `json:"deepLink,omitempty"` - // The type of deployment, for example, ‘Blue green’ or ‘Rolling’. - DeploymentType ChangeTrackingDeploymentType `json:"deploymentType,omitempty"` - // A description of the deployment. - Description string `json:"description,omitempty"` - // The NR1 entity that was deployed. - EntityGUID common.EntityGUID `json:"entityGuid"` - // String that can be used to correlate two or more events. - GroupId string `json:"groupId,omitempty"` - // The start time of the deployment, the number of milliseconds since the Unix epoch. Defaults to now - Timestamp nrtime.EpochMilliseconds `json:"timestamp,omitempty"` - // Username of the deployer or bot. - User string `json:"user,omitempty"` - // The version of the deployed software, for example, something like v1.1 - Version string `json:"version"` -} diff --git a/pkg/changetracking/types.go b/pkg/changetracking/types.go index 4b23ca6d2..587b89651 100644 --- a/pkg/changetracking/types.go +++ b/pkg/changetracking/types.go @@ -37,28 +37,91 @@ var ChangeTrackingDeploymentTypeTypes = struct { SHADOW: "SHADOW", } +// ChangeTrackingValidationFlag - Validation flags to determine how we handle input data. +type ChangeTrackingValidationFlag string + +var ChangeTrackingValidationFlagTypes = struct { + // Will validate all string fields to be within max size limit. An error is returned and data is not saved if any of the fields exceeds max size limit. + FAIL_ON_FIELD_LENGTH ChangeTrackingValidationFlag + // For APM entities, a call is made to the legacy New Relic v2 REST API. When this flag is set, if the call fails for any reason, an error will be returned containing the failure message. + FAIL_ON_REST_API_FAILURES ChangeTrackingValidationFlag +}{ + // Will validate all string fields to be within max size limit. An error is returned and data is not saved if any of the fields exceeds max size limit. + FAIL_ON_FIELD_LENGTH: "FAIL_ON_FIELD_LENGTH", + // For APM entities, a call is made to the legacy New Relic v2 REST API. When this flag is set, if the call fails for any reason, an error will be returned containing the failure message. + FAIL_ON_REST_API_FAILURES: "FAIL_ON_REST_API_FAILURES", +} + +// ChangeTrackingDataHandlingRules - Validation and data handling rules to be applied to deployment input data. +type ChangeTrackingDataHandlingRules struct { + // Flags for validation, for example, ‘FAIL_ON_FIELD_LENGTH’. + ValidationFlags []ChangeTrackingValidationFlag `json:"validationFlags"` +} + // ChangeTrackingDeployment - A deployment. type ChangeTrackingDeployment struct { - // A URL for the changelog or list of changes if not linkable. + // A URL to the changelog or, if not linkable, a list of changes. Changelog string `json:"changelog,omitempty"` // The commit identifier, for example, a Git commit SHA. Commit string `json:"commit,omitempty"` - // A link back to the system generating the deployment. + // Represents key-value pairs of custom attributes in JSON format. + CustomAttributes ChangeTrackingRawCustomAttributesMap `json:"customAttributes,omitempty"` + // A link to the system that generated the deployment. DeepLink string `json:"deepLink,omitempty"` - // Optional: deployment identifier. + // A unique deployment identifier. DeploymentId string `json:"deploymentId,omitempty"` // The type of deployment, for example, ‘Blue green’ or ‘Rolling’. DeploymentType ChangeTrackingDeploymentType `json:"deploymentType,omitempty"` // A description of the deployment. Description string `json:"description,omitempty"` - // The NR1 entity that was deployed. + // The NR entity that was deployed. EntityGUID common.EntityGUID `json:"entityGuid"` - // String that can be used to correlate two or more events. + // An identifier used to correlate two or more events. GroupId string `json:"groupId,omitempty"` - // The start time of the deployment, the number of milliseconds since the Unix epoch. + // The start time of the deployment as the number of milliseconds since the Unix epoch. Timestamp nrtime.EpochMilliseconds `json:"timestamp"` - // Username of the deployer or bot. + // The username of the deployer or bot. + User string `json:"user,omitempty"` + // The version of the deployed software, for example, something like v1.1. + Version string `json:"version"` +} + +// ChangeTrackingDeploymentInput - A deployment. +type ChangeTrackingDeploymentInput struct { + // A URL for the changelog or, if not linkable, a list of changes. + Changelog string `json:"changelog,omitempty"` + // The commit identifier, for example, a Git commit SHA. + Commit string `json:"commit,omitempty"` + // Represents key-value pairs of custom attributes in JSON format. Attribute values can be of type string, boolean, or numeric. + // + // **Restricted attributes names:** accountId, appID, changelog, commit, customAttributes, deepLink, deploymentType, description, entity.guid, entity.name, entity.type, entityGuid, entityName, eventType, groupId, timestamp, user, version + // + // **Restricted attribute name prefixes:** 'nr.', 'newrelic.' + // + // For more information on limitations, see [our docs](https://docs.newrelic.com/docs/change-tracking/change-tracking-graphql/) + // + // **Examples:** + // + // • {cloudVendor : "vendorName", region : "us-east-1", environment : "staging"} + // • {isProd : true, region : "us-east-1", instances: 2, deployTime : 10.5} + CustomAttributes ChangeTrackingRawCustomAttributesMap `json:"customAttributes,omitempty"` + // A URL to the system that generated the deployment. + DeepLink string `json:"deepLink,omitempty"` + // The type of deployment, for example, ‘Blue green’ or ‘Rolling’. + DeploymentType ChangeTrackingDeploymentType `json:"deploymentType,omitempty"` + // A description of the deployment. + Description string `json:"description,omitempty"` + // The NR entity that was deployed. + EntityGUID common.EntityGUID `json:"entityGuid"` + // An identifier used to correlate two or more events. + GroupId string `json:"groupId,omitempty"` + // The start time of the deployment as the number of milliseconds since the Unix epoch. Should be within the boundary of the past or future 24 hours. Defaults to now. + Timestamp nrtime.EpochMilliseconds `json:"timestamp,omitempty"` + // The username of the deployer or bot. User string `json:"user,omitempty"` // The version of the deployed software, for example, something like v1.1 Version string `json:"version"` } + +// ChangeTrackingRawCustomAttributesMap - A JSON scalar +type ChangeTrackingRawCustomAttributesMap map[string]interface{} From d69097b6d51c2a6ae1de124867b02863f3756148 Mon Sep 17 00:00:00 2001 From: Alfredo Molero Date: Tue, 24 Oct 2023 13:06:59 -0400 Subject: [PATCH 2/3] chore: fix type error --- pkg/changetracking/changetracking_api_integration_test.go | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/pkg/changetracking/changetracking_api_integration_test.go b/pkg/changetracking/changetracking_api_integration_test.go index cfe669487..8e6ef0bb8 100644 --- a/pkg/changetracking/changetracking_api_integration_test.go +++ b/pkg/changetracking/changetracking_api_integration_test.go @@ -21,12 +21,7 @@ func TestChangeTrackingCreateDeployment_Basic(t *testing.T) { a := newIntegrationTestClient(t) - var customAttributes = map[string]interface{}{ - "a": 1, - "b": "two", - "c": 1.5, - "d": true, - } + var customAttributes = `{"a":"1","b":"two","c":"1.5","d":"true"}` attrs := make(map[string]interface{}) err := json.Unmarshal([]byte(customAttributes), &attrs) if err != nil { From 3dbd2dfef105f33eeec6e975d03ee5ec0864f7ae Mon Sep 17 00:00:00 2001 From: Alfredo Molero Date: Tue, 24 Oct 2023 14:03:19 -0400 Subject: [PATCH 3/3] chore: fix type error --- .../changetracking_api_integration_test.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/pkg/changetracking/changetracking_api_integration_test.go b/pkg/changetracking/changetracking_api_integration_test.go index 8e6ef0bb8..ffb03a891 100644 --- a/pkg/changetracking/changetracking_api_integration_test.go +++ b/pkg/changetracking/changetracking_api_integration_test.go @@ -42,7 +42,10 @@ func TestChangeTrackingCreateDeployment_Basic(t *testing.T) { Version: "0.0.1", } - res, err := a.ChangeTrackingCreateDeployment([]ChangeTrackingValidationFlag{ChangeTrackingValidationFlagTypes.FAIL_ON_FIELD_LENGTH}, input) + res, err := a.ChangeTrackingCreateDeployment( + ChangeTrackingDataHandlingRules{ValidationFlags: []ChangeTrackingValidationFlag{ChangeTrackingValidationFlagTypes.FAIL_ON_FIELD_LENGTH}}, + input, + ) require.NoError(t, err) require.NotNil(t, res) @@ -67,7 +70,10 @@ func TestChangeTrackingCreateDeployment_TimestampError(t *testing.T) { Version: "0.0.1", } - res, err := a.ChangeTrackingCreateDeployment(input) + res, err := a.ChangeTrackingCreateDeployment( + ChangeTrackingDataHandlingRules{ValidationFlags: []ChangeTrackingValidationFlag{ChangeTrackingValidationFlagTypes.FAIL_ON_FIELD_LENGTH}}, + input, + ) require.Error(t, err) require.Nil(t, res) }