Skip to content

Commit

Permalink
feat(destinations): add custom header auth and secureUrl to destinations
Browse files Browse the repository at this point in the history
commit 65be45b
Merge: 363c897 8c11550
Author: nzur-newrelic <70852759+nzur-newrelic@users.noreply.github.com>
Date:   Thu Apr 11 10:48:49 2024 +0300

    chore: merge changes on main into this branch

commit 8c11550
Author: nr-developer-toolkit <62031461+nr-developer-toolkit@users.noreply.github.com>
Date:   Tue Apr 9 12:13:24 2024 +0000

    chore(release): release v2.29.0

commit d540836
Author: Sander Blue <sblue@sanderblue.com>
Date:   Mon Apr 8 16:13:45 2024 -0500

    feat(entities): add KeyTransactionEntity types (manual update)

commit 341009e
Author: nr-developer-toolkit <62031461+nr-developer-toolkit@users.noreply.github.com>
Date:   Mon Apr 8 17:39:35 2024 +0000

    chore(release): release v2.28.1

commit 590c459
Author: Sander Blue <sblue@sanderblue.com>
Date:   Mon Apr 8 11:02:15 2024 -0500

    fix(entities): include 'reporting' if part of entity search NRQL query

commit 363c897
Merge: 8062d54 0b73c2f
Author: nzur-newrelic <nzur@newrelic.com>
Date:   Mon Apr 8 18:49:58 2024 +0300

    fix(notifications): merge latest commits

commit 8062d54
Author: nzur-newrelic <nzur@newrelic.com>
Date:   Mon Apr 8 18:49:22 2024 +0300

    feat(destinations): implement test for secureUrl

commit 0b73c2f
Author: pranav-new-relic <pnandula@newrelic.com>
Date:   Mon Apr 8 21:16:36 2024 +0530

    chore: specify tutone overrides for the pointer overridden types

commit 2f1286c
Author: nzur-newrelic <nzur@newrelic.com>
Date:   Mon Apr 8 15:44:04 2024 +0300

    fix(notifications): mistake character in comment

commit 635cff6
Author: nzur-newrelic <nzur@newrelic.com>
Date:   Mon Apr 8 15:42:23 2024 +0300

    feat(destinations): rename customheaders get function

commit 1ea31a6
Author: nzur-newrelic <nzur@newrelic.com>
Date:   Mon Apr 8 15:39:00 2024 +0300

    feat(destinations): working mutations and queries with custom headers

commit 4af170a
Author: nzur-newrelic <nzur@newrelic.com>
Date:   Mon Apr 8 14:27:55 2024 +0300

    fix(notifications): using correct input type

commit f6d16d4
Author: nzur-newrelic <nzur@newrelic.com>
Date:   Sun Apr 7 11:24:30 2024 +0300

    fix(notifications): small fixes to nerdgraph queries

commit f310e98
Author: nzur-newrelic <nzur@newrelic.com>
Date:   Sun Apr 7 11:22:56 2024 +0300

    feat(destinations): revert accidental change in notifications api

commit 83e376c
Author: nzur-newrelic <nzur@newrelic.com>
Date:   Thu Apr 4 18:19:38 2024 +0300

    feat(destinations): revert accidental change in tutone

commit eb4e78e
Author: nzur-newrelic <nzur@newrelic.com>
Date:   Thu Apr 4 17:59:17 2024 +0300

    feat(destinations): revert change on mutations and queries

commit 32e595c
Author: nzur-newrelic <nzur@newrelic.com>
Date:   Thu Apr 4 17:44:08 2024 +0300

    feat(destinations): updated nerdgraph schema

commit 396afc8
Merge: dc4ad93 a28cda5
Author: nzur-newrelic <nzur@newrelic.com>
Date:   Thu Apr 4 13:03:02 2024 +0300

    fix(notifications): merge latest commits

commit dc4ad93
Author: nzur-newrelic <nzur@newrelic.com>
Date:   Tue Mar 5 12:12:21 2024 +0200

    feat(destinations): added integration tests for custom headers

commit c1a1f2c
Author: nzur-newrelic <nzur@newrelic.com>
Date:   Tue Mar 5 12:11:44 2024 +0200

    feat(destinations): added custom headers to GQL schema

commit f5371d4
Author: nzur-newrelic <nzur@newrelic.com>
Date:   Tue Mar 5 12:10:49 2024 +0200

    feat(destinations): complete ai types

commit 961846c
Author: nzur-newrelic <nzur@newrelic.com>
Date:   Tue Mar 5 10:51:58 2024 +0200

    feat(destinations): add custom headers auth to types_ai
  • Loading branch information
