Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stackdriver monitoring AlertPolicy resource #503

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build/terraform
757 changes: 757 additions & 0 deletions products/monitoring/api.yaml

Large diffs are not rendered by default.

92 changes: 92 additions & 0 deletions products/monitoring/terraform.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Copyright 2017 Google Inc.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
--- !ruby/object:Provider::Terraform::Config
overrides: !ruby/object:Provider::ResourceOverrides
AlertPolicy: !ruby/object:Provider::Terraform::ResourceOverride
id_format: "{{name}}"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pretty sure {{name}} is the default, so this can be removed too (i could be wrong though)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if you add something to override the import formats, it won't affect the generated code since you did a custom import, but it'll hopefully fix the documentation since it's showing a few different formats.

import_format: ["{{name}}"]
mutex: alertPolicy/{{project}}
examples: |
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Complete drive-by but wanna use a new-style example :)

#423 #446 #485 for context

### Basic Usage
```hcl
resource "google_monitoring_alert_policy" "basic" {
display_name = "Test Policy Basic"
combiner = "OR"
conditions = [
{
display_name = "test condition"
condition_threshold {
filter = "metric.type=\"compute.googleapis.com/instance/disk/write_bytes_count\" AND resource.type=\"gce_instance\""
duration = "60s"
comparison = "COMPARISON_GT"
aggregations = [
{
alignment_period = "60s"
per_series_aligner = "ALIGN_RATE"
}
]
}
}
]
}
```

custom_code: !ruby/object:Provider::Terraform::CustomCode
custom_import: templates/terraform/custom_import/self_link_as_name.erb
post_create: templates/terraform/post_create/set_computed_name.erb

Group: !ruby/object:Provider::Terraform::ResourceOverride
id_format: "{{name}}"
examples: |
### Basic Usage
```hcl
resource "google_monitoring_group" "test" {
display_name = "New Group"
filter = "resource.metadata.region=\"europe-west2\""
}
```

### Full Usage
```hcl
resource "google_monitoring_group" "parent_group" {
display_name = "Parent Group"
filter = "resource.metadata.region=\"europe-west2\""
is_cluster = true
}

resource "google_monitoring_group" "child_group" {
display_name = "Child Group"
parent_name = "${google_monitoring_group.parent_group.name}"
filter = "resource.metadata.region=\"europe-west2\""
}

output "parent_group_name" {
value = "${google_monitoring_group.parent_group.name}"
}
```
properties:
name: !ruby/object:Provider::Terraform::PropertyOverride
custom_expand: 'templates/terraform/custom_expand/monitoring_group_name.erb'
custom_flatten: 'templates/terraform/custom_flatten/name_from_self_link.erb'
parentName: !ruby/object:Provider::Terraform::PropertyOverride
custom_expand: 'templates/terraform/custom_expand/monitoring_group_name.erb'
custom_flatten: 'templates/terraform/custom_flatten/name_from_self_link.erb'
custom_code: !ruby/object:Provider::Terraform::CustomCode
post_create: templates/terraform/post_create/group.erb

files: !ruby/object:Provider::Config::Files
copy:
'google/resource_monitoring_alert_policy_test.go':
'templates/terraform/tests/resource_monitoring_alert_policy_test.go'
compile:
'google/provider_{{product_name}}_gen.go': 'templates/terraform/provider_gen.erb'
26 changes: 26 additions & 0 deletions templates/terraform/custom_expand/monitoring_group_name.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<% if false # the license inside this if block pertains to this file -%>
# Copyright 2018 Google Inc.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
<% end -%>
func expand<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
project, err := getProject(d, config)
if err != nil {
return nil, err
}

if v.(string) == "" {
return "", nil
}

return fmt.Sprintf("projects/%s/groups/%s", project, v.(string)), nil
}
7 changes: 7 additions & 0 deletions templates/terraform/custom_import/self_link_as_name.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

config := meta.(*Config)

// current import_formats can't import id's with forward slashes in them.
parseImportId([]string{"(?P<name>.+)"}, d, config)

