diff --git a/newrelic/config.go b/newrelic/config.go index da96c6447..1f681f492 100644 --- a/newrelic/config.go +++ b/newrelic/config.go @@ -27,3 +27,24 @@ func (c *Config) Client() (*newrelic.Client, error) { return &client, nil } + +// ClientInfra returns a new client for accessing New Relic +func (c *Config) ClientInfra() (*newrelic.InfraClient, error) { + nrConfig := newrelic.Config{ + APIKey: c.APIKey, + Debug: logging.IsDebugOrHigher(), + BaseURL: c.APIURL, + } + + client := newrelic.NewInfraClient(nrConfig) + + log.Printf("[INFO] New Relic Infra client configured") + + return &client, nil +} + +// ProviderConfig for the custom provider +type ProviderConfig struct { + Client *newrelic.Client + InfraClient *newrelic.InfraClient +} diff --git a/newrelic/data_source_newrelic_application.go b/newrelic/data_source_newrelic_application.go index e76a78782..491d5838e 100644 --- a/newrelic/data_source_newrelic_application.go +++ b/newrelic/data_source_newrelic_application.go @@ -33,7 +33,7 @@ func dataSourceNewRelicApplication() *schema.Resource { } func dataSourceNewRelicApplicationRead(d *schema.ResourceData, meta interface{}) error { - client := meta.(*newrelic.Client) + client := meta.(*ProviderConfig).Client log.Printf("[INFO] Reading New Relic applications") diff --git a/newrelic/data_source_newrelic_key_transaction.go b/newrelic/data_source_newrelic_key_transaction.go index f5d0751f9..d1a51836b 100644 --- a/newrelic/data_source_newrelic_key_transaction.go +++ b/newrelic/data_source_newrelic_key_transaction.go @@ -23,7 +23,7 @@ func dataSourceNewRelicKeyTransaction() *schema.Resource { } func dataSourceNewRelicKeyTransactionRead(d *schema.ResourceData, meta interface{}) error { - client := meta.(*newrelic.Client) + client := meta.(*ProviderConfig).Client log.Printf("[INFO] Reading New Relic key transactions") diff --git a/newrelic/provider.go b/newrelic/provider.go index e5e610337..2772dfd78 100644 --- a/newrelic/provider.go +++ b/newrelic/provider.go @@ -1,6 +1,7 @@ package newrelic import ( + "fmt" "log" "github.com/hashicorp/terraform/helper/schema" @@ -22,6 +23,11 @@ func Provider() terraform.ResourceProvider { Optional: true, DefaultFunc: schema.EnvDefaultFunc("NEWRELIC_API_URL", "https://api.newrelic.com/v2"), }, + "infra_api_url": { + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("NEWRELIC_INFRA_API_URL", "https://infra-api.newrelic.com/v2"), + }, }, DataSourcesMap: map[string]*schema.Resource{ @@ -30,12 +36,13 @@ func Provider() terraform.ResourceProvider { }, ResourcesMap: map[string]*schema.Resource{ - "newrelic_alert_channel": resourceNewRelicAlertChannel(), - "newrelic_alert_condition": resourceNewRelicAlertCondition(), - "newrelic_nrql_alert_condition": resourceNewRelicNrqlAlertCondition(), - "newrelic_alert_policy": resourceNewRelicAlertPolicy(), - "newrelic_alert_policy_channel": resourceNewRelicAlertPolicyChannel(), - "newrelic_dashboard": resourceNewRelicDashboard(), + "newrelic_alert_channel": resourceNewRelicAlertChannel(), + "newrelic_alert_condition": resourceNewRelicAlertCondition(), + "newrelic_nrql_alert_condition": resourceNewRelicNrqlAlertCondition(), + "newrelic_infra_alert_condition": resourceNewRelicInfraAlertCondition(), + "newrelic_alert_policy": resourceNewRelicAlertPolicy(), + "newrelic_alert_policy_channel": resourceNewRelicAlertPolicyChannel(), + "newrelic_dashboard": resourceNewRelicDashboard(), }, ConfigureFunc: providerConfigure, @@ -48,5 +55,27 @@ func providerConfigure(data *schema.ResourceData) (interface{}, error) { APIURL: data.Get("api_url").(string), } log.Println("[INFO] Initializing New Relic client") - return config.Client() + + client, err := config.Client() + if err != nil { + return nil, fmt.Errorf("Error initializing New Relic client: %s", err) + } + + infraConfig := Config{ + APIKey: data.Get("api_key").(string), + APIURL: data.Get("infra_api_url").(string), + } + log.Println("[INFO] Initializing New Relic Infra client") + + clientInfra, err := infraConfig.ClientInfra() + if err != nil { + return nil, fmt.Errorf("Error initializing New Relic Infra client: %s", err) + } + + providerConfig := ProviderConfig{ + Client: client, + InfraClient: clientInfra, + } + + return &providerConfig, nil } diff --git a/newrelic/resource_newrelic_alert_channel.go b/newrelic/resource_newrelic_alert_channel.go index e8a642d2d..16b55c20d 100644 --- a/newrelic/resource_newrelic_alert_channel.go +++ b/newrelic/resource_newrelic_alert_channel.go @@ -104,7 +104,7 @@ func buildAlertChannelStruct(d *schema.ResourceData) *newrelic.AlertChannel { } func resourceNewRelicAlertChannelCreate(d *schema.ResourceData, meta interface{}) error { - client := meta.(*newrelic.Client) + client := meta.(*ProviderConfig).Client channel := buildAlertChannelStruct(d) log.Printf("[INFO] Creating New Relic alert channel %s", channel.Name) @@ -120,7 +120,7 @@ func resourceNewRelicAlertChannelCreate(d *schema.ResourceData, meta interface{} } func resourceNewRelicAlertChannelRead(d *schema.ResourceData, meta interface{}) error { - client := meta.(*newrelic.Client) + client := meta.(*ProviderConfig).Client id, err := strconv.ParseInt(d.Id(), 10, 32) if err != nil { @@ -149,7 +149,7 @@ func resourceNewRelicAlertChannelRead(d *schema.ResourceData, meta interface{}) } func resourceNewRelicAlertChannelDelete(d *schema.ResourceData, meta interface{}) error { - client := meta.(*newrelic.Client) + client := meta.(*ProviderConfig).Client id, err := strconv.ParseInt(d.Id(), 10, 32) if err != nil { diff --git a/newrelic/resource_newrelic_alert_channel_test.go b/newrelic/resource_newrelic_alert_channel_test.go index a062e26ca..acf2f1f93 100644 --- a/newrelic/resource_newrelic_alert_channel_test.go +++ b/newrelic/resource_newrelic_alert_channel_test.go @@ -8,7 +8,6 @@ import ( "github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" - newrelic "github.com/paultyng/go-newrelic/api" ) func TestAccNewRelicAlertChannel_Basic(t *testing.T) { @@ -51,7 +50,7 @@ func TestAccNewRelicAlertChannel_Basic(t *testing.T) { } func testAccCheckNewRelicAlertChannelDestroy(s *terraform.State) error { - client := testAccProvider.Meta().(*newrelic.Client) + client := testAccProvider.Meta().(*ProviderConfig).Client for _, r := range s.RootModule().Resources { if r.Type != "newrelic_alert_channel" { continue @@ -82,7 +81,7 @@ func testAccCheckNewRelicAlertChannelExists(n string) resource.TestCheckFunc { return fmt.Errorf("No channel ID is set") } - client := testAccProvider.Meta().(*newrelic.Client) + client := testAccProvider.Meta().(*ProviderConfig).Client id, err := strconv.ParseInt(rs.Primary.ID, 10, 32) if err != nil { diff --git a/newrelic/resource_newrelic_alert_condition.go b/newrelic/resource_newrelic_alert_condition.go index 6472f236b..0959e5242 100644 --- a/newrelic/resource_newrelic_alert_condition.go +++ b/newrelic/resource_newrelic_alert_condition.go @@ -278,7 +278,7 @@ func readAlertConditionStruct(condition *newrelic.AlertCondition, d *schema.Reso } func resourceNewRelicAlertConditionCreate(d *schema.ResourceData, meta interface{}) error { - client := meta.(*newrelic.Client) + client := meta.(*ProviderConfig).Client condition := buildAlertConditionStruct(d) log.Printf("[INFO] Creating New Relic alert condition %s", condition.Name) @@ -294,7 +294,7 @@ func resourceNewRelicAlertConditionCreate(d *schema.ResourceData, meta interface } func resourceNewRelicAlertConditionRead(d *schema.ResourceData, meta interface{}) error { - client := meta.(*newrelic.Client) + client := meta.(*ProviderConfig).Client log.Printf("[INFO] Reading New Relic alert condition %s", d.Id()) @@ -320,7 +320,7 @@ func resourceNewRelicAlertConditionRead(d *schema.ResourceData, meta interface{} } func resourceNewRelicAlertConditionUpdate(d *schema.ResourceData, meta interface{}) error { - client := meta.(*newrelic.Client) + client := meta.(*ProviderConfig).Client condition := buildAlertConditionStruct(d) ids, err := parseIDs(d.Id(), 2) @@ -345,7 +345,7 @@ func resourceNewRelicAlertConditionUpdate(d *schema.ResourceData, meta interface } func resourceNewRelicAlertConditionDelete(d *schema.ResourceData, meta interface{}) error { - client := meta.(*newrelic.Client) + client := meta.(*ProviderConfig).Client ids, err := parseIDs(d.Id(), 2) if err != nil { diff --git a/newrelic/resource_newrelic_alert_condition_test.go b/newrelic/resource_newrelic_alert_condition_test.go index a58765940..76089b7d6 100644 --- a/newrelic/resource_newrelic_alert_condition_test.go +++ b/newrelic/resource_newrelic_alert_condition_test.go @@ -7,7 +7,6 @@ import ( "github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" - newrelic "github.com/paultyng/go-newrelic/api" ) func TestAccNewRelicAlertCondition_Basic(t *testing.T) { @@ -111,7 +110,7 @@ func TestAccNewRelicAlertCondition_ZeroThreshold(t *testing.T) { // TODO: func_ TestAccNewRelicAlertCondition_Multi(t *testing.T) { func testAccCheckNewRelicAlertConditionDestroy(s *terraform.State) error { - client := testAccProvider.Meta().(*newrelic.Client) + client := testAccProvider.Meta().(*ProviderConfig).Client for _, r := range s.RootModule().Resources { if r.Type != "newrelic_alert_condition" { continue @@ -144,7 +143,7 @@ func testAccCheckNewRelicAlertConditionExists(n string) resource.TestCheckFunc { return fmt.Errorf("No alert condition ID is set") } - client := testAccProvider.Meta().(*newrelic.Client) + client := testAccProvider.Meta().(*ProviderConfig).Client ids, err := parseIDs(rs.Primary.ID, 2) if err != nil { diff --git a/newrelic/resource_newrelic_alert_policy.go b/newrelic/resource_newrelic_alert_policy.go index befc04cea..b5ac173d3 100644 --- a/newrelic/resource_newrelic_alert_policy.go +++ b/newrelic/resource_newrelic_alert_policy.go @@ -56,7 +56,7 @@ func buildAlertPolicyStruct(d *schema.ResourceData) *newrelic.AlertPolicy { } func resourceNewRelicAlertPolicyCreate(d *schema.ResourceData, meta interface{}) error { - client := meta.(*newrelic.Client) + client := meta.(*ProviderConfig).Client policy := buildAlertPolicyStruct(d) log.Printf("[INFO] Creating New Relic alert policy %s", policy.Name) @@ -72,7 +72,7 @@ func resourceNewRelicAlertPolicyCreate(d *schema.ResourceData, meta interface{}) } func resourceNewRelicAlertPolicyRead(d *schema.ResourceData, meta interface{}) error { - client := meta.(*newrelic.Client) + client := meta.(*ProviderConfig).Client id, err := strconv.ParseInt(d.Id(), 10, 32) if err != nil { @@ -100,7 +100,7 @@ func resourceNewRelicAlertPolicyRead(d *schema.ResourceData, meta interface{}) e } func resourceNewRelicAlertPolicyDelete(d *schema.ResourceData, meta interface{}) error { - client := meta.(*newrelic.Client) + client := meta.(*ProviderConfig).Client id, err := strconv.ParseInt(d.Id(), 10, 32) if err != nil { diff --git a/newrelic/resource_newrelic_alert_policy_channel.go b/newrelic/resource_newrelic_alert_policy_channel.go index df3eee640..d97387e17 100644 --- a/newrelic/resource_newrelic_alert_policy_channel.go +++ b/newrelic/resource_newrelic_alert_policy_channel.go @@ -48,7 +48,7 @@ func resourceNewRelicAlertPolicyChannel() *schema.Resource { } func resourceNewRelicAlertPolicyChannelCreate(d *schema.ResourceData, meta interface{}) error { - client := meta.(*newrelic.Client) + client := meta.(*ProviderConfig).Client policyID := d.Get("policy_id").(int) channelID := d.Get("channel_id").(int) @@ -75,7 +75,7 @@ func resourceNewRelicAlertPolicyChannelCreate(d *schema.ResourceData, meta inter } func resourceNewRelicAlertPolicyChannelRead(d *schema.ResourceData, meta interface{}) error { - client := meta.(*newrelic.Client) + client := meta.(*ProviderConfig).Client ids, err := parseIDs(d.Id(), 2) if err != nil { @@ -104,7 +104,7 @@ func resourceNewRelicAlertPolicyChannelRead(d *schema.ResourceData, meta interfa } func resourceNewRelicAlertPolicyChannelDelete(d *schema.ResourceData, meta interface{}) error { - client := meta.(*newrelic.Client) + client := meta.(*ProviderConfig).Client ids, err := parseIDs(d.Id(), 2) if err != nil { diff --git a/newrelic/resource_newrelic_alert_policy_channel_test.go b/newrelic/resource_newrelic_alert_policy_channel_test.go index 7caef10df..f728f8f3e 100644 --- a/newrelic/resource_newrelic_alert_policy_channel_test.go +++ b/newrelic/resource_newrelic_alert_policy_channel_test.go @@ -7,7 +7,6 @@ import ( "github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" - newrelic "github.com/paultyng/go-newrelic/api" ) func TestAccNewRelicAlertPolicyChannel_Basic(t *testing.T) { @@ -34,7 +33,7 @@ func TestAccNewRelicAlertPolicyChannel_Basic(t *testing.T) { } func testAccCheckNewRelicAlertPolicyChannelDestroy(s *terraform.State) error { - client := testAccProvider.Meta().(*newrelic.Client) + client := testAccProvider.Meta().(*ProviderConfig).Client for _, r := range s.RootModule().Resources { if r.Type != "newrelic_alert_policy_channel" { continue @@ -70,7 +69,7 @@ func testAccCheckNewRelicAlertPolicyChannelExists(n string) resource.TestCheckFu return fmt.Errorf("No resource ID is set") } - client := testAccProvider.Meta().(*newrelic.Client) + client := testAccProvider.Meta().(*ProviderConfig).Client ids, err := parseIDs(rs.Primary.ID, 2) if err != nil { diff --git a/newrelic/resource_newrelic_alert_policy_test.go b/newrelic/resource_newrelic_alert_policy_test.go index a76b452eb..366e64e6f 100644 --- a/newrelic/resource_newrelic_alert_policy_test.go +++ b/newrelic/resource_newrelic_alert_policy_test.go @@ -8,7 +8,6 @@ import ( "github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" - newrelic "github.com/paultyng/go-newrelic/api" ) func TestAccNewRelicAlertPolicy_Basic(t *testing.T) { @@ -43,7 +42,7 @@ func TestAccNewRelicAlertPolicy_Basic(t *testing.T) { } func testAccCheckNewRelicAlertPolicyDestroy(s *terraform.State) error { - client := testAccProvider.Meta().(*newrelic.Client) + client := testAccProvider.Meta().(*ProviderConfig).Client for _, r := range s.RootModule().Resources { if r.Type != "newrelic_alert_policy" { continue @@ -74,7 +73,7 @@ func testAccCheckNewRelicAlertPolicyExists(n string) resource.TestCheckFunc { return fmt.Errorf("No policy ID is set") } - client := testAccProvider.Meta().(*newrelic.Client) + client := testAccProvider.Meta().(*ProviderConfig).Client id, err := strconv.ParseInt(rs.Primary.ID, 10, 32) if err != nil { diff --git a/newrelic/resource_newrelic_dashboard.go b/newrelic/resource_newrelic_dashboard.go index fd83f3de9..697208be0 100644 --- a/newrelic/resource_newrelic_dashboard.go +++ b/newrelic/resource_newrelic_dashboard.go @@ -208,7 +208,7 @@ func flattenDashboard(dashboard *newrelic.Dashboard, d *schema.ResourceData) err } func resourceNewRelicDashboardCreate(d *schema.ResourceData, meta interface{}) error { - client := meta.(*newrelic.Client) + client := meta.(*ProviderConfig).Client dashboard := expandDashboard(d) log.Printf("[INFO] Creating New Relic dashboard: %s", dashboard.Title) @@ -223,7 +223,7 @@ func resourceNewRelicDashboardCreate(d *schema.ResourceData, meta interface{}) e } func resourceNewRelicDashboardRead(d *schema.ResourceData, meta interface{}) error { - client := meta.(*newrelic.Client) + client := meta.(*ProviderConfig).Client log.Printf("[INFO] Reading New Relic dashboard %s", d.Id()) @@ -246,7 +246,7 @@ func resourceNewRelicDashboardRead(d *schema.ResourceData, meta interface{}) err } func resourceNewRelicDashboardUpdate(d *schema.ResourceData, meta interface{}) error { - client := meta.(*newrelic.Client) + client := meta.(*ProviderConfig).Client dashboard := expandDashboard(d) id, err := strconv.Atoi(d.Id()) @@ -266,7 +266,7 @@ func resourceNewRelicDashboardUpdate(d *schema.ResourceData, meta interface{}) e } func resourceNewRelicDashboardDelete(d *schema.ResourceData, meta interface{}) error { - client := meta.(*newrelic.Client) + client := meta.(*ProviderConfig).Client id, err := strconv.Atoi(d.Id()) if err != nil { diff --git a/newrelic/resource_newrelic_dashboard_test.go b/newrelic/resource_newrelic_dashboard_test.go index 074897a67..afb404e99 100644 --- a/newrelic/resource_newrelic_dashboard_test.go +++ b/newrelic/resource_newrelic_dashboard_test.go @@ -8,7 +8,6 @@ import ( "github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" - newrelic "github.com/paultyng/go-newrelic/api" ) func TestAccNewRelicDashboard_Basic(t *testing.T) { @@ -88,7 +87,7 @@ func TestAccNewRelicDashboard_Basic(t *testing.T) { } func testAccCheckNewRelicDashboardDestroy(s *terraform.State) error { - client := testAccProvider.Meta().(*newrelic.Client) + client := testAccProvider.Meta().(*ProviderConfig).Client for _, r := range s.RootModule().Resources { if r.Type != "newrelic_dashboard" { continue @@ -119,7 +118,7 @@ func testAccCheckNewRelicDashboardExists(n string) resource.TestCheckFunc { return fmt.Errorf("No dashboard ID is set") } - client := testAccProvider.Meta().(*newrelic.Client) + client := testAccProvider.Meta().(*ProviderConfig).Client id, err := strconv.ParseInt(rs.Primary.ID, 10, 32) if err != nil { diff --git a/newrelic/resource_newrelic_infra_alert_condition.go b/newrelic/resource_newrelic_infra_alert_condition.go new file mode 100644 index 000000000..44c484626 --- /dev/null +++ b/newrelic/resource_newrelic_infra_alert_condition.go @@ -0,0 +1,312 @@ +package newrelic + +import ( + "log" + + "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform/helper/validation" + newrelic "github.com/paultyng/go-newrelic/api" +) + +var thresholdConditionTypes = map[string][]string{ + "infra_process_running": { + "duration_minutes", + "value", + }, + "infra_metric": { + "duration_minutes", + "value", + "time_function", + }, + "infra_host_not_reporting": { + "duration_minutes", + }, +} + +// thresholdSchema returns the schema to use for threshold. +// +func thresholdSchema() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "value": { + Type: schema.TypeInt, + Optional: true, + }, + "duration": { + Type: schema.TypeInt, + Required: true, + ValidateFunc: validation.IntBetween(1, 60), + }, + "time_function": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"any", "all"}, false), + }, + }, + } +} + +func resourceNewRelicInfraAlertCondition() *schema.Resource { + validThresholdConditionTypes := make([]string, 0, len(thresholdConditionTypes)) + for k := range thresholdConditionTypes { + validThresholdConditionTypes = append(validThresholdConditionTypes, k) + } + + return &schema.Resource{ + Create: resourceNewRelicInfraAlertConditionCreate, + Read: resourceNewRelicInfraAlertConditionRead, + Update: resourceNewRelicInfraAlertConditionUpdate, + Delete: resourceNewRelicInfraAlertConditionDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + Schema: map[string]*schema.Schema{ + "policy_id": { + Type: schema.TypeInt, + Required: true, + ForceNew: true, + }, + "name": { + Type: schema.TypeString, + Required: true, + }, + "enabled": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + "type": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice(validThresholdConditionTypes, false), + }, + "event": { + Type: schema.TypeString, + Optional: true, + }, + "where": { + Type: schema.TypeString, + Optional: true, + }, + "process_where": { + Type: schema.TypeString, + Optional: true, + }, + "comparison": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"above", "below", "equal"}, false), + }, + "select": { + Type: schema.TypeString, + Optional: true, + }, + "created_at": { + Type: schema.TypeInt, + Computed: true, + }, + "updated_at": { + Type: schema.TypeInt, + Computed: true, + }, + "critical": { + Type: schema.TypeList, + MinItems: 1, + MaxItems: 1, + Optional: true, + Elem: thresholdSchema(), + //TODO: ValidateFunc from thresholdConditionTypes map + }, + "warning": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + MinItems: 1, + ForceNew: true, + Elem: thresholdSchema(), + //TODO: ValidateFunc from thresholdConditionTypes map + }, + }, + } +} + +func buildInfraAlertConditionStruct(d *schema.ResourceData) *newrelic.AlertInfraCondition { + + condition := newrelic.AlertInfraCondition{ + Name: d.Get("name").(string), + Enabled: d.Get("enabled").(bool), + PolicyID: d.Get("policy_id").(int), + Event: d.Get("event").(string), + Comparison: d.Get("comparison").(string), + Select: d.Get("select").(string), + Type: d.Get("type").(string), + Critical: expandAlertThreshold(d.Get("critical")), + } + + if attr, ok := d.GetOk("warning"); ok { + condition.Warning = expandAlertThreshold(attr) + } + + if attr, ok := d.GetOk("where"); ok { + condition.Where = attr.(string) + } + + if attr, ok := d.GetOk("process_where"); ok { + condition.ProcessWhere = attr.(string) + } + + return &condition +} + +func readInfraAlertConditionStruct(condition *newrelic.AlertInfraCondition, d *schema.ResourceData) error { + ids, err := parseIDs(d.Id(), 2) + if err != nil { + return err + } + + policyID := ids[0] + + d.Set("policy_id", policyID) + d.Set("name", condition.Name) + d.Set("enabled", condition.Enabled) + d.Set("created_at", condition.CreatedAt) + d.Set("updated_at", condition.UpdatedAt) + + if condition.Where != "" { + d.Set("where", condition.Where) + } + + if condition.ProcessWhere != "" { + d.Set("process_where", condition.ProcessWhere) + } + + if err := d.Set("critical", flattenAlertThreshold(condition.Critical)); err != nil { + return err + } + + if condition.Warning != nil { + if err := d.Set("warning", flattenAlertThreshold(condition.Warning)); err != nil { + return err + } + } + + return nil +} + +func resourceNewRelicInfraAlertConditionCreate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ProviderConfig).InfraClient + condition := buildInfraAlertConditionStruct(d) + + log.Printf("[INFO] Creating New Relic Infra alert condition %s", condition.Name) + + condition, err := client.CreateAlertInfraCondition(*condition) + if err != nil { + return err + } + + d.SetId(serializeIDs([]int{condition.PolicyID, condition.ID})) + + return resourceNewRelicInfraAlertConditionRead(d, meta) +} + +func resourceNewRelicInfraAlertConditionRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ProviderConfig).InfraClient + + log.Printf("[INFO] Reading New Relic Infra alert condition %s", d.Id()) + + ids, err := parseIDs(d.Id(), 2) + if err != nil { + return err + } + + policyID := ids[0] + id := ids[1] + + condition, err := client.GetAlertInfraCondition(policyID, id) + if err != nil { + if err == newrelic.ErrNotFound { + d.SetId("") + return nil + } + + return err + } + + return readInfraAlertConditionStruct(condition, d) +} + +func resourceNewRelicInfraAlertConditionUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ProviderConfig).InfraClient + condition := buildInfraAlertConditionStruct(d) + + ids, err := parseIDs(d.Id(), 2) + if err != nil { + return err + } + + policyID := ids[0] + id := ids[1] + + condition.PolicyID = policyID + condition.ID = id + + log.Printf("[INFO] Updating New Relic Infra alert condition %d", id) + + _, err = client.UpdateAlertInfraCondition(*condition) + if err != nil { + return err + } + + return resourceNewRelicInfraAlertConditionRead(d, meta) +} + +func resourceNewRelicInfraAlertConditionDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ProviderConfig).InfraClient + + ids, err := parseIDs(d.Id(), 2) + if err != nil { + return err + } + + policyID := ids[0] + id := ids[1] + + log.Printf("[INFO] Deleting New Relic Infra alert condition %d", id) + + if err := client.DeleteAlertInfraCondition(policyID, id); err != nil { + return err + } + + d.SetId("") + + return nil +} + +func expandAlertThreshold(v interface{}) *newrelic.AlertInfraThreshold { + rah := v.([]interface{})[0].(map[string]interface{}) + + alertInfraThreshold := &newrelic.AlertInfraThreshold{ + Duration: rah["duration"].(int), + } + + if val, ok := rah["value"]; ok { + alertInfraThreshold.Value = val.(int) + } + + if val, ok := rah["time_function"]; ok { + alertInfraThreshold.Function = val.(string) + } + + return alertInfraThreshold +} + +func flattenAlertThreshold(v *newrelic.AlertInfraThreshold) []interface{} { + alertInfraThreshold := map[string]interface{}{ + "duration": v.Duration, + "value": v.Value, + "time_function": v.Function, + } + + return []interface{}{alertInfraThreshold} +} diff --git a/newrelic/resource_newrelic_infra_alert_condition_test.go b/newrelic/resource_newrelic_infra_alert_condition_test.go new file mode 100644 index 000000000..ccc535cb2 --- /dev/null +++ b/newrelic/resource_newrelic_infra_alert_condition_test.go @@ -0,0 +1,297 @@ +package newrelic + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccNewRelicInfraAlertCondition_Basic(t *testing.T) { + rName := acctest.RandString(5) + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckNewRelicInfraAlertConditionDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckNewRelicInfraAlertConditionConfig(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckNewRelicInfraAlertConditionExists("newrelic_infra_alert_condition.foo"), + resource.TestCheckResourceAttr( + "newrelic_infra_alert_condition.foo", "name", fmt.Sprintf("tf-test-%s", rName)), + resource.TestCheckResourceAttr( + "newrelic_infra_alert_condition.foo", "critical.0.duration", "10"), + resource.TestCheckNoResourceAttr( + "newrelic_infra_alert_condition.foo", "warning"), + ), + }, + resource.TestStep{ + Config: testAccCheckNewRelicInfraAlertConditionConfigUpdated(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckNewRelicInfraAlertConditionExists("newrelic_infra_alert_condition.foo"), + resource.TestCheckResourceAttr( + "newrelic_infra_alert_condition.foo", "name", fmt.Sprintf("tf-test-updated-%s", rName)), + ), + }, + }, + }) +} + +func TestAccNewRelicInfraAlertCondition_Where(t *testing.T) { + rName := acctest.RandString(5) + whereClause := "(`hostname` LIKE '%cassandra%')" + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckNewRelicInfraAlertConditionDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckNewRelicInfraAlertConditionConfigWithWhere(rName, whereClause), + Check: resource.ComposeTestCheckFunc( + testAccCheckNewRelicInfraAlertConditionExists("newrelic_infra_alert_condition.foo"), + resource.TestCheckResourceAttr( + "newrelic_infra_alert_condition.foo", "name", fmt.Sprintf("tf-test-%s", rName)), + resource.TestCheckResourceAttr( + "newrelic_infra_alert_condition.foo", "critical.0.duration", "10"), + resource.TestCheckResourceAttr( + "newrelic_infra_alert_condition.foo", "critical.0.value", "0"), + resource.TestCheckResourceAttr( + "newrelic_infra_alert_condition.foo", "where", whereClause), + resource.TestCheckResourceAttr( + "newrelic_infra_alert_condition.foo", "process_where", "commandName = 'java'"), + resource.TestCheckResourceAttr( + "newrelic_infra_alert_condition.foo", "comparison", "equal"), + ), + }, + }, + }) +} + +func TestAccNewRelicInfraAlertCondition_Thresholds(t *testing.T) { + rName := acctest.RandString(5) + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckNewRelicInfraAlertConditionDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckNewRelicInfraAlertConditionConfigWithThreshold(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckNewRelicInfraAlertConditionExists("newrelic_infra_alert_condition.foo"), + resource.TestCheckResourceAttr( + "newrelic_infra_alert_condition.foo", "name", fmt.Sprintf("tf-test-%s", rName)), + resource.TestCheckResourceAttr( + "newrelic_infra_alert_condition.foo", "critical.0.duration", "10"), + resource.TestCheckResourceAttr( + "newrelic_infra_alert_condition.foo", "critical.0.value", "10"), + resource.TestCheckResourceAttr( + "newrelic_infra_alert_condition.foo", "critical.0.time_function", "any"), + resource.TestCheckResourceAttr( + "newrelic_infra_alert_condition.foo", "warning.0.value", "20"), + ), + }, + resource.TestStep{ + Config: testAccCheckNewRelicInfraAlertConditionConfigWithThresholdUpdated(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckNewRelicInfraAlertConditionExists("newrelic_infra_alert_condition.foo"), + resource.TestCheckResourceAttr( + "newrelic_infra_alert_condition.foo", "name", fmt.Sprintf("tf-test-%s", rName)), + resource.TestCheckResourceAttr( + "newrelic_infra_alert_condition.foo", "critical.0.duration", "20"), + resource.TestCheckResourceAttr( + "newrelic_infra_alert_condition.foo", "critical.0.value", "15"), + resource.TestCheckResourceAttr( + "newrelic_infra_alert_condition.foo", "critical.0.time_function", "all"), + resource.TestCheckNoResourceAttr( + "newrelic_infra_alert_condition.foo", "warning"), + ), + }, + }, + }) +} + +func testAccCheckNewRelicInfraAlertConditionDestroy(s *terraform.State) error { + client := testAccProvider.Meta().(*ProviderConfig).InfraClient + for _, r := range s.RootModule().Resources { + if r.Type != "newrelic_infra_alert_condition" { + continue + } + + ids, err := parseIDs(r.Primary.ID, 2) + if err != nil { + return err + } + + policyID := ids[0] + id := ids[1] + + _, err = client.GetAlertInfraCondition(policyID, id) + if err == nil { + return fmt.Errorf("Infra Alert condition still exists") + } + + } + return nil +} + +func testAccCheckNewRelicInfraAlertConditionExists(n string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + if rs.Primary.ID == "" { + return fmt.Errorf("No alert condition ID is set") + } + + client := testAccProvider.Meta().(*ProviderConfig).InfraClient + + ids, err := parseIDs(rs.Primary.ID, 2) + if err != nil { + return err + } + + policyID := ids[0] + id := ids[1] + + found, err := client.GetAlertInfraCondition(policyID, id) + if err != nil { + return err + } + + if found.ID != id { + return fmt.Errorf("Alert condition not found: %v - %v", id, found) + } + + return nil + } +} + +func testAccCheckNewRelicInfraAlertConditionConfig(rName string) string { + return fmt.Sprintf(` + +resource "newrelic_alert_policy" "foo" { + name = "tf-test-%[1]s" +} + +resource "newrelic_infra_alert_condition" "foo" { + policy_id = "${newrelic_alert_policy.foo.id}" + + name = "tf-test-%[1]s" + type = "infra_metric" + event = "StorageSample" + select = "diskFreePercent" + comparison = "below" + + critical { + duration = 10 + value = 10 + time_function = "any" + } +} +`, rName) +} + +func testAccCheckNewRelicInfraAlertConditionConfigUpdated(rName string) string { + return fmt.Sprintf(` +resource "newrelic_alert_policy" "foo" { + name = "tf-test-%[1]s" +} + +resource "newrelic_infra_alert_condition" "foo" { + policy_id = "${newrelic_alert_policy.foo.id}" + + name = "tf-test-updated-%[1]s" + type = "infra_metric" + event = "StorageSample" + select = "diskFreePercent" + comparison = "below" + + critical { + duration = 10 + value = 10 + time_function = "any" + } +} +`, rName) +} + +func testAccCheckNewRelicInfraAlertConditionConfigWithThreshold(rName string) string { + return fmt.Sprintf(` +resource "newrelic_alert_policy" "foo" { + name = "tf-test-%[1]s" +} + +resource "newrelic_infra_alert_condition" "foo" { + policy_id = "${newrelic_alert_policy.foo.id}" + + name = "tf-test-%[1]s" + type = "infra_metric" + event = "StorageSample" + select = "diskFreePercent" + comparison = "below" + + critical { + duration = 10 + value = 10 + time_function = "any" + } + + warning { + duration = 10 + value = 20 + time_function = "any" + } +} +`, rName) +} + +func testAccCheckNewRelicInfraAlertConditionConfigWithThresholdUpdated(rName string) string { + return fmt.Sprintf(` +resource "newrelic_alert_policy" "foo" { + name = "tf-test-%[1]s" +} + +resource "newrelic_infra_alert_condition" "foo" { + policy_id = "${newrelic_alert_policy.foo.id}" + + name = "tf-test-%[1]s" + type = "infra_metric" + event = "StorageSample" + select = "diskFreePercent" + comparison = "below" + + critical { + duration = 20 + value = 15 + time_function = "all" + } +} +`, rName) +} + +func testAccCheckNewRelicInfraAlertConditionConfigWithWhere(rName, where string) string { + return fmt.Sprintf(` +resource "newrelic_alert_policy" "foo" { + name = "tf-test-%[1]s" +} + +resource "newrelic_infra_alert_condition" "foo" { + policy_id = "${newrelic_alert_policy.foo.id}" + + name = "tf-test-%[1]s" + type = "infra_process_running" + process_where = "commandName = 'java'" + comparison = "equal" + where = "%[2]s" + + critical { + duration = 10 + value = 0 + } +} +`, rName, where) +} diff --git a/newrelic/resource_newrelic_nrql_alert_condition.go b/newrelic/resource_newrelic_nrql_alert_condition.go index 5d93a262b..8fb800956 100644 --- a/newrelic/resource_newrelic_nrql_alert_condition.go +++ b/newrelic/resource_newrelic_nrql_alert_condition.go @@ -182,7 +182,7 @@ func readNrqlAlertConditionStruct(condition *newrelic.AlertNrqlCondition, d *sch } func resourceNewRelicNrqlAlertConditionCreate(d *schema.ResourceData, meta interface{}) error { - client := meta.(*newrelic.Client) + client := meta.(*ProviderConfig).Client condition := buildNrqlAlertConditionStruct(d) log.Printf("[INFO] Creating New Relic NRQL alert condition %s", condition.Name) @@ -198,7 +198,7 @@ func resourceNewRelicNrqlAlertConditionCreate(d *schema.ResourceData, meta inter } func resourceNewRelicNrqlAlertConditionRead(d *schema.ResourceData, meta interface{}) error { - client := meta.(*newrelic.Client) + client := meta.(*ProviderConfig).Client log.Printf("[INFO] Reading New Relic NRQL alert condition %s", d.Id()) @@ -224,7 +224,7 @@ func resourceNewRelicNrqlAlertConditionRead(d *schema.ResourceData, meta interfa } func resourceNewRelicNrqlAlertConditionUpdate(d *schema.ResourceData, meta interface{}) error { - client := meta.(*newrelic.Client) + client := meta.(*ProviderConfig).Client condition := buildNrqlAlertConditionStruct(d) ids, err := parseIDs(d.Id(), 2) @@ -249,7 +249,7 @@ func resourceNewRelicNrqlAlertConditionUpdate(d *schema.ResourceData, meta inter } func resourceNewRelicNrqlAlertConditionDelete(d *schema.ResourceData, meta interface{}) error { - client := meta.(*newrelic.Client) + client := meta.(*ProviderConfig).Client ids, err := parseIDs(d.Id(), 2) if err != nil { diff --git a/newrelic/resource_newrelic_nrql_alert_condition_test.go b/newrelic/resource_newrelic_nrql_alert_condition_test.go index 552ec5336..75265ab6a 100644 --- a/newrelic/resource_newrelic_nrql_alert_condition_test.go +++ b/newrelic/resource_newrelic_nrql_alert_condition_test.go @@ -7,7 +7,6 @@ import ( "github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" - newrelic "github.com/paultyng/go-newrelic/api" ) func TestAccNewRelicNrqlAlertCondition_Basic(t *testing.T) { @@ -84,7 +83,7 @@ func TestAccNewRelicNrqlAlertCondition_Basic(t *testing.T) { // TODO: func_ TestAccNewRelicNrqlAlertCondition_Multi(t *testing.T) { func testAccCheckNewRelicNrqlAlertConditionDestroy(s *terraform.State) error { - client := testAccProvider.Meta().(*newrelic.Client) + client := testAccProvider.Meta().(*ProviderConfig).Client for _, r := range s.RootModule().Resources { if r.Type != "newrelic_nrql_alert_condition" { continue @@ -117,7 +116,7 @@ func testAccCheckNewRelicNrqlAlertConditionExists(n string) resource.TestCheckFu return fmt.Errorf("No alert condition ID is set") } - client := testAccProvider.Meta().(*newrelic.Client) + client := testAccProvider.Meta().(*ProviderConfig).Client ids, err := parseIDs(rs.Primary.ID, 2) if err != nil { diff --git a/vendor/github.com/paultyng/go-newrelic/api/alert_infra_conditions.go b/vendor/github.com/paultyng/go-newrelic/api/alert_infra_conditions.go new file mode 100644 index 000000000..fd4a8037d --- /dev/null +++ b/vendor/github.com/paultyng/go-newrelic/api/alert_infra_conditions.go @@ -0,0 +1,121 @@ +package api + +import ( + "fmt" + "net/url" + "strconv" +) + +func (c *InfraClient) queryAlertInfraConditions(policyID int) ([]AlertInfraCondition, error) { + conditions := []AlertInfraCondition{} + + reqURL, err := url.Parse("/alerts/conditions") + if err != nil { + return nil, err + } + + qs := reqURL.Query() + qs.Set("policy_id", strconv.Itoa(policyID)) + + reqURL.RawQuery = qs.Encode() + + nextPath := reqURL.String() + + for nextPath != "" { + resp := struct { + InfraConditions []AlertInfraCondition `json:"data,omitempty"` + }{} + + nextPath, err = c.Do("GET", nextPath, nil, &resp) + if err != nil { + return nil, err + } + + for _, c := range resp.InfraConditions { + c.PolicyID = policyID + } + + conditions = append(conditions, resp.InfraConditions...) + } + + return conditions, nil +} + +// GetAlertInfraCondition gets information about a Infra alert condition given an ID and policy ID. +func (c *InfraClient) GetAlertInfraCondition(policyID int, id int) (*AlertInfraCondition, error) { + conditions, err := c.queryAlertInfraConditions(policyID) + if err != nil { + return nil, err + } + + for _, condition := range conditions { + if condition.ID == id { + return &condition, nil + } + } + + return nil, ErrNotFound +} + +// ListAlertInfraConditions returns Infra alert conditions for the specified policy. +func (c *InfraClient) ListAlertInfraConditions(policyID int) ([]AlertInfraCondition, error) { + return c.queryAlertInfraConditions(policyID) +} + +// CreateAlertInfraCondition creates an Infra alert condition given the passed configuration. +func (c *InfraClient) CreateAlertInfraCondition(condition AlertInfraCondition) (*AlertInfraCondition, error) { + policyID := condition.PolicyID + + req := struct { + Condition AlertInfraCondition `json:"data"` + }{ + Condition: condition, + } + + resp := struct { + Condition AlertInfraCondition `json:"data,omitempty"` + }{} + + u := &url.URL{Path: "/alerts/conditions"} + _, err := c.Do("POST", u.String(), req, &resp) + if err != nil { + return nil, err + } + + resp.Condition.PolicyID = policyID + + return &resp.Condition, nil +} + +// UpdateAlertInfraCondition updates an Infra alert condition with the specified changes. +func (c *InfraClient) UpdateAlertInfraCondition(condition AlertInfraCondition) (*AlertInfraCondition, error) { + policyID := condition.PolicyID + id := condition.ID + + req := struct { + Condition AlertInfraCondition `json:"data"` + }{ + Condition: condition, + } + + resp := struct { + Condition AlertInfraCondition `json:"data,omitempty"` + }{} + + u := &url.URL{Path: fmt.Sprintf("/alerts/conditions/%v", id)} + _, err := c.Do("PUT", u.String(), req, &resp) + if err != nil { + return nil, err + } + + resp.Condition.PolicyID = policyID + + return &resp.Condition, nil +} + +// DeleteAlertInfraCondition removes the Infra alert condition given the specified ID and policy ID. +func (c *InfraClient) DeleteAlertInfraCondition(policyID int, id int) error { + u := &url.URL{Path: fmt.Sprintf("/alerts/conditions/%v", id)} + _, err := c.Do("DELETE", u.String(), nil, nil) + return err +} diff --git a/vendor/github.com/paultyng/go-newrelic/api/client.go b/vendor/github.com/paultyng/go-newrelic/api/client.go index 08f06d62d..368b3b05c 100644 --- a/vendor/github.com/paultyng/go-newrelic/api/client.go +++ b/vendor/github.com/paultyng/go-newrelic/api/client.go @@ -14,6 +14,20 @@ type Client struct { RestyClient *resty.Client } +// InfraClient represents the client state for the Infrastructure API +type InfraClient struct { + Client +} + +// NewInfraClient returns a new InfraClient for the specified apiKey. +func NewInfraClient(config Config) InfraClient { + if config.BaseURL == "" { + config.BaseURL = "https://infra-api.newrelic.com/v2" + } + + return InfraClient{New(config)} +} + // ErrorResponse represents an error response from New Relic. type ErrorResponse struct { Detail *ErrorDetail `json:"error,omitempty"` @@ -68,7 +82,8 @@ func New(config Config) Client { // Do exectes an API request with the specified parameters. func (c *Client) Do(method string, path string, body interface{}, response interface{}) (string, error) { r := c.RestyClient.R(). - SetError(&ErrorResponse{}) + SetError(&ErrorResponse{}). + SetHeader("Content-Type", "application/json") if body != nil { r = r.SetBody(body) diff --git a/vendor/github.com/paultyng/go-newrelic/api/types.go b/vendor/github.com/paultyng/go-newrelic/api/types.go index d538899da..ec5398894 100644 --- a/vendor/github.com/paultyng/go-newrelic/api/types.go +++ b/vendor/github.com/paultyng/go-newrelic/api/types.go @@ -297,3 +297,28 @@ type DashboardWidgetLayout struct { Row int `json:"row"` Column int `json:"column"` } + +// AlertInfraThreshold represents an Infra alerting condition +type AlertInfraThreshold struct { + Value int `json:"value,omitempty"` + Duration int `json:"duration_minutes,omitempty"` + Function string `json:"time_function,omitempty"` +} + +// AlertInfraCondition represents a New Relic Infra Alert condition. +type AlertInfraCondition struct { + PolicyID int `json:"policy_id,omitempty"` + ID int `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Type string `json:"type,omitempty"` + Comparison string `json:"comparison,omitempty"` + CreatedAt int `json:"created_at_epoch_millis,omitempty"` + UpdatedAt int `json:"updated_at_epoch_millis,omitempty"` + Enabled bool `json:"enabled,omitempty"` + Event string `json:"event_type,omitempty"` + Select string `json:"select_value,omitempty"` + Where string `json:"where_clause,omitempty"` + ProcessWhere string `json:"process_where_clause,omitempty"` + Warning *AlertInfraThreshold `json:"warning_threshold,omitempty"` + Critical *AlertInfraThreshold `json:"critical_threshold,omitempty"` +} diff --git a/vendor/vendor.json b/vendor/vendor.json index 525def958..17a7886ee 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -604,10 +604,10 @@ "revisionTime": "2016-11-16T22:44:47Z" }, { - "checksumSHA1": "8UonU0IfV3BjknE1g2mhZ4rTwBg=", + "checksumSHA1": "P8iQbWY66Nw4g+xCnNiquMl1rZc=", "path": "github.com/paultyng/go-newrelic/api", - "revision": "960e8b39399fe02c2bb58ce0498abec2564fdd1c", - "revisionTime": "2018-01-24T20:26:26Z" + "revision": "0b59f493a5f1be587889bf870cd51c20d3f5e888", + "revisionTime": "2018-05-31T15:18:35Z" }, { "checksumSHA1": "u5s2PZ7fzCOqQX7bVPf9IJ+qNLQ=", diff --git a/website/docs/r/infra_alert_condition.html.markdown b/website/docs/r/infra_alert_condition.html.markdown new file mode 100644 index 000000000..fd649e431 --- /dev/null +++ b/website/docs/r/infra_alert_condition.html.markdown @@ -0,0 +1,64 @@ +--- +layout: "newrelic" +page_title: "New Relic: newrelic_infra_alert_condition" +sidebar_current: "docs-newrelic-resource-infra-alert-condition" +description: |- + Create and manage an Infrastructure alert condition for a policy in New Relic. +--- + +# newrelic\_infra_alert\_condition + +## Example Usage + +```hcl +resource "newrelic_alert_policy" "foo" { + name = "foo" +} + +resource "newrelic_infra_alert_condition" "foo" { + policy_id = "${newrelic_alert_policy.foo.id}" + + name = "High disk usage" + type = "infra_metric" + event = "StorageSample" + select = "diskUsedPercent" + comparison = "above" + where = "(`hostname` LIKE '%frontend%')" + + critical { + duration = 25 + value = 90 + time_function = "all" + } +} +``` + +## Argument Reference + +The following arguments are supported: + + * `policy_id` - (Required) The ID of the alert policy where this condition should be used. + * `name` - (Required) The Infrastructure alert condition's name. + * `enabled` - (Optional) Set whether to enable the alert condition. Defaults to `true`. + * `type` - (Required) The type of Infrastructure alert condition: "infra_process_running", "infra_metric", or "infra_host_not_reporting". + * `event` - (Required) The metric event; for example, system metrics, process metrics, storage metrics, or network metrics. + * `select` - (Required) The attribute name to identify the type of metric condition; for example, "network", "process", "system", or "storage". + * `comparison` - (Required) The operator used to evaluate the threshold value; "above", "below", "equal". + * `critical` - (Required) Identifies the critical threshold parameters for triggering an alert notification. See [Thresholds](#thresholds) below for details. + * `warning` - (Optional) Identifies the warning threshold parameters. See [Thresholds](#thresholds) below for details. + * `where` - (Optional) Infrastructure host filter for the alert condition. + * `process_where` - (Optional) Any filters applied to processes; for example: `"commandName = 'java'"`. + +## Thresholds + +The `critical` and `warning` threshold mapping supports the following arguments: + + * `duration` - (Required) Identifies the number of minutes the threshold must be passed or met for the alert to trigger. Threshold durations must be between 1 and 60 minutes (inclusive). + * `value` - (Optional) Threshold value, computed against the `comparison` operator. Supported by "infra_metric" and "infra_process_running" alert condition types. + * `time_function` - (Optional) Indicates if the condition needs to be sustained or to just break the threshold once; `all` or `any`. Supported by the "infra_metric" alert condition type. + +## Attributes Reference + +The following attributes are exported: + + * `id` - The ID of the Infrastructure alert condition. diff --git a/website/newrelic.erb b/website/newrelic.erb index f4bd0af39..8356d23cf 100644 --- a/website/newrelic.erb +++ b/website/newrelic.erb @@ -40,6 +40,9 @@