pranav-new-relic committed Apr 11, 2024
1 parent 8c11550 commit 9fc45c5
Show file tree
Hide file tree
Showing 5 changed files with 405 additions and 13 deletions.
6 changes: 6 additions & 0 deletions .tutone.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1032,10 +1032,16 @@ packages:
- name: AiNotificationsDestination
- name: AiNotificationsCredentialsInput
field_type_override: "*AiNotificationsCredentialsInput"
- name: AiNotificationsSecureURLInput
field_type_override: "*AiNotificationsSecureURLInput"
- name: AiNotificationsSecureURLUpdate
field_type_override: "*AiNotificationsSecureURLUpdate"
- name: AiNotificationsAuth
field_type_override: "ai.AiNotificationsAuth"
- name: AiNotificationsError
field_type_override: "ai.AiNotificationsError"
- name: AiNotificationsCustomHeadersAuthInput
field_type_override: "*AiNotificationsCustomHeadersAuthInput"
- name: ID
field_type_override: string
skip_type_create: true
Expand Down
76 changes: 76 additions & 0 deletions pkg/ai/types_ai.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,10 @@ type AiNotificationsTokenAuth struct {
Prefix string `json:"prefix"`
}

func (x AiNotificationsTokenAuth) GetCustomHeaders() []AiNotificationsCustomHeaders {
return nil
}

func (x AiNotificationsTokenAuth) GetAccessTokenURL() string {
return ""
}
Expand Down Expand Up @@ -268,6 +272,10 @@ type AiNotificationsBasicAuth struct {
User string `json:"user"`
}

func (x AiNotificationsBasicAuth) GetCustomHeaders() []AiNotificationsCustomHeaders {
return nil
}

