Update go-newrelic vendor and use new field (#13158)

Fixes #12972
This commit is contained in:
Paul Tyng 2017-04-16 18:59:11 -04:00 committed by Paul Stack
parent 1f75a5f372
commit b8b896e11b
15 changed files with 320 additions and 21 deletions

View File

@ -106,6 +106,10 @@ func resourceNewRelicAlertCondition() *schema.Resource {
Type: schema.TypeString,
Optional: true,
},
"condition_scope": {
Type: schema.TypeString,
Optional: true,
},
"term": {
Type: schema.TypeList,
Elem: &schema.Resource{
@ -186,6 +190,7 @@ func buildAlertConditionStruct(d *schema.ResourceData) *newrelic.AlertCondition
Metric: d.Get("metric").(string),
Terms: terms,
PolicyID: d.Get("policy_id").(int),
Scope: d.Get("condition_scope").(string),
}
if attr, ok := d.GetOk("runbook_url"); ok {
@ -226,6 +231,7 @@ func readAlertConditionStruct(condition *newrelic.AlertCondition, d *schema.Reso
d.Set("type", condition.Type)
d.Set("metric", condition.Metric)
d.Set("runbook_url", condition.RunbookURL)
d.Set("condition_scope", condition.Scope)
d.Set("user_defined_metric", condition.UserDefined.Metric)
d.Set("user_defined_value_function", condition.UserDefined.ValueFunction)
if err := d.Set("entities", entities); err != nil {

View File

@ -29,8 +29,6 @@ func TestAccNewRelicAlertCondition_Basic(t *testing.T) {
"newrelic_alert_condition.foo", "runbook_url", "https://foo.example.com"),
resource.TestCheckResourceAttr(
"newrelic_alert_condition.foo", "entities.#", "1"),
resource.TestCheckResourceAttr(
"newrelic_alert_condition.foo", "entities.0", "12345"),
resource.TestCheckResourceAttr(
"newrelic_alert_condition.foo", "term.#", "1"),
resource.TestCheckResourceAttr(
@ -55,8 +53,6 @@ func TestAccNewRelicAlertCondition_Basic(t *testing.T) {
"newrelic_alert_condition.foo", "runbook_url", "https://bar.example.com"),
resource.TestCheckResourceAttr(
"newrelic_alert_condition.foo", "entities.#", "1"),
resource.TestCheckResourceAttr(
"newrelic_alert_condition.foo", "entities.0", "67890"),
resource.TestCheckResourceAttr(
"newrelic_alert_condition.foo", "term.#", "1"),
resource.TestCheckResourceAttr(
@ -136,6 +132,10 @@ func testAccCheckNewRelicAlertConditionExists(n string) resource.TestCheckFunc {
func testAccCheckNewRelicAlertConditionConfig(rName string) string {
return fmt.Sprintf(`
data "newrelic_application" "app" {
name = "%[2]s"
}
resource "newrelic_alert_policy" "foo" {
name = "tf-test-%[1]s"
}
@ -143,11 +143,12 @@ resource "newrelic_alert_policy" "foo" {
resource "newrelic_alert_condition" "foo" {
policy_id = "${newrelic_alert_policy.foo.id}"
name = "tf-test-%[1]s"
type = "apm_app_metric"
entities = ["12345"]
metric = "apdex"
runbook_url = "https://foo.example.com"
name = "tf-test-%[1]s"
type = "apm_app_metric"
entities = ["${data.newrelic_application.app.id}"]
metric = "apdex"
runbook_url = "https://foo.example.com"
condition_scope = "application"
term {
duration = 5
@ -157,11 +158,15 @@ resource "newrelic_alert_condition" "foo" {
time_function = "all"
}
}
`, rName)
`, rName, testAccExpectedApplicationName)
}
func testAccCheckNewRelicAlertConditionConfigUpdated(rName string) string {
return fmt.Sprintf(`
data "newrelic_application" "app" {
name = "%[2]s"
}
resource "newrelic_alert_policy" "foo" {
name = "tf-test-updated-%[1]s"
}
@ -169,11 +174,12 @@ resource "newrelic_alert_policy" "foo" {
resource "newrelic_alert_condition" "foo" {
policy_id = "${newrelic_alert_policy.foo.id}"
name = "tf-test-updated-%[1]s"
type = "apm_app_metric"
entities = ["67890"]
metric = "apdex"
runbook_url = "https://bar.example.com"
name = "tf-test-updated-%[1]s"
type = "apm_app_metric"
entities = ["${data.newrelic_application.app.id}"]
metric = "apdex"
runbook_url = "https://bar.example.com"
condition_scope = "application"
term {
duration = 10
@ -183,7 +189,7 @@ resource "newrelic_alert_condition" "foo" {
time_function = "all"
}
}
`, rName)
`, rName, testAccExpectedApplicationName)
}
// TODO: const testAccCheckNewRelicAlertConditionConfigMulti = `

View File

@ -52,6 +52,7 @@ func (c *Client) ListAlertChannels() ([]AlertChannel, error) {
return c.queryAlertChannels()
}
// CreateAlertChannel allows you to create an alert channel with the specified data and links.
func (c *Client) CreateAlertChannel(channel AlertChannel) (*AlertChannel, error) {
// TODO: support attaching policy ID's here?
// qs := map[string]string{
@ -59,7 +60,7 @@ func (c *Client) CreateAlertChannel(channel AlertChannel) (*AlertChannel, error)
// }
if len(channel.Links.PolicyIDs) > 0 {
return nil, fmt.Errorf("You cannot create an alert channel with policy IDs, you must attach polidy IDs after creation.")
return nil, fmt.Errorf("cannot create an alert channel with policy IDs, you must attach polidy IDs after creation")
}
req := struct {
@ -80,6 +81,7 @@ func (c *Client) CreateAlertChannel(channel AlertChannel) (*AlertChannel, error)
return &resp.Channels[0], nil
}
// DeleteAlertChannel deletes the alert channel with the specified ID.
func (c *Client) DeleteAlertChannel(id int) error {
u := &url.URL{Path: fmt.Sprintf("/alerts_channels/%v.json", id)}
_, err := c.Do("DELETE", u.String(), nil, nil)

View File

@ -41,6 +41,7 @@ func (c *Client) queryAlertConditions(policyID int) ([]AlertCondition, error) {
return conditions, nil
}
// GetAlertCondition gets information about an alert condition given an ID and policy ID.
func (c *Client) GetAlertCondition(policyID int, id int) (*AlertCondition, error) {
conditions, err := c.queryAlertConditions(policyID)
if err != nil {
@ -61,6 +62,7 @@ func (c *Client) ListAlertConditions(policyID int) ([]AlertCondition, error) {
return c.queryAlertConditions(policyID)
}
// CreateAlertCondition creates an alert condition given the passed configuration.
func (c *Client) CreateAlertCondition(condition AlertCondition) (*AlertCondition, error) {
policyID := condition.PolicyID
@ -85,6 +87,7 @@ func (c *Client) CreateAlertCondition(condition AlertCondition) (*AlertCondition
return &resp.Condition, nil
}
// UpdateAlertCondition updates an alert condition with the specified changes.
func (c *Client) UpdateAlertCondition(condition AlertCondition) (*AlertCondition, error) {
policyID := condition.PolicyID
id := condition.ID
@ -110,6 +113,7 @@ func (c *Client) UpdateAlertCondition(condition AlertCondition) (*AlertCondition
return &resp.Condition, nil
}
// DeleteAlertCondition removes the alert condition given the specified ID and policy ID.
func (c *Client) DeleteAlertCondition(policyID int, id int) error {
u := &url.URL{Path: fmt.Sprintf("/alerts_conditions/%v.json", id)}
_, err := c.Do("DELETE", u.String(), nil, nil)

View File

@ -6,6 +6,7 @@ import (
"strconv"
)
// UpdateAlertPolicyChannels updates a policy by adding the specified notification channels.
func (c *Client) UpdateAlertPolicyChannels(policyID int, channelIDs []int) error {
channelIDStrings := make([]string, len(channelIDs))
@ -30,6 +31,7 @@ func (c *Client) UpdateAlertPolicyChannels(policyID int, channelIDs []int) error
return err
}
// DeleteAlertPolicyChannel deletes a notification channel from an alert policy.
func (c *Client) DeleteAlertPolicyChannel(policyID int, channelID int) error {
reqURL, err := url.Parse("/alerts_policy_channels.json")
if err != nil {

View File

@ -53,6 +53,7 @@ func (c *Client) queryApplications(filters applicationsFilters) ([]Application,
return applications, nil
}
// ListApplications lists all the applications you have access to.
func (c *Client) ListApplications() ([]Application, error) {
return c.queryApplications(applicationsFilters{})
}

View File

@ -13,6 +13,7 @@ type Client struct {
RestyClient *resty.Client
}
// ErrorResponse represents an error response from New Relic.
type ErrorResponse struct {
Detail *ErrorDetail `json:"error,omitempty"`
}
@ -24,6 +25,7 @@ func (e *ErrorResponse) Error() string {
return "Unknown error"
}
// ErrorDetail represents the details of an ErrorResponse from New Relic.
type ErrorDetail struct {
Title string `json:"title,omitempty"`
}

View File

@ -0,0 +1,45 @@
package api
import (
"fmt"
"net/url"
)
func (c *Client) queryComponentMetricData(componentID int, names []string) ([]Metric, error) {
data := []Metric{}
reqURL, err := url.Parse(fmt.Sprintf("/components/%v/metrics/data.json", componentID))
if err != nil {
return nil, err
}
qs := reqURL.Query()
for _, name := range names {
qs.Add("names[]", name)
}
reqURL.RawQuery = qs.Encode()
nextPath := reqURL.String()
for nextPath != "" {
resp := struct {
MetricData struct {
Metrics []Metric `json:"metrics"`
} `json:"metric_data,omitempty"`
}{}
nextPath, err = c.Do("GET", nextPath, nil, &resp)
if err != nil {
return nil, err
}
data = append(data, resp.MetricData.Metrics...)
}
return data, nil
}
// ListComponentMetricData lists all the metric data for the specified component ID and metric names.
func (c *Client) ListComponentMetricData(componentID int, names []string) ([]Metric, error) {
return c.queryComponentMetricData(componentID, names)
}

View File

@ -0,0 +1,40 @@
package api
import (
"fmt"
"net/url"
)
func (c *Client) queryComponentMetrics(componentID int) ([]ComponentMetric, error) {
metrics := []ComponentMetric{}
reqURL, err := url.Parse(fmt.Sprintf("/components/%v/metrics.json", componentID))
if err != nil {
return nil, err
}
qs := reqURL.Query()
reqURL.RawQuery = qs.Encode()
nextPath := reqURL.String()
for nextPath != "" {
resp := struct {
Metrics []ComponentMetric `json:"metrics,omitempty"`
}{}
nextPath, err = c.Do("GET", nextPath, nil, &resp)
if err != nil {
return nil, err
}
metrics = append(metrics, resp.Metrics...)
}
return metrics, nil
}
// ListComponentMetrics lists all the component metrics for the specificed component ID.
func (c *Client) ListComponentMetrics(componentID int) ([]ComponentMetric, error) {
return c.queryComponentMetrics(componentID)
}

View File

@ -0,0 +1,51 @@
package api
import (
"net/url"
"strconv"
)
type componentsFilters struct {
PluginID int
IDs []int
}
func (c *Client) queryComponents(filters componentsFilters) ([]Component, error) {
components := []Component{}
reqURL, err := url.Parse("/components.json")
if err != nil {
return nil, err
}
qs := reqURL.Query()
qs.Set("filter[plugin_id]", strconv.Itoa(filters.PluginID))
for _, id := range filters.IDs {
qs.Add("filter[ids]", strconv.Itoa(id))
}
reqURL.RawQuery = qs.Encode()
nextPath := reqURL.String()
for nextPath != "" {
resp := struct {
Components []Component `json:"components,omitempty"`
}{}
nextPath, err = c.Do("GET", nextPath, nil, &resp)
if err != nil {
return nil, err
}
components = append(components, resp.Components...)
}
return components, nil
}
// ListComponents lists all the components for the specified plugin ID.
func (c *Client) ListComponents(pluginID int) ([]Component, error) {
return c.queryComponents(componentsFilters{
PluginID: pluginID,
})
}

View File

@ -31,6 +31,7 @@ func (c *Client) queryLabels() ([]Label, error) {
return labels, nil
}
// GetLabel gets the label for the specified key.
func (c *Client) GetLabel(key string) (*Label, error) {
labels, err := c.queryLabels()
if err != nil {

51
vendor/github.com/paultyng/go-newrelic/api/plugins.go generated vendored Normal file
View File

@ -0,0 +1,51 @@
package api
import (
"net/url"
"strconv"
)
type pluginsFilters struct {
GUID *string
IDs []int
}
func (c *Client) queryPlugins(filters pluginsFilters) ([]Plugin, error) {
plugins := []Plugin{}
reqURL, err := url.Parse("/plugins.json")
if err != nil {
return nil, err
}
qs := reqURL.Query()
if filters.GUID != nil {
qs.Set("filter[guid]", *filters.GUID)
}
for _, id := range filters.IDs {
qs.Add("filter[ids]", strconv.Itoa(id))
}
reqURL.RawQuery = qs.Encode()
nextPath := reqURL.String()
for nextPath != "" {
resp := struct {
Plugins []Plugin `json:"plugins,omitempty"`
}{}
nextPath, err = c.Do("GET", nextPath, nil, &resp)
if err != nil {
return nil, err
}
plugins = append(plugins, resp.Plugins...)
}
return plugins, nil
}
// ListPlugins lists all the plugins you have access to.
func (c *Client) ListPlugins() ([]Plugin, error) {
return c.queryPlugins(pluginsFilters{})
}

View File

@ -3,6 +3,7 @@ package api
import "errors"
var (
// ErrNotFound is returned when the resource was not found in New Relic.
ErrNotFound = errors.New("newrelic: Resource not found")
)
@ -57,7 +58,8 @@ type AlertCondition struct {
Metric string `json:"metric,omitempty"`
RunbookURL string `json:"runbook_url,omitempty"`
Terms []AlertConditionTerm `json:"terms,omitempty"`
UserDefined AlertConditionUserDefined `json:"uder_defined,omitempty"`
UserDefined AlertConditionUserDefined `json:"user_defined,omitempty"`
Scope string `json:"condition_scope,omitempty"`
}
// AlertChannelLinks represent the links between policies and alert channels
@ -74,6 +76,7 @@ type AlertChannel struct {
Links AlertChannelLinks `json:"links,omitempty"`
}
// ApplicationSummary represents performance information about a New Relic application.
type ApplicationSummary struct {
ResponseTime float64 `json:"response_time"`
Throughput float64 `json:"throughput"`
@ -85,6 +88,7 @@ type ApplicationSummary struct {
ConcurrentInstanceCount int `json:"concurrent_instance_count"`
}
// ApplicationEndUserSummary represents performance information about a New Relic application.
type ApplicationEndUserSummary struct {
ResponseTime float64 `json:"response_time"`
Throughput float64 `json:"throughput"`
@ -92,6 +96,7 @@ type ApplicationEndUserSummary struct {
ApdexScore float64 `json:"apdex_score"`
}
// ApplicationSettings represents some of the settings of a New Relic application.
type ApplicationSettings struct {
AppApdexThreshold float64 `json:"app_apdex_threshold,omitempty"`
EndUserApdexThreshold float64 `json:"end_user_apdex_threshold,omitempty"`
@ -99,6 +104,7 @@ type ApplicationSettings struct {
UseServerSideConfig bool `json:"use_server_side_config,omitempty"`
}
// ApplicationLinks represents all the links for a New Relic application.
type ApplicationLinks struct {
ServerIDs []int `json:"servers,omitempty"`
HostIDs []int `json:"application_hosts,omitempty"`
@ -106,6 +112,7 @@ type ApplicationLinks struct {
AlertPolicyID int `json:"alert_policy"`
}
// Application represents information about a New Relic application.
type Application struct {
ID int `json:"id,omitempty"`
Name string `json:"name,omitempty"`
@ -118,3 +125,83 @@ type Application struct {
Settings ApplicationSettings `json:"settings,omitempty"`
Links ApplicationLinks `json:"links,omitempty"`
}
// PluginDetails represents information about a New Relic plugin.
type PluginDetails struct {
Description int `json:"description"`
IsPublic string `json:"is_public"`
CreatedAt string `json:"created_at,omitempty"`
UpdatedAt string `json:"updated_at,omitempty"`
LastPublishedAt string `json:"last_published_at,omitempty"`
HasUnpublishedChanges bool `json:"has_unpublished_changes"`
BrandingImageURL string `json:"branding_image_url"`
UpgradedAt string `json:"upgraded_at,omitempty"`
ShortName string `json:"short_name"`
PublisherAboutURL string `json:"publisher_about_url"`
PublisherSupportURL string `json:"publisher_support_url"`
DownloadURL string `json:"download_url"`
FirstEditedAt string `json:"first_edited_at,omitempty"`
LastEditedAt string `json:"last_edited_at,omitempty"`
FirstPublishedAt string `json:"first_published_at,omitempty"`
PublishedVersion string `json:"published_version"`
}
// MetricThreshold represents the different thresholds for a metric in an alert.
type MetricThreshold struct {
Caution float64 `json:"caution"`
Critical float64 `json:"critical"`
}
// MetricValue represents the observed value of a metric.
type MetricValue struct {
Raw float64 `json:"raw"`
Formatted string `json:"formatted"`
}
// MetricTimeslice represents the values of a metric over a given time.
type MetricTimeslice struct {
From string `json:"from,omitempty"`
To string `json:"to,omitempty"`
Values map[string]interface{} `json:"values,omitempty"`
}
// Metric represents data for a specific metric.
type Metric struct {
Name string `json:"name"`
Timeslices []MetricTimeslice `json:"timeslices"`
}
// SummaryMetric represents summary information for a specific metric.
type SummaryMetric struct {
ID int `json:"id"`
Name string `json:"name"`
Metric string `json:"metric"`
ValueFunction string `json:"value_function"`
Thresholds MetricThreshold `json:"thresholds"`
Values MetricValue `json:"values"`
}
// Plugin represents information about a New Relic plugin.
type Plugin struct {
ID int `json:"id"`
Name string `json:"name,omitempty"`
GUID string `json:"guid,omitempty"`
Publisher string `json:"publisher,omitempty"`
ComponentAgentCount int `json:"component_agent_count"`
Details PluginDetails `json:"details"`
SummaryMetrics []SummaryMetric `json:"summary_metrics"`
}
// Component represnets information about a New Relic component.
type Component struct {
ID int `json:"id"`
Name string `json:"name,omitempty"`
HealthStatus string `json:"health_status,omitempty"`
SummaryMetrics []SummaryMetric `json:"summary_metrics"`
}
// ComponentMetric represents metric information for a specific component.
type ComponentMetric struct {
Name string `json:"name,omitempty"`
Values []string `json:"values"`
}

6
vendor/vendor.json vendored
View File

@ -2733,10 +2733,10 @@
"revisionTime": "2016-08-11T16:27:25Z"
},
{
"checksumSHA1": "lOEkLP94OsQSLFp+38rY1GjnMtk=",
"checksumSHA1": "SUK6xOTZDwljlX/AoHAmgoz0e1E=",
"path": "github.com/paultyng/go-newrelic/api",
"revision": "81a8e05b0e494285f1322f99f3c6f93c8f1192b1",
"revisionTime": "2016-11-29T00:49:55Z"
"revision": "5fbf16b273dd4b544c9588450c58711d9f46f912",
"revisionTime": "2017-03-27T18:23:21Z"
},
{
"checksumSHA1": "mUb0GqsJK4UDh3Kx8TobjzvDUG4=",

View File

@ -48,6 +48,7 @@ The following arguments are supported:
* `entities` - (Required) The instance IDS associated with this condition.
* `metric` - (Required) The metric field accepts parameters based on the `type` set.
* `runbook_url` - (Optional) Runbook URL to display in notifications.
* `condition_scope` - (Optional) `instance` or `application`. This is required if you are using the JVM plugin in New Relic.
* `term` - (Required) A list of terms for this condition. See [Terms](#terms) below for details.
* `user_defined_metric` - (Optional) A custom metric to be evaluated.
* `user_defined_value_function` - (Optional) One of: `average`, `min`, `max`, `total`, or `sample_size`.