Skip to content

Commit 839d135

Browse files
authored
Merge branch 'main' into main
2 parents 96e9952 + fabce46 commit 839d135

12 files changed

+402
-25
lines changed

newrelic/data_source_newrelic_entity.go

+9-11
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88

99
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
1010
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
11-
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
1211
"github.com/newrelic/newrelic-client-go/v2/pkg/entities"
1312
)
1413

@@ -28,21 +27,19 @@ func dataSourceNewRelicEntity() *schema.Resource {
2827
Description: "Ignore case when searching the entity name.",
2928
},
3029
"type": {
31-
Type: schema.TypeString,
32-
Optional: true,
33-
Computed: true,
34-
Description: "The entity's type. Valid values are APPLICATION, DASHBOARD, HOST, MONITOR, and WORKLOAD.",
35-
ValidateFunc: validation.StringInSlice([]string{"APPLICATION", "DASHBOARD", "HOST", "MONITOR", "WORKLOAD"}, true),
30+
Type: schema.TypeString,
31+
Optional: true,
32+
Computed: true,
33+
Description: "The entity's type. Valid values are APPLICATION, DASHBOARD, HOST, MONITOR, SERVICE and WORKLOAD.",
3634
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
3735
return strings.EqualFold(old, new) // Case fold this attribute when diffing
3836
},
3937
},
4038
"domain": {
41-
Type: schema.TypeString,
42-
Optional: true,
43-
Computed: true,
44-
Description: "The entity's domain. Valid values are APM, BROWSER, INFRA, MOBILE, SYNTH, and VIZ. If not specified, all domains are searched.",
45-
ValidateFunc: validation.StringInSlice([]string{"APM", "BROWSER", "INFRA", "MOBILE", "SYNTH", "VIZ"}, true),
39+
Type: schema.TypeString,
40+
Optional: true,
41+
Computed: true,
42+
Description: "The entity's domain. Valid values are APM, BROWSER, INFRA, MOBILE, SYNTH, and EXT. If not specified, all domains are searched.",
4643
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
4744
return strings.EqualFold(old, new) // Case fold this attribute when diffing
4845
},
@@ -109,6 +106,7 @@ func dataSourceNewRelicEntityRead(ctx context.Context, d *schema.ResourceData, m
109106
}
110107

111108
entityResults, err := client.Entities.GetEntitySearchWithContext(ctx, entities.EntitySearchOptions{}, "", params, []entities.EntitySearchSortCriteria{})
109+
112110
if err != nil {
113111
return diag.FromErr(err)
114112
}

newrelic/data_source_newrelic_entity_integration_test.go

+68
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,36 @@ func TestAccNewRelicEntityData_IgnoreCase(t *testing.T) {
6262
})
6363
}
6464

