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

Add Logs List Chart resource #383

Merged
merged 6 commits into from
Aug 4, 2022
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 go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ require (
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d
github.com/hashicorp/terraform-plugin-sdk v1.15.0
github.com/mitchellh/go-homedir v1.1.0
github.com/signalfx/signalfx-go v1.22.0
github.com/signalfx/signalfx-go v1.23.0
github.com/stretchr/testify v1.6.1
)

Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -217,8 +217,8 @@ github.com/signalfx/golib/v3 v3.3.37 h1:CvL6Q8hySjm7D82P039qH2lFWJvBa18IJdAwa4LH
github.com/signalfx/golib/v3 v3.3.37/go.mod h1:zH70SVnrzVUqDmUFEwDk1HSwS71Pi2w3bSsNpnOtYuQ=
github.com/signalfx/gomemcache v0.0.0-20180823214636-4f7ef64c72a9/go.mod h1:Ytb8KfCSyuwy/VILnROdgCvbQLA5ch0nkbG7lKT0BXw=
github.com/signalfx/sapm-proto v0.4.0/go.mod h1:x3gtwJ1GRejtkghB4nYpwixh2zqJrLbPU959ZNhM0Fk=
github.com/signalfx/signalfx-go v1.22.0 h1:7b7MwCNOFL2xq+onzOpkDJYBMSk5HTWhEZI7d1QQb/k=
github.com/signalfx/signalfx-go v1.22.0/go.mod h1:YhPTMdQJDfphcRBdk+9acbbAw1gYY7z5BIHUWzLmGlA=
github.com/signalfx/signalfx-go v1.23.0 h1:gWLOw2TuYckzzqQ6/aMWrKypNLIzx5s2XwkINw5m+Ck=
github.com/signalfx/signalfx-go v1.23.0/go.mod h1:YhPTMdQJDfphcRBdk+9acbbAw1gYY7z5BIHUWzLmGlA=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v0.0.0-20190215210624-980c5ac6f3ac h1:wbW+Bybf9pXxnCFAOWZTqkRjAc7rAIwo2e1ArUhiHxg=
github.com/smartystreets/assertions v0.0.0-20190215210624-980c5ac6f3ac/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
Expand Down
1 change: 1 addition & 0 deletions signalfx/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ func Provider() terraform.ResourceProvider {
"signalfx_text_chart": textChartResource(),
"signalfx_victor_ops_integration": integrationVictorOpsResource(),
"signalfx_webhook_integration": integrationWebhookResource(),
"signalfx_logs_list_chart": logsListChartResource(),
},
ConfigureFunc: signalfxConfigure,
}
Expand Down
320 changes: 320 additions & 0 deletions signalfx/resource_signalfx_logs_list_chart.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,320 @@
package signalfx

import (
"context"
"encoding/json"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
"log"

"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
chart "github.com/signalfx/signalfx-go/chart"
)

func logsListChartResource() *schema.Resource {
return &schema.Resource{
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "Name of the chart",
},
"program_text": &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "Signalflow program text for the chart. More info at \"https://developers.signalfx.com/docs/signalflow-overview\"",
ValidateFunc: validation.StringLenBetween(16, 50000),
},
"description": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Description: "Description of the chart (Optional)",
},
"time_range": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Description: "Seconds to display in the visualization. This is a rolling range from the current time. Example: 3600 = `-1h`",
ConflictsWith: []string{"start_time", "end_time"},
},
"start_time": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Description: "Seconds since epoch to start the visualization",
ConflictsWith: []string{"time_range"},
},
"end_time": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Description: "Seconds since epoch to end the visualization",
ConflictsWith: []string{"time_range"},
},
"columns": &schema.Schema{
Type: schema.TypeList,
Optional: true,
Description: "Column configuration",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "Name of the column",
},
},
},
},
"sort_options": &schema.Schema{
Type: schema.TypeList,
Optional: true,
Description: "Sorting options configuration",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"field": &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "Name of the column",
},
"descending": &schema.Schema{
Type: schema.TypeBool,
Required: true,
Description: "Name of the column",
},
},
},
},
"default_connection": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Description: "default connection that the dashboard uses",
},
"url": &schema.Schema{
Type: schema.TypeString,
Computed: true,
Description: "URL of the chart",
},
},

Create: logslistchartCreate,
Read: logslistchartRead,
Update: logslistchartUpdate,
Delete: logslistchartDelete,
Exists: chartExists,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
}
}

/*
Use Resource object to construct json payload in order to create a logs list chart
*/
func getPayloadLogsListChart(d *schema.ResourceData) *chart.CreateUpdateChartRequest {
var timeOptions *chart.TimeDisplayOptions
var col []*chart.Columns
var sort []*chart.SortOptions

if val, ok := d.GetOk("time_range"); ok {
r := int64(val.(int) * 1000)
timeOptions = &chart.TimeDisplayOptions{
Range: &r,
Type: "relative",
}
}
if val, ok := d.GetOk("start_time"); ok {
start := int64(val.(int) * 1000)
timeOptions = &chart.TimeDisplayOptions{
Start: &start,
Type: "absolute",
}
if val, ok := d.GetOk("end_time"); ok {
end := int64(val.(int) * 1000)
timeOptions.End = &end
}
}

if columns, ok := d.Get("columns").([]interface{}); ok {

for _, column := range columns {
if column == nil {
continue
}

columnMap := column.(map[string]interface{})
if columnMap["name"].(string) != "" {
col = append(col, &chart.Columns{
Name: columnMap["name"].(string),
})
}
}
}

if sortOptions, ok := d.Get("sort_options").([]interface{}); ok {

for _, sortOption := range sortOptions {
if sortOption == nil {
continue
}

sortOptionMap := sortOption.(map[string]interface{})
if sortOptionMap["field"].(string) != "" {
sort = append(sort, &chart.SortOptions{
Field: sortOptionMap["field"].(string),
Descending: sortOptionMap["descending"].(bool),
})
}
}
}

return &chart.CreateUpdateChartRequest{
Name: d.Get("name").(string),
Description: d.Get("description").(string),
ProgramText: d.Get("program_text").(string),
Options: &chart.Options{
Time: timeOptions,
Type: "LogsChart",
Columns: col,
SortOptions: sort,
DefaultConnection: d.Get("default_connection").(string),
},
}
}

func logslistchartCreate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*signalfxConfig)
payload := getPayloadLogsListChart(d)

debugOutput, _ := json.Marshal(payload)
log.Printf("[DEBUG] SignalFx: Create Logs List Chart Payload: %s", string(debugOutput))

c, err := config.Client.CreateChart(context.TODO(), payload)
if err != nil {
return err
}
// Since things worked, set the URL and move on
appURL, err := buildAppURL(config.CustomAppURL, CHART_APP_PATH+c.Id)
if err != nil {
return err
}
if err := d.Set("url", appURL); err != nil {
return err
}
d.SetId(c.Id)
log.Printf("[DEBUG] appURL in create: %s", string(appURL))

return logslistchartAPIToTF(d, c)
}

func logslistchartAPIToTF(d *schema.ResourceData, c *chart.Chart) error {
debugOutput, _ := json.Marshal(c)
log.Printf("[DEBUG] SignalFx: Got Logs List Chart to enState: %s", string(debugOutput))

if err := d.Set("name", c.Name); err != nil {
return err
}
if err := d.Set("description", c.Description); err != nil {
return err
}
if err := d.Set("program_text", c.ProgramText); err != nil {
return err
}

options := c.Options

if options.Time != nil {
if options.Time.Type == "relative" {
if options.Time.Range != nil {
if err := d.Set("time_range", *options.Time.Range/1000); err != nil {
return err
}
}
} else {
if options.Time.Start != nil {
if err := d.Set("start_time", *options.Time.Start/1000); err != nil {
return err
}
}
if options.Time.End != nil {
if err := d.Set("end_time", *options.Time.End/1000); err != nil {
return err
}
}
}
}

if options.SortOptions != nil {

if len(options.SortOptions) > 0 {
sos := make([]map[string]interface{}, len(options.SortOptions))
for i, so := range options.SortOptions {
sos[i] = map[string]interface{}{
"descending": so.Descending,
"field": so.Field,
}
}
if err := d.Set("sort_options", sos); err != nil {
return err
}
}
}

if options.Columns != nil {
if len(options.Columns) > 0 {
cols := make([]map[string]interface{}, len(options.Columns))
for i, col := range options.Columns {
cols[i] = map[string]interface{}{
"name": col.Name,
}
}
if err := d.Set("columns", cols); err != nil {
return err
}
}
}

if options.DefaultConnection != "" {
if err := d.Set("default_connection", options.DefaultConnection); err != nil {
return err
}

}
return nil
}

func logslistchartRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*signalfxConfig)
c, err := config.Client.GetChart(context.TODO(), d.Id())
if err != nil {
return err
}

appURL, err := buildAppURL(config.CustomAppURL, CHART_APP_PATH+c.Id)
if err != nil {
return err
}
if err := d.Set("url", appURL); err != nil {
return err
}
log.Printf("[DEBUG] appURL in read: %s", string(appURL))

return logslistchartAPIToTF(d, c)
}

func logslistchartUpdate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*signalfxConfig)
payload := getPayloadLogsListChart(d)
debugOutput, _ := json.Marshal(payload)
log.Printf("[DEBUG] SignalFx: Update Logs List Chart Payload: %s", string(debugOutput))

c, err := config.Client.UpdateChart(context.TODO(), d.Id(), payload)
if err != nil {
return err
}
log.Printf("[DEBUG] SignalFx: Update Logs List Chart Response: %v", c)

d.SetId(c.Id)
return logslistchartAPIToTF(d, c)
}

func logslistchartDelete(d *schema.ResourceData, meta interface{}) error {
config := meta.(*signalfxConfig)

return config.Client.DeleteChart(context.TODO(), d.Id())
}
Loading