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

provider/librato: Enable mgmt of Librato metrics #14562

Merged
merged 9 commits into from
May 26, 2017

Conversation

wchrisjohnson
Copy link
Contributor

@wchrisjohnson wchrisjohnson commented May 17, 2017

  • Update the Librato provider to allow the management of Librato metrics.
  • Updated the underlying go-librato vendored pkg to take advantage of recent changes that dovetail with these changes.
  • Refactored some common funcs out.

@wchrisjohnson wchrisjohnson changed the title Enable mgmt of Librato metrics Enable mgmt of Librato metrics *** WIP *** May 17, 2017
@wchrisjohnson wchrisjohnson changed the title Enable mgmt of Librato metrics *** WIP *** provider/librato: Enable mgmt of Librato metrics *** WIP *** May 17, 2017
Copy link
Contributor

@bernerdschaefer bernerdschaefer left a comment

Choose a reason for hiding this comment

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

I'm excited to see support for this!

composite = "s(\"librato.cpu.percent.user\", {\"environment\" : \"prod\", \"service\": \"api\"})"
attributes {
display_stacked = true,
created_by_ua = "go-librato/0.1"
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think anyone would ever write this attribute in a config; presumably it's set by go-librato when the metric is created. Does the resource behave as expected without this in the config?

Copy link
Contributor Author

@wchrisjohnson wchrisjohnson May 18, 2017

Choose a reason for hiding this comment

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

The tests fail w/o this in the config. Perhaps I'm taking the wrong approach in fixing the issue:

hashicorp/terraform - [cj-add-librato-metrics●] » TF_LOG=info make testacc TEST=./builtin/providers/librato TESTARGS="-run=TestAccLibratoCompositeMetric"
==> Checking that code complies with gofmt requirements...
go generate $(go list ./... | grep -v /terraform/vendor/)
2017/05/18 15:53:37 Generated command/internal_plugin_list.go
TF_ACC=1 go test ./builtin/providers/librato -v -run=TestAccLibratoCompositeMetric -timeout 120m
=== RUN   TestAccLibratoCompositeMetric
2017/05/18 15:53:41 [WARN] Test: Executing step 0
2017/05/18 15:53:41 [INFO] terraform: building graph: GraphTypeValidate
2017/05/18 15:53:41 [WARN] terraform: shadow graph disabled
2017/05/18 15:53:41 [INFO] terraform: building graph: GraphTypeRefresh
2017/05/18 15:53:41 [WARN] terraform: shadow graph disabled
2017/05/18 15:53:41 [INFO] terraform: building graph: GraphTypePlan
2017/05/18 15:53:41 [WARN] terraform: shadow graph disabled
2017/05/18 15:53:41 [WARN] Test: Step plan: DIFF:

CREATE: librato_metric.foobar
  attributes.#:                 "0" => "1"
  attributes.0.display_stacked: "" => "true"
  composite:                    "" => "s(\"librato.cpu.percent.user\", {\"environment\" : \"prod\", \"service\": \"api\"})"
  description:                  "" => "A test composite metric"
  name:                         "" => "tftest-metric-x4dlskaqoh"
  type:                         "" => "composite"

STATE:

<no state>
2017/05/18 15:53:41 [INFO] terraform: building graph: GraphTypeApply
2017/05/18 15:53:41 [WARN] terraform: shadow graph disabled
2017/05/18 15:53:42 [INFO] terraform: building graph: GraphTypePlan
2017/05/18 15:53:42 [WARN] terraform: shadow graph disabled
2017/05/18 15:53:42 [INFO] terraform: building graph: GraphTypeRefresh
2017/05/18 15:53:42 [WARN] terraform: shadow graph disabled
2017/05/18 15:53:42 [INFO] Reading Librato Metric: tftest-metric-x4dlskaqoh
2017/05/18 15:53:42 [INFO] Read Librato Metric: {"name":"tftest-metric-x4dlskaqoh","description":"A test composite metric","type":"composite","composite":"s(\"librato.cpu.percent.user\", {\"environment\" : \"prod\", \"service\": \"api\"})","attributes":{"color":null,"display_max":null,"display_min":null,"display_units_long":"","display_units_short":"","display_stacked":true,"display_transform":"","created_by_ua":"go-librato/0.1"}}
2017/05/18 15:53:42 [INFO] terraform: building graph: GraphTypePlan
2017/05/18 15:53:42 [WARN] terraform: shadow graph disabled
2017/05/18 15:53:42 [WARN] Test: Executing destroy step
2017/05/18 15:53:42 [INFO] terraform: building graph: GraphTypeValidate
2017/05/18 15:53:42 [WARN] terraform: shadow graph disabled
2017/05/18 15:53:42 [INFO] terraform: building graph: GraphTypeRefresh
2017/05/18 15:53:42 [WARN] terraform: shadow graph disabled
2017/05/18 15:53:42 [INFO] Reading Librato Metric: tftest-metric-x4dlskaqoh
2017/05/18 15:53:42 [INFO] Read Librato Metric: {"name":"tftest-metric-x4dlskaqoh","description":"A test composite metric","type":"composite","composite":"s(\"librato.cpu.percent.user\", {\"environment\" : \"prod\", \"service\": \"api\"})","attributes":{"color":null,"display_max":null,"display_min":null,"display_units_long":"","display_units_short":"","display_stacked":true,"display_transform":"","created_by_ua":"go-librato/0.1"}}
2017/05/18 15:53:42 [INFO] terraform: building graph: GraphTypePlanDestroy
2017/05/18 15:53:42 [WARN] terraform: shadow graph disabled
2017/05/18 15:53:42 [WARN] Test: Step plan: DIFF:

DESTROY: librato_metric.foobar

STATE:

librato_metric.foobar:
  ID = tftest-metric-x4dlskaqoh
  attributes.# = 1
  attributes.0.aggregate = false
  attributes.0.color = 
  attributes.0.created_by_ua = go-librato/0.1
  attributes.0.display_max = 
  attributes.0.display_min = 
  attributes.0.display_stacked = true
  attributes.0.display_units_long = 
  attributes.0.display_units_short = 
  attributes.0.gap_detection = false
  composite = s("librato.cpu.percent.user", {"environment" : "prod", "service": "api"})
  description = A test composite metric
  name = tftest-metric-x4dlskaqoh
  type = composite
2017/05/18 15:53:42 [INFO] terraform: building graph: GraphTypeApply
2017/05/18 15:53:42 [WARN] terraform: shadow graph disabled
2017/05/18 15:53:42 [INFO] Deleting Metric: tftest-metric-x4dlskaqoh
2017/05/18 15:53:42 [INFO] Verifying Metric tftest-metric-x4dlskaqoh deleted
2017/05/18 15:53:42 [INFO] GETing Metric tftest-metric-x4dlskaqoh
2017/05/18 15:53:42 [INFO] GET returned a 404 for Metric tftest-metric-x4dlskaqoh
2017/05/18 15:53:42 [INFO] I think Metric is deleted
*** testAccCheckLibratoMetricDestroy ID: tftest-metric-x4dlskaqoh
2017/05/18 15:53:42 [INFO] terraform: building graph: GraphTypePlanDestroy
2017/05/18 15:53:42 [WARN] terraform: shadow graph disabled
2017/05/18 15:53:42 [INFO] terraform: building graph: GraphTypeRefresh
2017/05/18 15:53:42 [WARN] terraform: shadow graph disabled
2017/05/18 15:53:42 [INFO] terraform: building graph: GraphTypePlanDestroy
2017/05/18 15:53:42 [WARN] terraform: shadow graph disabled
--- FAIL: TestAccLibratoCompositeMetric (0.78s)
	testing.go:280: Step 0 error: After applying this step and refreshing, the plan was not empty:
		
		DIFF:
		
		UPDATE: librato_metric.foobar
		  attributes.0.created_by_ua: "go-librato/0.1" => ""
		
		STATE:
		
		librato_metric.foobar:
		  ID = tftest-metric-x4dlskaqoh
		  attributes.# = 1
		  attributes.0.aggregate = false
		  attributes.0.color = 
		  attributes.0.created_by_ua = go-librato/0.1
		  attributes.0.display_max = 
		  attributes.0.display_min = 
		  attributes.0.display_stacked = true
		  attributes.0.display_units_long = 
		  attributes.0.display_units_short = 
		  attributes.0.gap_detection = false
		  composite = s("librato.cpu.percent.user", {"environment" : "prod", "service": "api"})
		  description = A test composite metric
		  name = tftest-metric-x4dlskaqoh
		  type = composite
FAIL
exit status 1
FAIL	github.com/hashicorp/terraform/builtin/providers/librato	0.794s
make: *** [testacc] Error 1

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 the created_by_ua attribute needs to be marked as Computed: true to signal that its value is set by the server, not by users.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

aha!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That looks to be working!

}
}