// GetAuthType returns a pointer to the value of AuthType from AiNotificationsBasicAuth
func (x AiNotificationsBasicAuth) GetAuthType() AiNotificationsAuthType {
return x.AuthType
Expand Down Expand Up @@ -390,6 +398,8 @@ type AiNotificationsAuth struct {
Password SecureValue `json:"password,omitempty"`
// Basic auth user
User string `json:"user,omitempty"`
// Custom headers
CustomHeaders []AiNotificationsCustomHeaders `json:"customHeaders,omitempty"`
}

func (x *AiNotificationsAuth) ImplementsAiNotificationsAuth() {}
Expand All @@ -405,8 +415,64 @@ type AiNotificationsAuthInterface interface {
GetRefreshInterval() int
GetRefreshable() bool
GetScope() string
GetCustomHeaders() []AiNotificationsCustomHeaders
}

// AiNotificationsCustomHeaders - Custom headers
type AiNotificationsCustomHeaders struct {
Key string `json:"key"`
}

// AiNotificationsCustomHeadersAuth - Custom headers based authentication
type AiNotificationsCustomHeadersAuth struct {
// Authentication Type - CustomHeaders
AuthType AiNotificationsAuthType `json:"authType"`
// Custom headers
CustomHeaders []AiNotificationsCustomHeaders `json:"customHeaders"`
}

func (x AiNotificationsCustomHeadersAuth) GetUser() string {
return ""
}

func (x AiNotificationsCustomHeadersAuth) GetPrefix() string {
return ""
}

func (x AiNotificationsCustomHeadersAuth) GetAccessTokenURL() string {
return ""
}

func (x AiNotificationsCustomHeadersAuth) GetAuthorizationURL() string {
return ""
}

func (x AiNotificationsCustomHeadersAuth) GetClientId() string {
return ""
}

func (x AiNotificationsCustomHeadersAuth) GetRefreshInterval() int {
return 0
}

func (x AiNotificationsCustomHeadersAuth) GetRefreshable() bool {
return false
}

func (x AiNotificationsCustomHeadersAuth) GetScope() string {
return ""
}

func (x AiNotificationsCustomHeadersAuth) GetAuthType() AiNotificationsAuthType {
return x.AuthType
}

func (x AiNotificationsCustomHeadersAuth) GetCustomHeaders() []AiNotificationsCustomHeaders {
return x.CustomHeaders
}

func (x AiNotificationsCustomHeadersAuth) ImplementsAiNotificationsAuth() {}

// UnmarshalAiNotificationsAuthInterface unmarshals the interface into the correct type
// based on __typename provided by GraphQL
func UnmarshalAiNotificationsAuthInterface(b []byte) (*AiNotificationsAuthInterface, error) {
Expand Down Expand Up @@ -451,6 +517,16 @@ func UnmarshalAiNotificationsAuthInterface(b []byte) (*AiNotificationsAuthInterf

var xxx AiNotificationsAuthInterface = &interfaceType

return &xxx, nil
case "AiNotificationsCustomHeadersAuth":
var interfaceType AiNotificationsCustomHeadersAuth
err = json.Unmarshal(b, &interfaceType)
if err != nil {
return nil, err
}

var xxx AiNotificationsAuthInterface = &interfaceType

return &xxx, nil
}
} else {
Expand Down
29 changes: 28 additions & 1 deletion pkg/notifications/notifications_api.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

176 changes: 176 additions & 0 deletions pkg/notifications/notifications_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,182 @@ func TestNotificationMutationDestination_FilterByName(t *testing.T) {
require.NotNil(t, deleteResult)
}

func TestNotificationMutationDestination_CustomHeaderAuth(t *testing.T) {
t.Parallel()

n := newIntegrationTestClient(t)

accountID, err := mock.GetTestAccountID()
if err != nil {
t.Skipf("%s", err)
}

// Create a destination to work with in this test
testIntegrationDestinationNameRandStr := mock.RandSeq(5)
destination := AiNotificationsDestinationInput{}
destination.Type = AiNotificationsDestinationTypeTypes.WEBHOOK
destination.Properties = []AiNotificationsPropertyInput{
{
Key: "url",
Value: "https://webhook.site/94193c01-4a81-4782-8f1b-554d5230395b",
Label: "",
DisplayValue: "",
},
}
destination.Auth = &AiNotificationsCredentialsInput{
Type: AiNotificationsAuthTypeTypes.CUSTOM_HEADERS,
CustomHeaders: &AiNotificationsCustomHeadersAuthInput{
[]AiNotificationsCustomHeaderInput{
{Key: "key1", Value: "value1"},
{Key: "key2", Value: "value2"},
{Key: "key3", Value: "value3"},
},
},
}
destination.Name = fmt.Sprintf("test-notifications-destination-%s", testIntegrationDestinationNameRandStr)

// Test: Create
createResult, err := n.AiNotificationsCreateDestination(accountID, destination)
require.NoError(t, err)
require.NotNil(t, createResult)
require.NotEmpty(t, createResult.Destination.Auth)
require.Equal(t, ai.AiNotificationsAuthType("CUSTOM_HEADERS"), createResult.Destination.Auth.AuthType)
require.Equal(t, 3, len(createResult.Destination.Auth.CustomHeaders))
require.Equal(t, "key1", createResult.Destination.Auth.CustomHeaders[0].Key)
require.Equal(t, "key2", createResult.Destination.Auth.CustomHeaders[1].Key)
require.Equal(t, "key3", createResult.Destination.Auth.CustomHeaders[2].Key)

// Test: Get Destination by id
filters := ai.AiNotificationsDestinationFilter{
ID: createResult.Destination.ID,
}
sorter := AiNotificationsDestinationSorter{}
getDestinationResult, err := n.GetDestinations(accountID, "", filters, sorter)
require.NoError(t, err)
require.NotNil(t, getDestinationResult)
assert.Equal(t, 1, getDestinationResult.TotalCount)
require.NotEmpty(t, getDestinationResult.Entities[0].GUID)
require.Equal(t, ai.AiNotificationsAuthType("CUSTOM_HEADERS"), getDestinationResult.Entities[0].Auth.AuthType)
require.Equal(t, 3, len(getDestinationResult.Entities[0].Auth.CustomHeaders))
require.Equal(t, "key1", getDestinationResult.Entities[0].Auth.CustomHeaders[0].Key)
require.Equal(t, "key2", getDestinationResult.Entities[0].Auth.CustomHeaders[1].Key)
require.Equal(t, "key3", getDestinationResult.Entities[0].Auth.CustomHeaders[2].Key)

// Test: Update Destination
updateDestination := AiNotificationsDestinationUpdate{}
updateDestination.Active = false
updateDestination.Properties = []AiNotificationsPropertyInput{
{
Key: "url",
Value: "https://webhook.site/94193c01-4a81-4782-8f1b-554d5230395b",
Label: "",
DisplayValue: "",
},
}
updateDestination.Auth = &AiNotificationsCredentialsInput{
Type: AiNotificationsAuthTypeTypes.CUSTOM_HEADERS,
CustomHeaders: &AiNotificationsCustomHeadersAuthInput{
[]AiNotificationsCustomHeaderInput{
{Key: "key1", Value: "value1"},
{Key: "key4", Value: "value4"},
},
},
}
updateDestination.Name = fmt.Sprintf("test-notifications-update-destination-%s", testIntegrationDestinationNameRandStr)

updateDestinationResult, err := n.AiNotificationsUpdateDestination(accountID, updateDestination, createResult.Destination.ID)
require.NoError(t, err)
require.NotNil(t, updateDestinationResult)
require.Equal(t, ai.AiNotificationsAuthType("CUSTOM_HEADERS"), updateDestinationResult.Destination.Auth.AuthType)
require.Equal(t, 2, len(updateDestinationResult.Destination.Auth.CustomHeaders))
require.Equal(t, "key1", updateDestinationResult.Destination.Auth.CustomHeaders[0].Key)
require.Equal(t, "key4", updateDestinationResult.Destination.Auth.CustomHeaders[1].Key)

// Test: Delete
deleteResult, err := n.AiNotificationsDeleteDestination(accountID, createResult.Destination.ID)
require.NoError(t, err)
require.NotNil(t, deleteResult)
}

func TestNotificationMutationDestination_secureUrl(t *testing.T) {
t.Parallel()

n := newIntegrationTestClient(t)

accountID, err := mock.GetTestAccountID()
if err != nil {
t.Skipf("%s", err)
}

// Create a destination to work with in this test
testIntegrationDestinationNameRandStr := mock.RandSeq(5)
destination := AiNotificationsDestinationInput{}
destination.Type = AiNotificationsDestinationTypeTypes.WEBHOOK
destination.Properties = []AiNotificationsPropertyInput{}
destination.SecureURL = &AiNotificationsSecureURLInput{
Prefix: "https://webhook.site",
SecureSuffix: "/94193c01-4a81-4782-8f1b-554d5230395b",
}
destination.Auth = &AiNotificationsCredentialsInput{
Type: AiNotificationsAuthTypeTypes.TOKEN,
Token: AiNotificationsTokenAuthInput{
Token: "Token",
Prefix: "Bearer",
},
}
destination.Name = fmt.Sprintf("test-notifications-destination-%s", testIntegrationDestinationNameRandStr)

// Test: Create
createResult, err := n.AiNotificationsCreateDestination(accountID, destination)
require.NoError(t, err)
require.NotNil(t, createResult)
require.NotNil(t, createResult.Destination.SecureURL)
require.Equal(t, createResult.Destination.SecureURL.Prefix, "https://webhook.site")
require.NotEmpty(t, createResult.Destination.Auth)
require.Equal(t, ai.AiNotificationsAuthType("TOKEN"), createResult.Destination.Auth.AuthType)

// Test: Get Destination by id
filters := ai.AiNotificationsDestinationFilter{
ID: createResult.Destination.ID,
}
sorter := AiNotificationsDestinationSorter{}
getDestinationResult, err := n.GetDestinations(accountID, "", filters, sorter)
require.NoError(t, err)
require.NotNil(t, getDestinationResult)
assert.Equal(t, 1, getDestinationResult.TotalCount)
require.NotEmpty(t, getDestinationResult.Entities[0].GUID)
require.NotNil(t, getDestinationResult.Entities[0].SecureURL)
require.Equal(t, getDestinationResult.Entities[0].SecureURL.Prefix, "https://webhook.site")

// Test: Update Destination
updateDestination := AiNotificationsDestinationUpdate{}
updateDestination.Active = false
updateDestination.Properties = []AiNotificationsPropertyInput{}
updateDestination.SecureURL = &AiNotificationsSecureURLUpdate{
Prefix: "https://webhook2.site",
SecureSuffix: "/59bb0d7a-1708-481a-a178-9161416f8ba6",
}
updateDestination.Auth = &AiNotificationsCredentialsInput{
Type: AiNotificationsAuthTypeTypes.TOKEN,
Token: AiNotificationsTokenAuthInput{
Token: "TokenUpdate",
Prefix: "BearerUpdate",
},
}
updateDestination.Name = fmt.Sprintf("test-notifications-update-destination-%s", testIntegrationDestinationNameRandStr)

updateDestinationResult, err := n.AiNotificationsUpdateDestination(accountID, updateDestination, createResult.Destination.ID)
require.NoError(t, err)
require.NotNil(t, updateDestinationResult)
require.NotNil(t, updateDestinationResult.Destination.SecureURL)
require.Equal(t, updateDestinationResult.Destination.SecureURL.Prefix, "https://webhook2.site")

// Test: Delete
deleteResult, err := n.AiNotificationsDeleteDestination(accountID, createResult.Destination.ID)
require.NoError(t, err)
require.NotNil(t, deleteResult)
}

func TestNotificationMutationChannel(t *testing.T) {
t.Parallel()

Expand Down
Loading

0 comments on commit 9fc45c5

Please sign in to comment.