return []*schema.ResourceData{d}, nil
3 changes: 3 additions & 0 deletions templates/terraform/expand_property_method.erb
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ func expand<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d *
<% if property.is_a?(Api::Type::Array) -%>
req := make([]interface{}, 0, len(l))
for _, raw := range l {
if raw == nil {
continue
}
<% else -%>
if len(l) == 0 {
return nil, nil
Expand Down
2 changes: 2 additions & 0 deletions templates/terraform/post_create/group.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
d.SetId(flattenMonitoringGroupName(res["name"]).(string))
d.Set("name", flattenMonitoringGroupName(res["name"]))
7 changes: 7 additions & 0 deletions templates/terraform/post_create/set_computed_name.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// `name` is autogenerated from the api so needs to be set post-create
name, ok := res["name"]
if !ok {
return fmt.Errorf("Create response didn't contain critical fields. Create may not have succeeded.")
}
d.Set("name", name.(string))
d.SetId(name.(string))
211 changes: 211 additions & 0 deletions templates/terraform/tests/resource_monitoring_alert_policy_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
package google

import (
"fmt"
"testing"

"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)

// Stackdriver tests cannot be run in parallel otherwise they will error out with:
// Error 503: Too many concurrent edits to the project configuration. Please try again.

func TestAccMonitoringAlertPolicy_basic(t *testing.T) {

alertName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
conditionName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
filter := `metric.type=\"compute.googleapis.com/instance/disk/write_bytes_count\" AND resource.type=\"gce_instance\"`

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAlertPolicyDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccMonitoringAlertPolicy_basic(alertName, conditionName, "ALIGN_RATE", filter),
},
resource.TestStep{
ResourceName: "google_monitoring_alert_policy.basic",
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccMonitoringAlertPolicy_update(t *testing.T) {

alertName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
conditionName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
filter1 := `metric.type=\"compute.googleapis.com/instance/disk/write_bytes_count\" AND resource.type=\"gce_instance\"`
aligner1 := "ALIGN_RATE"
filter2 := `metric.type=\"compute.googleapis.com/instance/cpu/utilization\" AND resource.type=\"gce_instance\"`
aligner2 := "ALIGN_MAX"

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAlertPolicyDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccMonitoringAlertPolicy_basic(alertName, conditionName, aligner1, filter1),
},
resource.TestStep{
ResourceName: "google_monitoring_alert_policy.basic",
ImportState: true,
ImportStateVerify: true,
},
resource.TestStep{
Config: testAccMonitoringAlertPolicy_basic(alertName, conditionName, aligner2, filter2),
},
resource.TestStep{
ResourceName: "google_monitoring_alert_policy.basic",
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccMonitoringAlertPolicy_full(t *testing.T) {
chrisst marked this conversation as resolved.
Show resolved Hide resolved

alertName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
conditionName1 := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
conditionName2 := fmt.Sprintf("tf-test-%s", acctest.RandString(10))

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAlertPolicyDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccMonitoringAlertPolicy_full(alertName, conditionName1, conditionName2),
},
resource.TestStep{
ResourceName: "google_monitoring_alert_policy.full",
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func testAccCheckAlertPolicyDestroy(s *terraform.State) error {
config := testAccProvider.Meta().(*Config)

for _, rs := range s.RootModule().Resources {
if rs.Type != "google_monitoring_alert_policy" {
continue
}

name := rs.Primary.Attributes["name"]

url := fmt.Sprintf("https://monitoring.googleapis.com/v3/%s", name)
_, err := sendRequest(config, "GET", url, nil)

if err == nil {
return fmt.Errorf("Error, alert policy %s still exists", name)
}
}

return nil
}

func testAccMonitoringAlertPolicy_basic(alertName, conditionName, aligner, filter string) string {
return fmt.Sprintf(`
resource "google_monitoring_alert_policy" "basic" {
display_name = "%s"
enabled = true
combiner = "OR"

conditions = [
chrisst marked this conversation as resolved.
Show resolved Hide resolved
{
display_name = "%s"

condition_threshold = {
aggregations = [
{
alignment_period = "60s"
per_series_aligner = "%s"
},
]

duration = "60s"
comparison = "COMPARISON_GT"
filter = "%s"
}
},
]
}
`, alertName, conditionName, aligner, filter)
}

func testAccMonitoringAlertPolicy_full(alertName, conditionName1, conditionName2 string) string {
return fmt.Sprintf(`
resource "google_monitoring_alert_policy" "full" {
display_name = "%s"
combiner = "OR"
enabled = true

conditions = [
{
display_name = "%s"

condition_threshold = {
threshold_value = 50

aggregations = [
{
alignment_period = "60s"
per_series_aligner = "ALIGN_RATE"
cross_series_reducer = "REDUCE_MEAN"

group_by_fields = [
"metric.label.device_name",
"project",
"resource.label.instance_id",
"resource.label.zone",
]
},
]

duration = "60s"
comparison = "COMPARISON_GT"

trigger = {
percent = 10
}

filter = "metric.type=\"compute.googleapis.com/instance/disk/write_bytes_count\" AND resource.type=\"gce_instance\""
}
},
{
condition_absent {
duration = "3600s"
filter = "metric.type=\"compute.googleapis.com/instance/cpu/utilization\" AND resource.type=\"gce_instance\""

aggregations {
alignment_period = "60s"
cross_series_reducer = "REDUCE_MEAN"
per_series_aligner = "ALIGN_MEAN"

group_by_fields = [
"project",
"resource.label.instance_id",
"resource.label.zone",
]
}

trigger {
count = 1
}
}

display_name = "%s"
},
]
}
`, alertName, conditionName1, conditionName2)
}