func testAccCheckLibratoMetricType(metric *librato.Metric, validTypes []string) resource.TestCheckFunc {
Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like this could be testAccCheckLibratoMetricType(metric *librato.Metric, wantType string) resource.TestCheckFunc and provide more valuable test coverage for the cases where it's used.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@wchrisjohnson wchrisjohnson changed the title provider/librato: Enable mgmt of Librato metrics *** WIP *** provider/librato: Enable mgmt of Librato metrics May 18, 2017
@wchrisjohnson
Copy link
Contributor Author

@grubernaut @tombuildsstuff can I ping someone to review this, or can any Terraform or Librato engineer review/approve it? Excuse the ignorance... 😀

Copy link
Contributor

@grubernaut grubernaut left a comment

Choose a reason for hiding this comment

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

Left comments, nits, and suggestions. Happy to discuss any items further!
Also needs documentation for the new resource added. Thanks for the contribution!

)

// Encodes a hash into a JSON string
func attributesFlatten(attrs map[string]string) (string, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've deleted this file for now. There is a decent amount of duplication within the Librato plugin (as well as the AWS plugin) that needs to be rectified, but that's a task for another PR. :-) . If I need these though, I'll use them vs the Librato specific ones so as to get us started with removing them.

)

const (
metricTypeGauge = "gauge"
Copy link
Contributor

Choose a reason for hiding this comment

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

These constants aren't used anywhere... Is there a need for them?

Copy link
Contributor

Choose a reason for hiding this comment

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

If you need to validate the metric type, could also use the validation function StringInSlice, and pass in a slice of the valid metric types:

var validMetricTypes []string("gauge", "counter", "composite"} // Or use the constant types declared earlier
// ...
ValidateFunc: StringInSlice(validMetricTypes),

Delete: resourceLibratoMetricDelete,

Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: can remove the duplicate type declarations here:
&schema.Schema

Copy link
Contributor Author

Choose a reason for hiding this comment

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

wow, I see this ALL OVER the terraform plugin landscape... good to know!

client := meta.(*librato.Client)

metric := new(librato.Metric)
if a, ok := d.GetOk("name"); ok {
Copy link
Contributor

Choose a reason for hiding this comment

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

name and type are required, so they won't ever be nil during the Create method. Can initialize the librato.Metric struct with these values

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

metric.Description = librato.String(a.(string))
}
if a, ok := d.GetOk("period"); ok {
metric.Period = librato.Uint(a.(uint))
Copy link
Contributor

Choose a reason for hiding this comment

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

This will panic, as the interface a is an int and not a uint.
Need to cast it to an integer before an unsigned integer:

metric.Period = librato.Uint(uint(a.(int)))

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

Check: resource.ComposeTestCheckFunc(
testAccCheckLibratoMetricExists("librato_metric.foobar", &metric),
testAccCheckLibratoMetricName(&metric, name),
testAccCheckLibratoMetricType(&metric, typ),
Copy link
Contributor

Choose a reason for hiding this comment

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

Test that the description was actually updated.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

Config: compositeMetricConfig(name, typ, fmt.Sprintf("An updated test %s metric", typ)),
Check: resource.ComposeTestCheckFunc(
testAccCheckLibratoMetricExists("librato_metric.foobar", &metric),
testAccCheckLibratoMetricName(&metric, name),
Copy link
Contributor

Choose a reason for hiding this comment

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

Test that the description was actually updated.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

continue
}

fmt.Printf("*** testAccCheckLibratoMetricDestroy ID: %s\n", rs.Primary.ID)
Copy link
Contributor

Choose a reason for hiding this comment

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

Use log.Printf("[DEBUG] ....")

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed

@@ -37,49 +36,12 @@ func resourceLibratoService() *schema.Resource {
"settings": &schema.Schema{
Type: schema.TypeString,
Required: true,
StateFunc: normalizeJson,
StateFunc: normalizeJSON,
Copy link
Contributor

Choose a reason for hiding this comment

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

Can use the structure function here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed for now

@@ -91,7 +53,7 @@ func resourceLibratoServiceCreate(d *schema.ResourceData, meta interface{}) erro
service.Title = librato.String(v.(string))
}
if v, ok := d.GetOk("settings"); ok {
res, err := resourceLibratoServicesExpandSettings(normalizeJson(v.(string)))
res, err := attributesExpand(normalizeJSON(v.(string)))
Copy link
Contributor

Choose a reason for hiding this comment

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

Can use the structure function for the rest of these

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed for now

@wchrisjohnson
Copy link
Contributor Author

Thanks for the extensive review @grubernaut - I will dig in and get these comments addressed asap.

Much of the approach I took here was based on existing code in the Librato provider. COuld you point me toward another provider I could look at to get a better sense of best practices and good habits to embrace around terraform development?

@grubernaut
Copy link
Contributor

@wchrisjohnson anytime! I would check out some of the resources in the AWS provider, the OPC provider, or the Fastly provider. The code here looks good, was just giving as much feedback and knowledge as I could. Happy to help further wherever needed!

@grubernaut
Copy link
Contributor

Hey @wchrisjohnson, just remembered, we wrote a provider development guide that might help out as well: https://www.terraform.io/guides/writing-custom-terraform-providers.html.
Also happy to help if you have any further questions on either the guide, or any further clarification. Thanks!

@wchrisjohnson
Copy link
Contributor Author

@grubernaut I think this PR is ready to be reviewed again. Thanks in advance!

@wchrisjohnson
Copy link
Contributor Author

wchrisjohnson commented May 26, 2017

Could we please get another review of this PR? We'd very much like to start using this new module!

@stack72 @catsby

Copy link
Contributor

@grubernaut grubernaut left a comment

Choose a reason for hiding this comment

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

Thanks for this! LGTM!

@grubernaut grubernaut merged commit 840f974 into hashicorp:master May 26, 2017
@wchrisjohnson
Copy link
Contributor Author

wchrisjohnson commented May 26, 2017

Thanks @grubernaut !!!

I have a quick question. I work for Heroku. Does terraform have any sort of program to give commit rights to a provider and its modules if they work for the provider? We are wondering if one or more of us can get commit rights for the Heroku provider? If so, how would we go about that?

@wchrisjohnson wchrisjohnson deleted the cj-add-librato-metrics branch May 26, 2017 18:55
@stack72
Copy link
Contributor

stack72 commented May 28, 2017 via email

@elblivion elblivion mentioned this pull request Jun 6, 2017
@ghost
Copy link

ghost commented Apr 12, 2020

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@ghost ghost locked and limited conversation to collaborators Apr 12, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants