Merge branch 'henrikhodne-librato-provider'
This commit is contained in:
commit
0a679ef991
|
@ -787,6 +787,10 @@
|
||||||
"ImportPath": "github.com/hashicorp/yamux",
|
"ImportPath": "github.com/hashicorp/yamux",
|
||||||
"Rev": "df949784da9ed028ee76df44652e42d37a09d7e4"
|
"Rev": "df949784da9ed028ee76df44652e42d37a09d7e4"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/henrikhodne/go-librato/librato",
|
||||||
|
"Rev": "613abdebf4922c4d9d46bcb4bcf14ee18c08d7de"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/hmrc/vmware-govcd",
|
"ImportPath": "github.com/hmrc/vmware-govcd",
|
||||||
"Comment": "v0.0.2-37-g5cd82f0",
|
"Comment": "v0.0.2-37-g5cd82f0",
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/hashicorp/terraform/builtin/providers/librato"
|
||||||
|
"github.com/hashicorp/terraform/plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
plugin.Serve(&plugin.ServeOpts{
|
||||||
|
ProviderFunc: librato.Provider,
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
package main
|
|
@ -0,0 +1,41 @@
|
||||||
|
package librato
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
"github.com/henrikhodne/go-librato/librato"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Provider returns a schema.Provider for Librato.
|
||||||
|
func Provider() terraform.ResourceProvider {
|
||||||
|
return &schema.Provider{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"email": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
DefaultFunc: schema.EnvDefaultFunc("LIBRATO_EMAIL", nil),
|
||||||
|
Description: "The email address for the Librato account.",
|
||||||
|
},
|
||||||
|
|
||||||
|
"token": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
DefaultFunc: schema.EnvDefaultFunc("LIBRATO_TOKEN", nil),
|
||||||
|
Description: "The auth token for the Librato account.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
ResourcesMap: map[string]*schema.Resource{
|
||||||
|
"librato_space": resourceLibratoSpace(),
|
||||||
|
"librato_space_chart": resourceLibratoSpaceChart(),
|
||||||
|
},
|
||||||
|
|
||||||
|
ConfigureFunc: providerConfigure,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func providerConfigure(d *schema.ResourceData) (interface{}, error) {
|
||||||
|
client := librato.NewClient(d.Get("email").(string), d.Get("token").(string))
|
||||||
|
|
||||||
|
return client, nil
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package librato
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
var testAccProviders map[string]terraform.ResourceProvider
|
||||||
|
var testAccProvider *schema.Provider
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
testAccProvider = Provider().(*schema.Provider)
|
||||||
|
testAccProviders = map[string]terraform.ResourceProvider{
|
||||||
|
"librato": testAccProvider,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProvider(t *testing.T) {
|
||||||
|
if err := Provider().(*schema.Provider).InternalValidate(); err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProvider_impl(t *testing.T) {
|
||||||
|
var _ terraform.ResourceProvider = Provider()
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccPreCheck(t *testing.T) {
|
||||||
|
if v := os.Getenv("LIBRATO_EMAIL"); v == "" {
|
||||||
|
t.Fatal("LIBRATO_EMAIL must be set for acceptance tests")
|
||||||
|
}
|
||||||
|
|
||||||
|
if v := os.Getenv("LIBRATO_TOKEN"); v == "" {
|
||||||
|
t.Fatal("LIBRATO_TOKEN must be set for acceptance tests")
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,134 @@
|
||||||
|
package librato
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
"github.com/henrikhodne/go-librato/librato"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceLibratoSpace() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Create: resourceLibratoSpaceCreate,
|
||||||
|
Read: resourceLibratoSpaceRead,
|
||||||
|
Update: resourceLibratoSpaceUpdate,
|
||||||
|
Delete: resourceLibratoSpaceDelete,
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"name": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: false,
|
||||||
|
},
|
||||||
|
"id": &schema.Schema{
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceLibratoSpaceCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
client := meta.(*librato.Client)
|
||||||
|
|
||||||
|
name := d.Get("name").(string)
|
||||||
|
|
||||||
|
space, _, err := client.Spaces.Create(&librato.Space{Name: librato.String(name)})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error creating Librato space %s: %s", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resource.Retry(1*time.Minute, func() *resource.RetryError {
|
||||||
|
_, _, err := client.Spaces.Get(*space.ID)
|
||||||
|
if err != nil {
|
||||||
|
if errResp, ok := err.(*librato.ErrorResponse); ok && errResp.Response.StatusCode == 404 {
|
||||||
|
return resource.RetryableError(err)
|
||||||
|
}
|
||||||
|
return resource.NonRetryableError(err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
return resourceLibratoSpaceReadResult(d, space)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceLibratoSpaceRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
client := meta.(*librato.Client)
|
||||||
|
|
||||||
|
id, err := strconv.ParseUint(d.Id(), 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
space, _, err := client.Spaces.Get(uint(id))
|
||||||
|
if err != nil {
|
||||||
|
if errResp, ok := err.(*librato.ErrorResponse); ok && errResp.Response.StatusCode == 404 {
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fmt.Errorf("Error reading Librato Space %s: %s", d.Id(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceLibratoSpaceReadResult(d, space)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceLibratoSpaceReadResult(d *schema.ResourceData, space *librato.Space) error {
|
||||||
|
d.SetId(strconv.FormatUint(uint64(*space.ID), 10))
|
||||||
|
if err := d.Set("id", *space.ID); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := d.Set("name", *space.Name); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceLibratoSpaceUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
client := meta.(*librato.Client)
|
||||||
|
id, err := strconv.ParseUint(d.Id(), 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange("name") {
|
||||||
|
newName := d.Get("name").(string)
|
||||||
|
log.Printf("[INFO] Modifying name space attribute for %d: %#v", id, newName)
|
||||||
|
if _, err = client.Spaces.Edit(uint(id), &librato.Space{Name: &newName}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceLibratoSpaceRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceLibratoSpaceDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
client := meta.(*librato.Client)
|
||||||
|
id, err := strconv.ParseUint(d.Id(), 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[INFO] Deleting Space: %d", id)
|
||||||
|
_, err = client.Spaces.Delete(uint(id))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error deleting space: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resource.Retry(1*time.Minute, func() *resource.RetryError {
|
||||||
|
_, _, err := client.Spaces.Get(uint(id))
|
||||||
|
if err != nil {
|
||||||
|
if errResp, ok := err.(*librato.ErrorResponse); ok && errResp.Response.StatusCode == 404 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return resource.NonRetryableError(err)
|
||||||
|
}
|
||||||
|
return resource.RetryableError(fmt.Errorf("space still exists"))
|
||||||
|
})
|
||||||
|
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,447 @@
|
||||||
|
package librato
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"math"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/hashcode"
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
"github.com/henrikhodne/go-librato/librato"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceLibratoSpaceChart() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Create: resourceLibratoSpaceChartCreate,
|
||||||
|
Read: resourceLibratoSpaceChartRead,
|
||||||
|
Update: resourceLibratoSpaceChartUpdate,
|
||||||
|
Delete: resourceLibratoSpaceChartDelete,
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"space_id": &schema.Schema{
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
"name": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"type": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
"min": &schema.Schema{
|
||||||
|
Type: schema.TypeFloat,
|
||||||
|
Default: math.NaN(),
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"max": &schema.Schema{
|
||||||
|
Type: schema.TypeFloat,
|
||||||
|
Default: math.NaN(),
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"label": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"related_space": &schema.Schema{
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"stream": &schema.Schema{
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Optional: true,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"metric": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ConflictsWith: []string{"stream.composite"},
|
||||||
|
},
|
||||||
|
"source": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ConflictsWith: []string{"stream.composite"},
|
||||||
|
},
|
||||||
|
"group_function": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ConflictsWith: []string{"stream.composite"},
|
||||||
|
},
|
||||||
|
"composite": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ConflictsWith: []string{"stream.metric", "stream.source", "stream.group_function"},
|
||||||
|
},
|
||||||
|
"summary_function": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"name": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"color": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"units_short": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"units_long": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"min": &schema.Schema{
|
||||||
|
Type: schema.TypeFloat,
|
||||||
|
Default: math.NaN(),
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"max": &schema.Schema{
|
||||||
|
Type: schema.TypeFloat,
|
||||||
|
Default: math.NaN(),
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"transform_function": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"period": &schema.Schema{
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Set: resourceLibratoSpaceChartHash,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceLibratoSpaceChartHash(v interface{}) int {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
m := v.(map[string]interface{})
|
||||||
|
buf.WriteString(fmt.Sprintf("%s-", m["metric"].(string)))
|
||||||
|
buf.WriteString(fmt.Sprintf("%s-", m["source"].(string)))
|
||||||
|
buf.WriteString(fmt.Sprintf("%s-", m["composite"].(string)))
|
||||||
|
|
||||||
|
return hashcode.String(buf.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceLibratoSpaceChartCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
client := meta.(*librato.Client)
|
||||||
|
|
||||||
|
spaceID := uint(d.Get("space_id").(int))
|
||||||
|
|
||||||
|
spaceChart := new(librato.SpaceChart)
|
||||||
|
if v, ok := d.GetOk("name"); ok {
|
||||||
|
spaceChart.Name = librato.String(v.(string))
|
||||||
|
}
|
||||||
|
if v, ok := d.GetOk("type"); ok {
|
||||||
|
spaceChart.Type = librato.String(v.(string))
|
||||||
|
}
|
||||||
|
if v, ok := d.GetOk("min"); ok {
|
||||||
|
if math.IsNaN(v.(float64)) {
|
||||||
|
spaceChart.Min = nil
|
||||||
|
} else {
|
||||||
|
spaceChart.Min = librato.Float(v.(float64))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if v, ok := d.GetOk("max"); ok {
|
||||||
|
if math.IsNaN(v.(float64)) {
|
||||||
|
spaceChart.Max = nil
|
||||||
|
} else {
|
||||||
|
spaceChart.Max = librato.Float(v.(float64))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if v, ok := d.GetOk("label"); ok {
|
||||||
|
spaceChart.Label = librato.String(v.(string))
|
||||||
|
}
|
||||||
|
if v, ok := d.GetOk("related_space"); ok {
|
||||||
|
spaceChart.RelatedSpace = librato.Uint(uint(v.(int)))
|
||||||
|
}
|
||||||
|
if v, ok := d.GetOk("stream"); ok {
|
||||||
|
vs := v.(*schema.Set)
|
||||||
|
streams := make([]librato.SpaceChartStream, vs.Len())
|
||||||
|
for i, streamDataM := range vs.List() {
|
||||||
|
streamData := streamDataM.(map[string]interface{})
|
||||||
|
var stream librato.SpaceChartStream
|
||||||
|
if v, ok := streamData["metric"].(string); ok && v != "" {
|
||||||
|
stream.Metric = librato.String(v)
|
||||||
|
}
|
||||||
|
if v, ok := streamData["source"].(string); ok && v != "" {
|
||||||
|
stream.Source = librato.String(v)
|
||||||
|
}
|
||||||
|
if v, ok := streamData["composite"].(string); ok && v != "" {
|
||||||
|
stream.Composite = librato.String(v)
|
||||||
|
}
|
||||||
|
if v, ok := streamData["group_function"].(string); ok && v != "" {
|
||||||
|
stream.GroupFunction = librato.String(v)
|
||||||
|
}
|
||||||
|
if v, ok := streamData["summary_function"].(string); ok && v != "" {
|
||||||
|
stream.SummaryFunction = librato.String(v)
|
||||||
|
}
|
||||||
|
if v, ok := streamData["transform_function"].(string); ok && v != "" {
|
||||||
|
stream.TransformFunction = librato.String(v)
|
||||||
|
}
|
||||||
|
if v, ok := streamData["color"].(string); ok && v != "" {
|
||||||
|
stream.Color = librato.String(v)
|
||||||
|
}
|
||||||
|
if v, ok := streamData["units_short"].(string); ok && v != "" {
|
||||||
|
stream.UnitsShort = librato.String(v)
|
||||||
|
}
|
||||||
|
if v, ok := streamData["units_longs"].(string); ok && v != "" {
|
||||||
|
stream.UnitsLong = librato.String(v)
|
||||||
|
}
|
||||||
|
if v, ok := streamData["min"].(float64); ok && !math.IsNaN(v) {
|
||||||
|
stream.Min = librato.Float(v)
|
||||||
|
}
|
||||||
|
if v, ok := streamData["max"].(float64); ok && !math.IsNaN(v) {
|
||||||
|
stream.Max = librato.Float(v)
|
||||||
|
}
|
||||||
|
streams[i] = stream
|
||||||
|
}
|
||||||
|
spaceChart.Streams = streams
|
||||||
|
}
|
||||||
|
|
||||||
|
spaceChartResult, _, err := client.Spaces.CreateChart(spaceID, spaceChart)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error creating Librato space chart %s: %s", *spaceChart.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resource.Retry(1*time.Minute, func() *resource.RetryError {
|
||||||
|
_, _, err := client.Spaces.GetChart(spaceID, *spaceChartResult.ID)
|
||||||
|
if err != nil {
|
||||||
|
if errResp, ok := err.(*librato.ErrorResponse); ok && errResp.Response.StatusCode == 404 {
|
||||||
|
return resource.RetryableError(err)
|
||||||
|
}
|
||||||
|
return resource.NonRetryableError(err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
return resourceLibratoSpaceChartReadResult(d, spaceChartResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceLibratoSpaceChartRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
client := meta.(*librato.Client)
|
||||||
|
|
||||||
|
spaceID := uint(d.Get("space_id").(int))
|
||||||
|
|
||||||
|
id, err := strconv.ParseUint(d.Id(), 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
chart, _, err := client.Spaces.GetChart(spaceID, uint(id))
|
||||||
|
if err != nil {
|
||||||
|
if errResp, ok := err.(*librato.ErrorResponse); ok && errResp.Response.StatusCode == 404 {
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fmt.Errorf("Error reading Librato Space chart %s: %s", d.Id(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceLibratoSpaceChartReadResult(d, chart)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceLibratoSpaceChartReadResult(d *schema.ResourceData, chart *librato.SpaceChart) error {
|
||||||
|
d.SetId(strconv.FormatUint(uint64(*chart.ID), 10))
|
||||||
|
if chart.Name != nil {
|
||||||
|
if err := d.Set("name", *chart.Name); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if chart.Type != nil {
|
||||||
|
if err := d.Set("type", *chart.Type); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if chart.Min != nil {
|
||||||
|
if err := d.Set("min", *chart.Min); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if chart.Max != nil {
|
||||||
|
if err := d.Set("max", *chart.Max); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if chart.Label != nil {
|
||||||
|
if err := d.Set("label", *chart.Label); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if chart.RelatedSpace != nil {
|
||||||
|
if err := d.Set("related_space", *chart.RelatedSpace); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
streams := resourceLibratoSpaceChartStreamsGather(d, chart.Streams)
|
||||||
|
if err := d.Set("stream", streams); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceLibratoSpaceChartStreamsGather(d *schema.ResourceData, streams []librato.SpaceChartStream) []map[string]interface{} {
|
||||||
|
retStreams := make([]map[string]interface{}, 0, len(streams))
|
||||||
|
for _, s := range streams {
|
||||||
|
stream := make(map[string]interface{})
|
||||||
|
if s.Metric != nil {
|
||||||
|
stream["metric"] = *s.Metric
|
||||||
|
}
|
||||||
|
if s.Source != nil {
|
||||||
|
stream["source"] = *s.Source
|
||||||
|
}
|
||||||
|
if s.Composite != nil {
|
||||||
|
stream["composite"] = *s.Composite
|
||||||
|
}
|
||||||
|
if s.GroupFunction != nil {
|
||||||
|
stream["group_function"] = *s.GroupFunction
|
||||||
|
}
|
||||||
|
if s.SummaryFunction != nil {
|
||||||
|
stream["summary_function"] = *s.SummaryFunction
|
||||||
|
}
|
||||||
|
if s.TransformFunction != nil {
|
||||||
|
stream["transform_function"] = *s.TransformFunction
|
||||||
|
}
|
||||||
|
if s.Color != nil {
|
||||||
|
stream["color"] = *s.Color
|
||||||
|
}
|
||||||
|
if s.UnitsShort != nil {
|
||||||
|
stream["units_short"] = *s.UnitsShort
|
||||||
|
}
|
||||||
|
if s.UnitsLong != nil {
|
||||||
|
stream["units_long"] = *s.UnitsLong
|
||||||
|
}
|
||||||
|
retStreams = append(retStreams, stream)
|
||||||
|
}
|
||||||
|
|
||||||
|
return retStreams
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceLibratoSpaceChartUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
client := meta.(*librato.Client)
|
||||||
|
|
||||||
|
spaceID := uint(d.Get("space_id").(int))
|
||||||
|
chartID, err := strconv.ParseUint(d.Id(), 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
spaceChart := new(librato.SpaceChart)
|
||||||
|
if d.HasChange("name") {
|
||||||
|
spaceChart.Name = librato.String(d.Get("name").(string))
|
||||||
|
}
|
||||||
|
if d.HasChange("min") {
|
||||||
|
if math.IsNaN(d.Get("min").(float64)) {
|
||||||
|
spaceChart.Min = nil
|
||||||
|
} else {
|
||||||
|
spaceChart.Min = librato.Float(d.Get("min").(float64))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if d.HasChange("max") {
|
||||||
|
if math.IsNaN(d.Get("max").(float64)) {
|
||||||
|
spaceChart.Max = nil
|
||||||
|
} else {
|
||||||
|
spaceChart.Max = librato.Float(d.Get("max").(float64))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if d.HasChange("label") {
|
||||||
|
spaceChart.Label = librato.String(d.Get("label").(string))
|
||||||
|
}
|
||||||
|
if d.HasChange("related_space") {
|
||||||
|
spaceChart.RelatedSpace = librato.Uint(d.Get("related_space").(uint))
|
||||||
|
}
|
||||||
|
if d.HasChange("stream") {
|
||||||
|
vs := d.Get("stream").(*schema.Set)
|
||||||
|
streams := make([]librato.SpaceChartStream, vs.Len())
|
||||||
|
for i, streamDataM := range vs.List() {
|
||||||
|
streamData := streamDataM.(map[string]interface{})
|
||||||
|
var stream librato.SpaceChartStream
|
||||||
|
if v, ok := streamData["metric"].(string); ok && v != "" {
|
||||||
|
stream.Metric = librato.String(v)
|
||||||
|
}
|
||||||
|
if v, ok := streamData["source"].(string); ok && v != "" {
|
||||||
|
stream.Source = librato.String(v)
|
||||||
|
}
|
||||||
|
if v, ok := streamData["composite"].(string); ok && v != "" {
|
||||||
|
stream.Composite = librato.String(v)
|
||||||
|
}
|
||||||
|
if v, ok := streamData["group_function"].(string); ok && v != "" {
|
||||||
|
stream.GroupFunction = librato.String(v)
|
||||||
|
}
|
||||||
|
if v, ok := streamData["summary_function"].(string); ok && v != "" {
|
||||||
|
stream.SummaryFunction = librato.String(v)
|
||||||
|
}
|
||||||
|
if v, ok := streamData["transform_function"].(string); ok && v != "" {
|
||||||
|
stream.TransformFunction = librato.String(v)
|
||||||
|
}
|
||||||
|
if v, ok := streamData["color"].(string); ok && v != "" {
|
||||||
|
stream.Color = librato.String(v)
|
||||||
|
}
|
||||||
|
if v, ok := streamData["units_short"].(string); ok && v != "" {
|
||||||
|
stream.UnitsShort = librato.String(v)
|
||||||
|
}
|
||||||
|
if v, ok := streamData["units_longs"].(string); ok && v != "" {
|
||||||
|
stream.UnitsLong = librato.String(v)
|
||||||
|
}
|
||||||
|
if v, ok := streamData["min"].(float64); ok && !math.IsNaN(v) {
|
||||||
|
stream.Min = librato.Float(v)
|
||||||
|
}
|
||||||
|
if v, ok := streamData["max"].(float64); ok && !math.IsNaN(v) {
|
||||||
|
stream.Max = librato.Float(v)
|
||||||
|
}
|
||||||
|
streams[i] = stream
|
||||||
|
}
|
||||||
|
spaceChart.Streams = streams
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = client.Spaces.EditChart(spaceID, uint(chartID), spaceChart)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error updating Librato space chart %s: %s", *spaceChart.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceLibratoSpaceChartRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceLibratoSpaceChartDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
client := meta.(*librato.Client)
|
||||||
|
|
||||||
|
spaceID := uint(d.Get("space_id").(int))
|
||||||
|
|
||||||
|
id, err := strconv.ParseUint(d.Id(), 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[INFO] Deleting Chart: %d/%d", spaceID, uint(id))
|
||||||
|
_, err = client.Spaces.DeleteChart(spaceID, uint(id))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error deleting space: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resource.Retry(1*time.Minute, func() *resource.RetryError {
|
||||||
|
_, _, err := client.Spaces.GetChart(spaceID, uint(id))
|
||||||
|
if err != nil {
|
||||||
|
if errResp, ok := err.(*librato.ErrorResponse); ok && errResp.Response.StatusCode == 404 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return resource.NonRetryableError(err)
|
||||||
|
}
|
||||||
|
return resource.RetryableError(fmt.Errorf("space chart still exists"))
|
||||||
|
})
|
||||||
|
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,230 @@
|
||||||
|
package librato
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
"github.com/henrikhodne/go-librato/librato"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccLibratoSpaceChart_Basic(t *testing.T) {
|
||||||
|
var spaceChart librato.SpaceChart
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckLibratoSpaceChartDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccCheckLibratoSpaceChartConfig_basic,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckLibratoSpaceChartExists("librato_space_chart.foobar", &spaceChart),
|
||||||
|
testAccCheckLibratoSpaceChartName(&spaceChart, "Foo Bar"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"librato_space_chart.foobar", "name", "Foo Bar"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccLibratoSpaceChart_Full(t *testing.T) {
|
||||||
|
var spaceChart librato.SpaceChart
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckLibratoSpaceChartDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccCheckLibratoSpaceChartConfig_full,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckLibratoSpaceChartExists("librato_space_chart.foobar", &spaceChart),
|
||||||
|
testAccCheckLibratoSpaceChartName(&spaceChart, "Foo Bar"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"librato_space_chart.foobar", "name", "Foo Bar"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccLibratoSpaceChart_Updated(t *testing.T) {
|
||||||
|
var spaceChart librato.SpaceChart
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckLibratoSpaceChartDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccCheckLibratoSpaceChartConfig_basic,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckLibratoSpaceChartExists("librato_space_chart.foobar", &spaceChart),
|
||||||
|
testAccCheckLibratoSpaceChartName(&spaceChart, "Foo Bar"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"librato_space_chart.foobar", "name", "Foo Bar"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccCheckLibratoSpaceChartConfig_new_value,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckLibratoSpaceChartExists("librato_space_chart.foobar", &spaceChart),
|
||||||
|
testAccCheckLibratoSpaceChartName(&spaceChart, "Bar Baz"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"librato_space_chart.foobar", "name", "Bar Baz"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckLibratoSpaceChartDestroy(s *terraform.State) error {
|
||||||
|
client := testAccProvider.Meta().(*librato.Client)
|
||||||
|
|
||||||
|
for _, rs := range s.RootModule().Resources {
|
||||||
|
if rs.Type != "librato_space_chart" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
id, err := strconv.ParseUint(rs.Primary.ID, 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("ID not a number")
|
||||||
|
}
|
||||||
|
|
||||||
|
spaceID, err := strconv.ParseUint(rs.Primary.Attributes["space_id"], 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Space ID not a number")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err = client.Spaces.GetChart(uint(spaceID), uint(id))
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
return fmt.Errorf("Space Chart still exists")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckLibratoSpaceChartName(spaceChart *librato.SpaceChart, name string) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
|
||||||
|
if spaceChart.Name == nil || *spaceChart.Name != name {
|
||||||
|
return fmt.Errorf("Bad name: %s", *spaceChart.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckLibratoSpaceChartExists(n string, spaceChart *librato.SpaceChart) 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 Space Chart ID is set")
|
||||||
|
}
|
||||||
|
|
||||||
|
client := testAccProvider.Meta().(*librato.Client)
|
||||||
|
|
||||||
|
id, err := strconv.ParseUint(rs.Primary.ID, 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("ID not a number")
|
||||||
|
}
|
||||||
|
|
||||||
|
spaceID, err := strconv.ParseUint(rs.Primary.Attributes["space_id"], 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Space ID not a number")
|
||||||
|
}
|
||||||
|
|
||||||
|
foundSpaceChart, _, err := client.Spaces.GetChart(uint(spaceID), uint(id))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if foundSpaceChart.ID == nil || *foundSpaceChart.ID != uint(id) {
|
||||||
|
return fmt.Errorf("Space not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
*spaceChart = *foundSpaceChart
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const testAccCheckLibratoSpaceChartConfig_basic = `
|
||||||
|
resource "librato_space" "foobar" {
|
||||||
|
name = "Foo Bar"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "librato_space_chart" "foobar" {
|
||||||
|
space_id = "${librato_space.foobar.id}"
|
||||||
|
name = "Foo Bar"
|
||||||
|
type = "line"
|
||||||
|
}`
|
||||||
|
|
||||||
|
const testAccCheckLibratoSpaceChartConfig_new_value = `
|
||||||
|
resource "librato_space" "foobar" {
|
||||||
|
name = "Foo Bar"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "librato_space_chart" "foobar" {
|
||||||
|
space_id = "${librato_space.foobar.id}"
|
||||||
|
name = "Bar Baz"
|
||||||
|
type = "line"
|
||||||
|
}`
|
||||||
|
|
||||||
|
const testAccCheckLibratoSpaceChartConfig_full = `
|
||||||
|
resource "librato_space" "foobar" {
|
||||||
|
name = "Foo Bar"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "librato_space" "barbaz" {
|
||||||
|
name = "Bar Baz"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "librato_space_chart" "foobar" {
|
||||||
|
space_id = "${librato_space.foobar.id}"
|
||||||
|
name = "Foo Bar"
|
||||||
|
type = "line"
|
||||||
|
min = 0
|
||||||
|
max = 100
|
||||||
|
label = "Percent"
|
||||||
|
related_space = "${librato_space.barbaz.id}"
|
||||||
|
|
||||||
|
# Minimal metric stream
|
||||||
|
stream {
|
||||||
|
metric = "librato.cpu.percent.idle"
|
||||||
|
source = "*"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Minimal composite stream
|
||||||
|
stream {
|
||||||
|
composite = "s(\"cpu\", \"*\")"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Full metric stream
|
||||||
|
stream {
|
||||||
|
metric = "librato.cpu.percent.idle"
|
||||||
|
source = "*"
|
||||||
|
group_function = "average"
|
||||||
|
summary_function = "max"
|
||||||
|
name = "CPU usage"
|
||||||
|
color = "#990000"
|
||||||
|
units_short = "%"
|
||||||
|
units_long = "percent"
|
||||||
|
min = 0
|
||||||
|
max = 100
|
||||||
|
transform_function = "x * 100"
|
||||||
|
period = 60
|
||||||
|
}
|
||||||
|
}`
|
|
@ -0,0 +1,106 @@
|
||||||
|
package librato
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
"github.com/henrikhodne/go-librato/librato"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccLibratoSpace_Basic(t *testing.T) {
|
||||||
|
var space librato.Space
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckLibratoSpaceDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccCheckLibratoSpaceConfig_basic,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckLibratoSpaceExists("librato_space.foobar", &space),
|
||||||
|
testAccCheckLibratoSpaceAttributes(&space),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"librato_space.foobar", "name", "Foo Bar"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckLibratoSpaceDestroy(s *terraform.State) error {
|
||||||
|
client := testAccProvider.Meta().(*librato.Client)
|
||||||
|
|
||||||
|
for _, rs := range s.RootModule().Resources {
|
||||||
|
if rs.Type != "librato_space" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
id, err := strconv.ParseUint(rs.Primary.ID, 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("ID not a number")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err = client.Spaces.Get(uint(id))
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
return fmt.Errorf("Space still exists")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckLibratoSpaceAttributes(space *librato.Space) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
|
||||||
|
if space.Name == nil || *space.Name != "Foo Bar" {
|
||||||
|
return fmt.Errorf("Bad name: %s", *space.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckLibratoSpaceExists(n string, space *librato.Space) 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 Space ID is set")
|
||||||
|
}
|
||||||
|
|
||||||
|
client := testAccProvider.Meta().(*librato.Client)
|
||||||
|
|
||||||
|
id, err := strconv.ParseUint(rs.Primary.ID, 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("ID not a number")
|
||||||
|
}
|
||||||
|
|
||||||
|
foundSpace, _, err := client.Spaces.Get(uint(id))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if foundSpace.ID == nil || *foundSpace.ID != uint(id) {
|
||||||
|
return fmt.Errorf("Space not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
*space = *foundSpace
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const testAccCheckLibratoSpaceConfig_basic = `
|
||||||
|
resource "librato_space" "foobar" {
|
||||||
|
name = "Foo Bar"
|
||||||
|
}`
|
|
@ -0,0 +1,21 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright 2015 Henrik Hodne
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
|
@ -0,0 +1,282 @@
|
||||||
|
package librato
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/google/go-querystring/query"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
libraryVersion = "0.1"
|
||||||
|
defaultBaseURL = "https://metrics-api.librato.com/v1/"
|
||||||
|
userAgent = "go-librato/" + libraryVersion
|
||||||
|
|
||||||
|
defaultMediaType = "application/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Client manages communication with the Librato API.
|
||||||
|
type Client struct {
|
||||||
|
// HTTP client used to communicate with the API
|
||||||
|
client *http.Client
|
||||||
|
|
||||||
|
// Headers to attach to every request made with the client. Headers will be
|
||||||
|
// used to provide Librato API authentication details and other necessary
|
||||||
|
// headers.
|
||||||
|
Headers map[string]string
|
||||||
|
|
||||||
|
// Email and Token contains the authentication details needed to authenticate
|
||||||
|
// against the Librato API.
|
||||||
|
Email, Token string
|
||||||
|
|
||||||
|
// Base URL for API requests. Defaults to the public Librato API, but can be
|
||||||
|
// set to an alternate endpoint if necessary. BaseURL should always be
|
||||||
|
// terminated by a slash.
|
||||||
|
BaseURL *url.URL
|
||||||
|
|
||||||
|
// User agent used when communicating with the Librato API.
|
||||||
|
UserAgent string
|
||||||
|
|
||||||
|
// Services used to manipulate API entities.
|
||||||
|
Spaces *SpacesService
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewClient returns a new Librato API client bound to the public Librato API.
|
||||||
|
func NewClient(email, token string) *Client {
|
||||||
|
bu, err := url.Parse(defaultBaseURL)
|
||||||
|
if err != nil {
|
||||||
|
panic("Default Librato API base URL couldn't be parsed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewClientWithBaseURL(bu, email, token)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewClientWithBaseURL returned a new Librato API client with a custom base URL.
|
||||||
|
func NewClientWithBaseURL(baseURL *url.URL, email, token string) *Client {
|
||||||
|
headers := map[string]string{
|
||||||
|
"Content-Type": defaultMediaType,
|
||||||
|
"Accept": defaultMediaType,
|
||||||
|
}
|
||||||
|
|
||||||
|
c := &Client{
|
||||||
|
client: http.DefaultClient,
|
||||||
|
Headers: headers,
|
||||||
|
Email: email,
|
||||||
|
Token: token,
|
||||||
|
BaseURL: baseURL,
|
||||||
|
UserAgent: userAgent,
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Spaces = &SpacesService{client: c}
|
||||||
|
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewRequest creates an API request. A relative URL can be provided in urlStr,
|
||||||
|
// in which case it is resolved relative to the BaseURL of the Client.
|
||||||
|
// Relative URLs should always be specified without a preceding slash. If
|
||||||
|
// specified, the value pointed to by body is JSON encoded and included as the
|
||||||
|
// request body. If specified, the map provided by headers will be used to
|
||||||
|
// update request headers.
|
||||||
|
func (c *Client) NewRequest(method, urlStr string, body interface{}) (*http.Request, error) {
|
||||||
|
rel, err := url.Parse(urlStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
u := c.BaseURL.ResolveReference(rel)
|
||||||
|
|
||||||
|
var buf io.ReadWriter
|
||||||
|
if body != nil {
|
||||||
|
buf = new(bytes.Buffer)
|
||||||
|
err := json.NewEncoder(buf).Encode(body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequest(method, u.String(), buf)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
req.SetBasicAuth(c.Email, c.Token)
|
||||||
|
if c.UserAgent != "" {
|
||||||
|
req.Header.Set("User-Agent", c.UserAgent)
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range c.Headers {
|
||||||
|
req.Header.Set(k, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return req, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do sends an API request and returns the API response. The API response is
|
||||||
|
// JSON decoded and stored in the value pointed to by v, or returned as an
|
||||||
|
// error if an API error has occurred. If v implements the io.Writer
|
||||||
|
// interface, the raw response body will be written to v, without attempting to
|
||||||
|
// first decode it.
|
||||||
|
func (c *Client) Do(req *http.Request, v interface{}) (*http.Response, error) {
|
||||||
|
resp, err := c.client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
err = CheckResponse(resp)
|
||||||
|
if err != nil {
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if v != nil {
|
||||||
|
if w, ok := v.(io.Writer); ok {
|
||||||
|
_, err = io.Copy(w, resp.Body)
|
||||||
|
} else {
|
||||||
|
err = json.NewDecoder(resp.Body).Decode(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrorResponse reports an error caused by an API request.
|
||||||
|
// ErrorResponse implements the Error interface.
|
||||||
|
type ErrorResponse struct {
|
||||||
|
// HTTP response that caused this error
|
||||||
|
Response *http.Response
|
||||||
|
|
||||||
|
// Error messages produces by Librato API.
|
||||||
|
Errors ErrorResponseMessages `json:"errors"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (er *ErrorResponse) Error() string {
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
|
||||||
|
if er.Errors.Params != nil && len(er.Errors.Params) > 0 {
|
||||||
|
buf.WriteString(" Parameter errors:")
|
||||||
|
for param, errs := range er.Errors.Params {
|
||||||
|
fmt.Fprintf(buf, " %s:", param)
|
||||||
|
for _, err := range errs {
|
||||||
|
fmt.Fprintf(buf, " %s,", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf.WriteString(".")
|
||||||
|
}
|
||||||
|
|
||||||
|
if er.Errors.Request != nil && len(er.Errors.Request) > 0 {
|
||||||
|
buf.WriteString(" Request errors:")
|
||||||
|
for _, err := range er.Errors.Request {
|
||||||
|
fmt.Fprintf(buf, " %s,", err)
|
||||||
|
}
|
||||||
|
buf.WriteString(".")
|
||||||
|
}
|
||||||
|
|
||||||
|
if er.Errors.System != nil && len(er.Errors.System) > 0 {
|
||||||
|
buf.WriteString(" System errors:")
|
||||||
|
for _, err := range er.Errors.System {
|
||||||
|
fmt.Fprintf(buf, " %s,", err)
|
||||||
|
}
|
||||||
|
buf.WriteString(".")
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf(
|
||||||
|
"%v %v: %d %v",
|
||||||
|
er.Response.Request.Method,
|
||||||
|
er.Response.Request.URL,
|
||||||
|
er.Response.StatusCode,
|
||||||
|
buf.String(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrorResponseMessages contains error messages returned from the Librato API.
|
||||||
|
type ErrorResponseMessages struct {
|
||||||
|
Params map[string][]string `json:"params,omitempty"`
|
||||||
|
Request []string `json:"request,omitempty"`
|
||||||
|
System []string `json:"system,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckResponse checks the API response for errors; and returns them if
|
||||||
|
// present. A Response is considered an error if it has a status code outside
|
||||||
|
// the 2XX range.
|
||||||
|
func CheckResponse(r *http.Response) error {
|
||||||
|
if c := r.StatusCode; 200 <= c && c <= 299 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
errorResponse := &ErrorResponse{Response: r}
|
||||||
|
|
||||||
|
data, err := ioutil.ReadAll(r.Body)
|
||||||
|
if err == nil && data != nil {
|
||||||
|
json.Unmarshal(data, errorResponse)
|
||||||
|
}
|
||||||
|
|
||||||
|
return errorResponse
|
||||||
|
}
|
||||||
|
|
||||||
|
func urlWithOptions(s string, opt interface{}) (string, error) {
|
||||||
|
rv := reflect.ValueOf(opt)
|
||||||
|
if rv.Kind() == reflect.Ptr && rv.IsNil() {
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
u, err := url.Parse(s)
|
||||||
|
if err != nil {
|
||||||
|
return s, err
|
||||||
|
}
|
||||||
|
|
||||||
|
qs, err := query.Values(opt)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
u.RawQuery = qs.Encode()
|
||||||
|
|
||||||
|
return u.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bool is a helper routine that allocates a new bool value
|
||||||
|
// to store v and returns a pointer to it.
|
||||||
|
func Bool(v bool) *bool {
|
||||||
|
p := new(bool)
|
||||||
|
*p = v
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int is a helper routine that allocates a new int32 value
|
||||||
|
// to store v and returns a pointer to it, but unlike Int32
|
||||||
|
// its argument value is an int.
|
||||||
|
func Int(v int) *int {
|
||||||
|
p := new(int)
|
||||||
|
*p = v
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uint is a helper routine that allocates a new uint value
|
||||||
|
// to store v and returns a pointer to it.
|
||||||
|
func Uint(v uint) *uint {
|
||||||
|
p := new(uint)
|
||||||
|
*p = v
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// String is a helper routine that allocates a new string value
|
||||||
|
// to store v and returns a pointer to it.
|
||||||
|
func String(v string) *string {
|
||||||
|
p := new(string)
|
||||||
|
*p = v
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float is a helper routine that allocates a new float64 value
|
||||||
|
// to store v and returns a pointer to it.
|
||||||
|
func Float(v float64) *float64 {
|
||||||
|
p := new(float64)
|
||||||
|
*p = v
|
||||||
|
return p
|
||||||
|
}
|
|
@ -0,0 +1,123 @@
|
||||||
|
package librato
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SpacesService handles communication with the Librato API methods related to
|
||||||
|
// spaces.
|
||||||
|
type SpacesService struct {
|
||||||
|
client *Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// Space represents a Librato Space.
|
||||||
|
type Space struct {
|
||||||
|
Name *string `json:"name"`
|
||||||
|
ID *uint `json:"id,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Space) String() string {
|
||||||
|
return Stringify(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SpaceListOptions specifies the optional parameters to the SpaceService.Find
|
||||||
|
// method.
|
||||||
|
type SpaceListOptions struct {
|
||||||
|
// filter by name
|
||||||
|
Name string `url:"name,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type listSpacesResponse struct {
|
||||||
|
Spaces []Space `json:"spaces"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// List spaces using the provided options.
|
||||||
|
//
|
||||||
|
// Librato API docs: http://dev.librato.com/v1/get/spaces
|
||||||
|
func (s *SpacesService) List(opt *SpaceListOptions) ([]Space, *http.Response, error) {
|
||||||
|
u, err := urlWithOptions("spaces", opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := s.client.NewRequest("GET", u, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var spacesResp listSpacesResponse
|
||||||
|
resp, err := s.client.Do(req, &spacesResp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return spacesResp.Spaces, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get fetches a space based on the provided ID.
|
||||||
|
//
|
||||||
|
// Librato API docs: http://dev.librato.com/v1/get/spaces/:id
|
||||||
|
func (s *SpacesService) Get(id uint) (*Space, *http.Response, error) {
|
||||||
|
u, err := urlWithOptions(fmt.Sprintf("spaces/%d", id), nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := s.client.NewRequest("GET", u, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
sp := new(Space)
|
||||||
|
resp, err := s.client.Do(req, sp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return sp, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a space with a given name.
|
||||||
|
//
|
||||||
|
// Librato API docs: http://dev.librato.com/v1/post/spaces
|
||||||
|
func (s *SpacesService) Create(space *Space) (*Space, *http.Response, error) {
|
||||||
|
req, err := s.client.NewRequest("POST", "spaces", space)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
sp := new(Space)
|
||||||
|
resp, err := s.client.Do(req, sp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return sp, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Edit a space.
|
||||||
|
//
|
||||||
|
// Librato API docs: http://dev.librato.com/v1/put/spaces/:id
|
||||||
|
func (s *SpacesService) Edit(spaceID uint, space *Space) (*http.Response, error) {
|
||||||
|
u := fmt.Sprintf("spaces/%d", spaceID)
|
||||||
|
req, err := s.client.NewRequest("PUT", u, space)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.client.Do(req, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete a space.
|
||||||
|
//
|
||||||
|
// Librato API docs: http://dev.librato.com/v1/delete/spaces/:id
|
||||||
|
func (s *SpacesService) Delete(id uint) (*http.Response, error) {
|
||||||
|
u := fmt.Sprintf("spaces/%d", id)
|
||||||
|
req, err := s.client.NewRequest("DELETE", u, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.client.Do(req, nil)
|
||||||
|
}
|
118
vendor/github.com/henrikhodne/go-librato/librato/spaces_charts.go
generated
vendored
Normal file
118
vendor/github.com/henrikhodne/go-librato/librato/spaces_charts.go
generated
vendored
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
package librato
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SpaceChart represents a chart in a Librato Space.
|
||||||
|
type SpaceChart struct {
|
||||||
|
ID *uint `json:"id,omitempty"`
|
||||||
|
Name *string `json:"name,omitempty"`
|
||||||
|
Type *string `json:"type,omitempty"`
|
||||||
|
Min *float64 `json:"min,omitempty"`
|
||||||
|
Max *float64 `json:"max,omitempty"`
|
||||||
|
Label *string `json:"label,omitempty"`
|
||||||
|
RelatedSpace *uint `json:"related_space,omitempty"`
|
||||||
|
Streams []SpaceChartStream `json:"streams,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SpaceChartStream represents a single stream in a chart in a Librato Space.
|
||||||
|
type SpaceChartStream struct {
|
||||||
|
Metric *string `json:"metric,omitempty"`
|
||||||
|
Source *string `json:"source,omitempty"`
|
||||||
|
Composite *string `json:"composite,omitempty"`
|
||||||
|
GroupFunction *string `json:"group_function,omitempty"`
|
||||||
|
SummaryFunction *string `json:"summary_function,omitempty"`
|
||||||
|
Color *string `json:"color,omitempty"`
|
||||||
|
Name *string `json:"name,omitempty"`
|
||||||
|
UnitsShort *string `json:"units_short,omitempty"`
|
||||||
|
UnitsLong *string `json:"units_long,omitempty"`
|
||||||
|
Min *float64 `json:"min,omitempty"`
|
||||||
|
Max *float64 `json:"max,omitempty"`
|
||||||
|
TransformFunction *string `json:"transform_function,omitempty"`
|
||||||
|
Period *int64 `json:"period,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateChart creates a chart in a given Librato Space.
|
||||||
|
//
|
||||||
|
// Librato API docs: http://dev.librato.com/v1/post/spaces/:id/charts
|
||||||
|
func (s *SpacesService) CreateChart(spaceID uint, chart *SpaceChart) (*SpaceChart, *http.Response, error) {
|
||||||
|
u := fmt.Sprintf("spaces/%d/charts", spaceID)
|
||||||
|
req, err := s.client.NewRequest("POST", u, chart)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
c := new(SpaceChart)
|
||||||
|
resp, err := s.client.Do(req, c)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return c, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListCharts lists all charts in a given Librato Space.
|
||||||
|
//
|
||||||
|
// Librato API docs: http://dev.librato.com/v1/get/spaces/:id/charts
|
||||||
|
func (s *SpacesService) ListCharts(spaceID uint) ([]SpaceChart, *http.Response, error) {
|
||||||
|
u := fmt.Sprintf("spaces/%d/charts", spaceID)
|
||||||
|
req, err := s.client.NewRequest("GET", u, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
charts := new([]SpaceChart)
|
||||||
|
resp, err := s.client.Do(req, charts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return *charts, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetChart gets a chart with a given ID in a space with a given ID.
|
||||||
|
//
|
||||||
|
// Librato API docs: http://dev.librato.com/v1/get/spaces/:id/charts
|
||||||
|
func (s *SpacesService) GetChart(spaceID, chartID uint) (*SpaceChart, *http.Response, error) {
|
||||||
|
u := fmt.Sprintf("spaces/%d/charts/%d", spaceID, chartID)
|
||||||
|
req, err := s.client.NewRequest("GET", u, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
c := new(SpaceChart)
|
||||||
|
resp, err := s.client.Do(req, c)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return c, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditChart edits a chart.
|
||||||
|
//
|
||||||
|
// Librato API docs: http://dev.librato.com/v1/put/spaces/:id/charts/:id
|
||||||
|
func (s *SpacesService) EditChart(spaceID, chartID uint, chart *SpaceChart) (*http.Response, error) {
|
||||||
|
u := fmt.Sprintf("spaces/%d/charts/%d", spaceID, chartID)
|
||||||
|
req, err := s.client.NewRequest("PUT", u, chart)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.client.Do(req, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteChart deletes a chart.
|
||||||
|
//
|
||||||
|
// Librato API docs: http://dev.librato.com/v1/delete/spaces/:id/charts/:id
|
||||||
|
func (s *SpacesService) DeleteChart(spaceID, chartID uint) (*http.Response, error) {
|
||||||
|
u := fmt.Sprintf("spaces/%d/charts/%d", spaceID, chartID)
|
||||||
|
req, err := s.client.NewRequest("DELETE", u, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.client.Do(req, nil)
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
package librato
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Stringify attempts to create a reasonable string representation of types in
|
||||||
|
// the Librato library. It does things like resolve pointers to their values
|
||||||
|
// and omits struct fields with nil values.
|
||||||
|
func Stringify(message interface{}) string {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
v := reflect.ValueOf(message)
|
||||||
|
stringifyValue(&buf, v)
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// stringifyValue was heavily inspired by the goprotobuf library.
|
||||||
|
|
||||||
|
func stringifyValue(w io.Writer, val reflect.Value) {
|
||||||
|
if val.Kind() == reflect.Ptr && val.IsNil() {
|
||||||
|
w.Write([]byte("<nil>"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
v := reflect.Indirect(val)
|
||||||
|
|
||||||
|
switch v.Kind() {
|
||||||
|
case reflect.String:
|
||||||
|
fmt.Fprintf(w, `"%s"`, v)
|
||||||
|
case reflect.Slice:
|
||||||
|
w.Write([]byte{'['})
|
||||||
|
for i := 0; i < v.Len(); i++ {
|
||||||
|
if i > 0 {
|
||||||
|
w.Write([]byte{' '})
|
||||||
|
}
|
||||||
|
|
||||||
|
stringifyValue(w, v.Index(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Write([]byte{']'})
|
||||||
|
return
|
||||||
|
case reflect.Struct:
|
||||||
|
if v.Type().Name() != "" {
|
||||||
|
w.Write([]byte(v.Type().String()))
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Write([]byte{'{'})
|
||||||
|
|
||||||
|
var sep bool
|
||||||
|
for i := 0; i < v.NumField(); i++ {
|
||||||
|
fv := v.Field(i)
|
||||||
|
if fv.Kind() == reflect.Ptr && fv.IsNil() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if fv.Kind() == reflect.Slice && fv.IsNil() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if sep {
|
||||||
|
w.Write([]byte(", "))
|
||||||
|
} else {
|
||||||
|
sep = true
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Write([]byte(v.Type().Field(i).Name))
|
||||||
|
w.Write([]byte{':'})
|
||||||
|
stringifyValue(w, fv)
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Write([]byte{'}'})
|
||||||
|
default:
|
||||||
|
if v.CanInterface() {
|
||||||
|
fmt.Fprint(w, v.Interface())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
vendor/github.com/henrikhodne/go-librato/librato/testing_helpers.go
generated
vendored
Normal file
17
vendor/github.com/henrikhodne/go-librato/librato/testing_helpers.go
generated
vendored
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
package librato
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ok fails the test if an err is not nil.
|
||||||
|
func ok(tb testing.TB, err error) {
|
||||||
|
if err != nil {
|
||||||
|
_, file, line, _ := runtime.Caller(1)
|
||||||
|
fmt.Printf("\033[31m%s:%d: unexpected error: %s\033[39m\n\n", filepath.Base(file), line, err.Error())
|
||||||
|
tb.FailNow()
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,6 +27,7 @@ body.layout-fastly,
|
||||||
body.layout-google,
|
body.layout-google,
|
||||||
body.layout-heroku,
|
body.layout-heroku,
|
||||||
body.layout-influxdb,
|
body.layout-influxdb,
|
||||||
|
body.layout-librato,
|
||||||
body.layout-mailgun,
|
body.layout-mailgun,
|
||||||
body.layout-mysql,
|
body.layout-mysql,
|
||||||
body.layout-openstack,
|
body.layout-openstack,
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
---
|
||||||
|
layout: "librato"
|
||||||
|
page_title: "Provider: Librato"
|
||||||
|
sidebar_current: "docs-librato-index"
|
||||||
|
description: |-
|
||||||
|
The Librato provider is used to interact with the resources supported by Librato. The provider needs to be configured with the proper credentials before it can be used.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Librato Provider
|
||||||
|
|
||||||
|
The Librato provider is used to interact with the
|
||||||
|
resources supported by Librato. The provider needs to be configured
|
||||||
|
with the proper credentials before it can be used.
|
||||||
|
|
||||||
|
Use the navigation to the left to read about the available resources.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
# Configure the Librato provider
|
||||||
|
provider "librato" {
|
||||||
|
email = "ops@company.com"
|
||||||
|
token = "${var.librato_token}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create a new space
|
||||||
|
resource "librato_space" "default" {
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `token` - (Required) Librato API token. It must be provided, but it can also
|
||||||
|
be sourced from the `LIBRATO_TOKEN` environment variable.
|
||||||
|
* `email` - (Required) Librato email address. It must be provided, but it can
|
||||||
|
also be sourced from the `LIBRATO_EMAIL` environment variable.
|
|
@ -0,0 +1,34 @@
|
||||||
|
---
|
||||||
|
layout: "librato"
|
||||||
|
page_title: "Librato: librato_space"
|
||||||
|
sidebar_current: "docs-librato-resource-space"
|
||||||
|
description: |-
|
||||||
|
Provides a Librato Space resource. This can be used to create and manage spaces on Librato.
|
||||||
|
---
|
||||||
|
|
||||||
|
# librato\_space
|
||||||
|
|
||||||
|
Provides a Librato Space resource. This can be used to
|
||||||
|
create and manage spaces on Librato.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
# Create a new Librato space
|
||||||
|
resource "librato_space" "default" {
|
||||||
|
name = "My New Space"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `name` - (Required) The name of the space.
|
||||||
|
|
||||||
|
## Attributes Reference
|
||||||
|
|
||||||
|
The following attributes are exported:
|
||||||
|
|
||||||
|
* `id` - The ID of the space.
|
||||||
|
* `name` - The name of the space.
|
|
@ -0,0 +1,110 @@
|
||||||
|
---
|
||||||
|
layout: "librato"
|
||||||
|
page_title: "Librato: librato_space_chart"
|
||||||
|
sidebar_current: "docs-librato-resource-space-chart"
|
||||||
|
description: |-
|
||||||
|
Provides a Librato Space Chart resource. This can be used to create and manage charts in Librato Spaces.
|
||||||
|
---
|
||||||
|
|
||||||
|
# librato\_space\_chart
|
||||||
|
|
||||||
|
Provides a Librato Space Chart resource. This can be used to
|
||||||
|
create and manage charts in Librato Spaces.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
# Create a new Librato space
|
||||||
|
resource "librato_space" "my_space" {
|
||||||
|
name = "My New Space"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create a new chart
|
||||||
|
resource "librato_space_chart" "server_temperature" {
|
||||||
|
name = "Server Temperature"
|
||||||
|
space_id = "${librato_space.my_space.id}"
|
||||||
|
|
||||||
|
stream {
|
||||||
|
metric = "server_temp"
|
||||||
|
source = "app1"
|
||||||
|
}
|
||||||
|
|
||||||
|
stream {
|
||||||
|
metric = "environmental_temp"
|
||||||
|
source = "*"
|
||||||
|
group_function = "breakout"
|
||||||
|
summary_function = "average"
|
||||||
|
}
|
||||||
|
|
||||||
|
stream {
|
||||||
|
metric = "server_temp"
|
||||||
|
source = "%"
|
||||||
|
group_function = "average"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `space_id` - (Required) The ID of the space this chart should be in.
|
||||||
|
* `name` - (Required) The title of the chart when it is displayed.
|
||||||
|
* `type` - (Optional) Indicates the type of chart. Must be one of line or
|
||||||
|
stacked (default to line).
|
||||||
|
* `min` - (Optional) The minimum display value of the chart's Y-axis.
|
||||||
|
* `max` - (Optional) The maximum display value of the chart's Y-axis.
|
||||||
|
* `label` - (Optional) The Y-axis label.
|
||||||
|
* `related_space` - (Optional) The ID of another space to which this chart is
|
||||||
|
related.
|
||||||
|
* `stream` - (Optional) Nested block describing a metric to use for data in the
|
||||||
|
chart. The structure of this block is described below.
|
||||||
|
|
||||||
|
The `stream` block supports:
|
||||||
|
|
||||||
|
* `metric` - (Required) The name of the metric. May not be specified if
|
||||||
|
`composite` is specified.
|
||||||
|
* `source` - (Required) The name of a source, or `*` to include all sources.
|
||||||
|
This field will also accept specific wildcard entries. For example
|
||||||
|
us-west-\*-app will match us-west-21-app but not us-west-12-db. Use % to
|
||||||
|
specify a dynamic source that will be provided after the instrument or
|
||||||
|
dashboard has loaded, or in the URL. May not be specified if `composite` is
|
||||||
|
specified.
|
||||||
|
* `group_function` - (Required) How to process the results when multiple sources
|
||||||
|
will be returned. Value must be one of average, sum, breakout. If average or
|
||||||
|
sum, a single line will be drawn representing the average or sum
|
||||||
|
(respectively) of all sources. If the group_function is breakout, a separate
|
||||||
|
line will be drawn for each source. If this property is not supplied, the
|
||||||
|
behavior will default to average. May not be specified if `composite` is
|
||||||
|
specified.
|
||||||
|
* `composite` - (Required) A composite metric query string to execute when this
|
||||||
|
stream is displayed. May not be specified if `metric`, `source` or
|
||||||
|
`group_function` is specified.
|
||||||
|
* `summary_function` - (Optional) When visualizing complex measurements or a
|
||||||
|
rolled-up measurement, this allows you to choose which statistic to use.
|
||||||
|
Defaults to "average". Valid options are: "max", "min", "average", "sum" or
|
||||||
|
"count".
|
||||||
|
* `name` - (Optional) A display name to use for the stream when generating the
|
||||||
|
tooltip.
|
||||||
|
* `color` - (Optional) Sets a color to use when rendering the stream. Must be a
|
||||||
|
seven character string that represents the hex code of the color e.g.
|
||||||
|
"#52D74C".
|
||||||
|
* `units_short` - (Optional) Unit value string to use as the tooltip label.
|
||||||
|
* `units_long` - (Optional) String value to set as they Y-axis label. All
|
||||||
|
streams that share the same units_long value will be plotted on the same
|
||||||
|
Y-axis.
|
||||||
|
* `min` - (Optional) Theoretical minimum Y-axis value.
|
||||||
|
* `max` - (Optional) Theoretical maximum Y-axis value.
|
||||||
|
* `transform_function` - (Optional) Linear formula to run on each measurement
|
||||||
|
prior to visualizaton.
|
||||||
|
* `period` - (Optional) An integer value of seconds that defines the period this
|
||||||
|
stream reports at. This aids in the display of the stream and allows the
|
||||||
|
period to be used in stream display transforms.
|
||||||
|
|
||||||
|
## Attributes Reference
|
||||||
|
|
||||||
|
The following attributes are exported:
|
||||||
|
|
||||||
|
* `id` - The ID of the chart.
|
||||||
|
* `space_id` - The ID of the space this chart should be in.
|
||||||
|
* `title` - The title of the chart when it is displayed.
|
|
@ -215,6 +215,10 @@
|
||||||
|
|
||||||
<li<%= sidebar_current("docs-providers-influxdb") %>>
|
<li<%= sidebar_current("docs-providers-influxdb") %>>
|
||||||
<a href="/docs/providers/influxdb/index.html">InfluxDB</a>
|
<a href="/docs/providers/influxdb/index.html">InfluxDB</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li<%= sidebar_current("docs-providers-librato") %>>
|
||||||
|
<a href="/docs/providers/librato/index.html">Librato</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("docs-providers-mailgun") %>>
|
<li<%= sidebar_current("docs-providers-mailgun") %>>
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
<% wrap_layout :inner do %>
|
||||||
|
<% content_for :sidebar do %>
|
||||||
|
<div class="docs-sidebar hidden-print affix-top" role="complementary">
|
||||||
|
<ul class="nav docs-sidenav">
|
||||||
|
<li<%= sidebar_current("docs-home") %>>
|
||||||
|
<a href="/docs/providers/index.html">« Documentation Home</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li<%= sidebar_current("docs-librato-index") %>>
|
||||||
|
<a href="/docs/providers/librato/index.html">Librato Provider</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li<%= sidebar_current(/^docs-librato-resource/) %>>
|
||||||
|
<a href="#">Resources</a>
|
||||||
|
<ul class="nav nav-visible">
|
||||||
|
<li<%= sidebar_current("docs-librato-resource-space") %>>
|
||||||
|
<a href="/docs/providers/librato/r/space.html">librato_space</a>
|
||||||
|
</li>
|
||||||
|
<li<%= sidebar_current("docs-librato-resource-space-chart") %>>
|
||||||
|
<a href="/docs/providers/librato/r/space_chart.html">librato_space_chart</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<%= yield %>
|
||||||
|
<% end %>
|
Loading…
Reference in New Issue