65+
func TestAccNewRelicEntityData_TypeFail(t *testing.T) {
66+
resource.ParallelTest(t, resource.TestCase{
67+
PreCheck: func() {
68+
testAccPreCheck(t)
69+
},
70+
Providers: testAccProviders,
71+
Steps: []resource.TestStep{
72+
{
73+
Config: testAccNewRelicEntityDataConfig_InvalidType(strings.ToUpper(testAccExpectedApplicationName), testAccountID),
74+
ExpectError: regexp.MustCompile("Argument \"queryBuilder\""),
75+
},
76+
},
77+
})
78+
}
79+
80+
func TestAccNewRelicEntityData_DomainFail(t *testing.T) {
81+
resource.ParallelTest(t, resource.TestCase{
82+
PreCheck: func() {
83+
testAccPreCheck(t)
84+
},
85+
Providers: testAccProviders,
86+
Steps: []resource.TestStep{
87+
{
88+
Config: testAccNewRelicEntityDataConfig_InvalidDomain(strings.ToUpper(testAccExpectedApplicationName), testAccountID),
89+
ExpectError: regexp.MustCompile("Argument \"queryBuilder\""),
90+
},
91+
},
92+
})
93+
}
94+
6595
func testAccCheckNewRelicEntityDataExists(t *testing.T, n string, appName string) resource.TestCheckFunc {
6696
return func(s *terraform.State) error {
6797
r := s.RootModule().Resources[n]
@@ -117,3 +147,41 @@ data "newrelic_entity" "entity" {
117147
}
118148
`, name, accountId)
119149
}
150+
151+
// The test entity for this data source is created in provider_test.go
152+
func testAccNewRelicEntityDataConfig_InvalidType(name string, accountId int) string {
153+
return fmt.Sprintf(`
154+
data "newrelic_entity" "entity" {
155+
name = "%s"
156+
type = "app"
157+
domain = "apm"
158+
tag {
159+
key = "accountId"
160+
value = "%d"
161+
}
162+
tag {
163+
key = "account"
164+
value = "New Relic Terraform Provider Acceptance Testing"
165+
}
166+
}
167+
`, name, accountId)
168+
}
169+
170+
// The test entity for this data source is created in provider_test.go
171+
func testAccNewRelicEntityDataConfig_InvalidDomain(name string, accountId int) string {
172+
return fmt.Sprintf(`
173+
data "newrelic_entity" "entity" {
174+
name = "%s"
175+
type = "application"
176+
domain = "VIZ"
177+
tag {
178+
key = "accountId"
179+
value = "%d"
180+
}
181+
tag {
182+
key = "account"
183+
value = "New Relic Terraform Provider Acceptance Testing"
184+
}
185+
}
186+
`, name, accountId)
187+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package newrelic
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"log"
7+
"strings"
8+
9+
"github.com/newrelic/newrelic-client-go/v2/pkg/ai"
10+
"github.com/newrelic/newrelic-client-go/v2/pkg/errors"
11+
"github.com/newrelic/newrelic-client-go/v2/pkg/notifications"
12+
13+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
14+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
15+
)
16+
17+
func dataSourceNewRelicNotificationDestination() *schema.Resource {
18+
return &schema.Resource{
19+
ReadContext: dataSourceNewRelicNotificationDestinationRead,
20+
Schema: map[string]*schema.Schema{
21+
"id": {
22+
Type: schema.TypeString,
23+
Required: true,
24+
Description: "The ID of the destination.",
25+
},
26+
"account_id": {
27+
Type: schema.TypeInt,
28+
Optional: true,
29+
Computed: true,
30+
Description: "The account ID under which to put the destination.",
31+
},
32+
"name": {
33+
Type: schema.TypeString,
34+
Optional: true,
35+
Description: "The name of the destination.",
36+
},
37+
"type": {
38+
Type: schema.TypeString,
39+
Optional: true,
40+
Description: fmt.Sprintf("The type of the destination. One of: (%s).", strings.Join(listValidNotificationsDestinationTypes(), ", ")),
41+
},
42+
"property": {
43+
Type: schema.TypeSet,
44+
Optional: true,
45+
Description: "Notification destination property type.",
46+
Elem: notificationsPropertySchema(),
47+
},
48+
"auth_basic": {
49+
Type: schema.TypeList,
50+
Optional: true,
51+
MaxItems: 1,
52+
ConflictsWith: []string{"auth_token"},
53+
Description: "Basic username and password authentication credentials.",
54+
Elem: &schema.Resource{
55+
Schema: map[string]*schema.Schema{
56+
"user": {
57+
Type: schema.TypeString,
58+
Optional: true,
59+
},
60+
},
61+
},
62+
},
63+
"auth_token": {
64+
Type: schema.TypeList,
65+
Optional: true,
66+
MaxItems: 1,
67+
ConflictsWith: []string{"auth_basic"},
68+
Description: "Token authentication credentials.",
69+
Elem: &schema.Resource{
70+
Schema: map[string]*schema.Schema{
71+
"prefix": {
72+
Type: schema.TypeString,
73+
Optional: true,
74+
},
75+
},
76+
},
77+
},
78+
"active": {
79+
Type: schema.TypeBool,
80+
Optional: true,
81+
Description: "Indicates whether the destination is active.",
82+
Default: true,
83+
},
84+
"status": {
85+
Type: schema.TypeString,
86+
Computed: true,
87+
Description: "The status of the destination.",
88+
},
89+
"last_sent": {
90+
Type: schema.TypeString,
91+
Computed: true,
92+
Description: "The last time a notification was sent.",
93+
},
94+
},
95+
}
96+
}
97+
98+
func dataSourceNewRelicNotificationDestinationRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
99+
client := meta.(*ProviderConfig).NewClient
100+
101+
log.Printf("[INFO] Reading New Relic Notification Destination")
102+
103+
providerConfig := meta.(*ProviderConfig)
104+
accountID := selectAccountID(providerConfig, d)
105+
updatedContext := updateContextWithAccountID(ctx, accountID)
106+
id := d.Id()
107+
filters := ai.AiNotificationsDestinationFilter{ID: id}
108+
sorter := notifications.AiNotificationsDestinationSorter{}
109+
110+
destinationResponse, err := client.Notifications.GetDestinationsWithContext(updatedContext, accountID, "", filters, sorter)
111+
if err != nil {
112+
if _, ok := err.(*errors.NotFound); ok {
113+
d.SetId("")
114+
return nil
115+
}
116+
117+
return diag.FromErr(err)
118+
}
119+
120+
if len(destinationResponse.Entities) == 0 {
121+
d.SetId("")
122+
return diag.FromErr(fmt.Errorf("the id '%s' does not match any New Relic notification destination", id))
123+
}
124+
125+
errors := buildAiNotificationsResponseErrors(destinationResponse.Errors)
126+
if len(errors) > 0 {
127+
return errors
128+
}
129+
130+
return diag.FromErr(flattenNotificationDestination(&destinationResponse.Entities[0], d))
131+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
//go:build integration
2+
// +build integration
3+
4+
package newrelic
5+
6+
import (
7+
"fmt"
8+
"testing"
9+
10+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
11+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
12+
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
13+
)
14+
15+
func TestAccNewRelicNotificationsDestinationDataSource_BasicAuth(t *testing.T) {
16+
resourceName := "newrelic_notifications_destination.foo"
17+
rand := acctest.RandString(5)
18+
rName := fmt.Sprintf("tf-notifications-test-%s", rand)
19+
20+
authAttr := `auth_basic {
21+
user = "username"
22+
password = "abc123"
23+
}`
24+
25+
resource.ParallelTest(t, resource.TestCase{
26+
PreCheck: func() { testAccPreCheck(t) },
27+
Providers: testAccProviders,
28+
Steps: []resource.TestStep{
29+
{
30+
Config: testAccNewRelicNotificationsDestinationDataSourceConfig(rName, authAttr),
31+
Check: resource.ComposeTestCheckFunc(
32+
testAccNewRelicNotificationsDestination("data.newrelic_notifications_destination.foo-source"),
33+
resource.TestCheckResourceAttr(resourceName, "name", rName),
34+
resource.TestCheckResourceAttr(resourceName, "type", "WEBHOOK"),
35+
),
36+
},
37+
},
38+
})
39+
}
40+
41+
func TestAccNewRelicNotificationsDestinationDataSource_TokenAuth(t *testing.T) {
42+
resourceName := "newrelic_notifications_destination.foo"
43+
rand := acctest.RandString(5)
44+
rName := fmt.Sprintf("tf-notifications-test-%s", rand)
45+
46+
authAttr := `auth_token {
47+
prefix = "testprefix"
48+
token = "abc123"
49+
}`
50+
51+
resource.ParallelTest(t, resource.TestCase{
52+
PreCheck: func() { testAccPreCheck(t) },
53+
Providers: testAccProviders,
54+
Steps: []resource.TestStep{
55+
{
56+
Config: testAccNewRelicNotificationsDestinationDataSourceConfig(rName, authAttr),
57+
Check: resource.ComposeTestCheckFunc(
58+
testAccNewRelicNotificationsDestination("data.newrelic_notifications_destination.foo-source"),
59+
resource.TestCheckResourceAttr(resourceName, "name", rName),
60+
resource.TestCheckResourceAttr(resourceName, "type", "WEBHOOK"),
61+
),
62+
},
63+
},
64+
})
65+
}
66+
67+
func testAccNewRelicNotificationsDestinationDataSourceConfig(name string, auth string) string {
68+
return fmt.Sprintf(`
69+
resource "newrelic_notification_destination" "foo" {
70+
name = "%[1]s"
71+
type = "WEBHOOK"
72+
active = true
73+
74+
property {
75+
key = "url"
76+
value = "https://webhook.site/"
77+
}
78+
79+
%[2]s
80+
}
81+
82+
data "newrelic_notification_destination" "foo-source" {
83+
id = newrelic_notification_destination.foo.id
84+
}
85+
`, name, auth)
86+
}
87+
88+
func testAccNewRelicNotificationsDestination(n string) resource.TestCheckFunc {
89+
return func(s *terraform.State) error {
90+
r := s.RootModule().Resources[n]
91+
a := r.Primary.Attributes
92+
93+
if a["id"] == "" {
94+
return fmt.Errorf("expected to get a notification destination from New Relic")
95+
}
96+
97+
return nil
98+
}
99+
}

newrelic/provider.go

+1
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ func Provider() *schema.Provider {
127127
"newrelic_cloud_account": dataSourceNewRelicCloudAccount(),
128128
"newrelic_entity": dataSourceNewRelicEntity(),
129129
"newrelic_key_transaction": dataSourceNewRelicKeyTransaction(),
130+
"newrelic_notification_destination": dataSourceNewRelicNotificationDestination(),
130131
"newrelic_obfuscation_expression": dataSourceNewRelicObfuscationExpression(),
131132
"newrelic_synthetics_private_location": dataSourceNewRelicSyntheticsPrivateLocation(),
132133
"newrelic_synthetics_secure_credential": dataSourceNewRelicSyntheticsSecureCredential(),

newrelic/resource_newrelic_notifications_channel_test.go

-1
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,6 @@ func testAccCheckNewRelicNotificationChannelExists(n string) resource.TestCheckF
313313
return err
314314
}
315315

316-
317316
if len(found.Entities) == 0 || string(found.Entities[0].ID) != rs.Primary.ID {
318317
return fmt.Errorf("channel not found: %v - %v", rs.Primary.ID, found)
319318
}

newrelic/resource_newrelic_nrql_alert_condition.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ func termSchema() *schema.Resource {
7272
"threshold_duration": {
7373
Type: schema.TypeInt,
7474
Optional: true,
75-
Description: "The duration, in seconds, that the threshold must violate in order to create an incident. Value must be a multiple of the 'aggregation_window' (which has a default of 60 seconds). Value must be within 120-3600 seconds for baseline conditions, and within 60-7200 seconds for static conditions",
75+
Description: "The duration, in seconds, that the threshold must violate in order to create an incident. Value must be a multiple of the 'aggregation_window' (which has a default of 60 seconds). Value must be within 120-86400 seconds for baseline conditions, and within 60-86400 seconds for static conditions",
7676
},
7777
},
7878
}

newrelic/resource_newrelic_nrql_alert_condition_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ func TestAccNewRelicNrqlAlertCondition_NerdGraphThresholdDurationValidationError
9999
rNameBaseline,
100100
"baseline",
101101
20,
102-
7200, // outside of accepted range [120, 3600] to test error handling
102+
86460, // outside of accepted range [120, 86400] to test error handling
103103
"static",
104104
"0",
105105
conditionalAttrBaseline,
@@ -112,7 +112,7 @@ func TestAccNewRelicNrqlAlertCondition_NerdGraphThresholdDurationValidationError
112112
rNameBaseline,
113113
"baseline",
114114
20,
115-
60, // outside of accepted range [120, 3600] to test error handling
115+
60, // outside of accepted range [120, 86400] to test error handling
116116
"static",
117117
"0",
118118
conditionalAttrBaseline,

0 commit comments

Comments
 (0)