diff --git a/bolt/lookup_service_test.go b/bolt/lookup_service_test.go index fa31b042cd8..63e2762d622 100644 --- a/bolt/lookup_service_test.go +++ b/bolt/lookup_service_test.go @@ -187,8 +187,9 @@ func TestClient_Name(t *testing.T) { }, init: func(ctx context.Context, s *bolt.Client) error { return s.CreateTelegrafConfig(ctx, &platform.TelegrafConfig{ - OrgID: platformtesting.MustIDBase16("0000000000000009"), - Name: "telegraf1", + OrgID: platformtesting.MustIDBase16("0000000000000009"), + Name: "telegraf1", + Config: "[agent]", }, testID) }, }, diff --git a/cmd/influxd/launcher/pkger_test.go b/cmd/influxd/launcher/pkger_test.go index b2c56a5efce..47e099b89e9 100644 --- a/cmd/influxd/launcher/pkger_test.go +++ b/cmd/influxd/launcher/pkger_test.go @@ -244,7 +244,7 @@ func TestLauncher_Pkger(t *testing.T) { assert.Equal(t, l.Org.ID, teles[0].TelegrafConfig.OrgID) assert.Equal(t, "first_tele_config", teles[0].TelegrafConfig.Name) assert.Equal(t, "desc", teles[0].TelegrafConfig.Description) - assert.Len(t, teles[0].TelegrafConfig.Plugins, 2) + assert.Equal(t, telConf, teles[0].TelegrafConfig.Config) vars := sum1.Variables require.Len(t, vars, 1) @@ -525,7 +525,22 @@ func newPkg(t *testing.T) *pkger.Pkg { return pkg } -const pkgYMLStr = `apiVersion: 0.1.0 +const telConf = `[agent] + interval = "10s" + metric_batch_size = 1000 + metric_buffer_limit = 10000 + collection_jitter = "0s" + flush_interval = "10s" +[[outputs.influxdb_v2]] + urls = ["http://localhost:9999"] + token = "$INFLUX_TOKEN" + organization = "rg" + bucket = "rucket_3" +[[inputs.cpu]] + percpu = true +` + +var pkgYMLStr = fmt.Sprintf(`apiVersion: 0.1.0 kind: Package meta: pkgName: pkg_name @@ -576,20 +591,7 @@ spec: associations: - kind: Label name: label_1 - config: | - [agent] - interval = "10s" - metric_batch_size = 1000 - metric_buffer_limit = 10000 - collection_jitter = "0s" - flush_interval = "10s" - [[outputs.influxdb_v2]] - urls = ["http://localhost:9999"] - token = "$INFLUX_TOKEN" - organization = "rg" - bucket = "rucket_3" - [[inputs.cpu]] - percpu = true + config: %+q - kind: Notification_Endpoint_HTTP name: http_none_auth_notification_endpoint type: none @@ -598,8 +600,8 @@ spec: url: https://www.example.com/endpoint/noneauth status: inactive associations: - - kind: Label - name: label_1 + - kind: Label + name: label_1 - kind: Check_Threshold name: check_0 every: 1m @@ -664,7 +666,7 @@ spec: associations: - kind: Label name: label_1 -` +`, telConf) const updatePkgYMLStr = `apiVersion: 0.1.0 kind: Package diff --git a/http/swagger.yml b/http/swagger.yml index c60c4fcfd88..ba05218c0b8 100644 --- a/http/swagger.yml +++ b/http/swagger.yml @@ -9307,15 +9307,15 @@ components: type: string description: type: string - agent: + metadata: type: object properties: - collectionInterval: - type: integer - plugins: - type: array - items: - $ref: "#/components/schemas/TelegrafRequestPlugin" + buckets: + type: array + items: + type: string + config: + type: string orgID: type: string TelegrafRequestPlugin: diff --git a/http/telegraf.go b/http/telegraf.go index e569488c3bc..2d26b795a6f 100644 --- a/http/telegraf.go +++ b/http/telegraf.go @@ -135,55 +135,6 @@ type telegrafLinks struct { Owners string `json:"owners"` } -// MarshalJSON implement the json.Marshaler interface. -// TODO: remove this hack and make labels and links return. -// see: https://github.com/influxdata/influxdb/issues/12457 -func (r *telegrafResponse) MarshalJSON() ([]byte, error) { - // telegrafPluginEncode is the helper struct for json encoding. - type telegrafPluginEncode struct { - // Name of the telegraf plugin, exp "docker" - Name string `json:"name"` - Type plugins.Type `json:"type"` - Comment string `json:"comment"` - Config plugins.Config `json:"config"` - } - - // telegrafConfigEncode is the helper struct for json encoding. - type telegrafConfigEncode struct { - ID platform.ID `json:"id"` - OrgID platform.ID `json:"orgID,omitempty"` - Name string `json:"name"` - Description string `json:"description"` - Agent platform.TelegrafAgentConfig `json:"agent"` - Plugins []telegrafPluginEncode `json:"plugins"` - Labels []platform.Label `json:"labels"` - Links telegrafLinks `json:"links"` - } - - tce := new(telegrafConfigEncode) - *tce = telegrafConfigEncode{ - ID: r.ID, - OrgID: r.OrgID, - Name: r.Name, - Description: r.Description, - Agent: r.Agent, - Plugins: make([]telegrafPluginEncode, len(r.Plugins)), - Labels: r.Labels, - Links: r.Links, - } - - for k, p := range r.Plugins { - tce.Plugins[k] = telegrafPluginEncode{ - Name: p.Config.PluginName(), - Type: p.Config.Type(), - Comment: p.Comment, - Config: p.Config, - } - } - - return json.Marshal(tce) -} - type telegrafResponse struct { *platform.TelegrafConfig Labels []platform.Label `json:"labels"` @@ -306,7 +257,7 @@ func (h *TelegrafHandler) handleGetTelegraf(w http.ResponseWriter, r *http.Reque w.Header().Set("Content-Type", "application/octet-stream") w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s.toml\"", strings.Replace(strings.TrimSpace(tc.Name), " ", "_", -1))) w.WriteHeader(http.StatusOK) - w.Write([]byte(tc.TOML())) + w.Write([]byte(tc.Config)) case "application/json": labels, err := h.LabelService.FindResourceLabels(ctx, platform.LabelMappingFilter{ResourceID: tc.ID}) if err != nil { @@ -321,7 +272,7 @@ func (h *TelegrafHandler) handleGetTelegraf(w http.ResponseWriter, r *http.Reque case "application/toml": w.Header().Set("Content-Type", "application/toml; charset=utf-8") w.WriteHeader(http.StatusOK) - w.Write([]byte(tc.TOML())) + w.Write([]byte(tc.Config)) } } @@ -349,12 +300,6 @@ func decodeTelegrafConfigFilter(ctx context.Context, r *http.Request) (*platform return f, err } -func decodePostTelegrafRequest(r *http.Request) (*platform.TelegrafConfig, error) { - var tc platform.TelegrafConfig - err := json.NewDecoder(r.Body).Decode(&tc) - return &tc, err -} - func decodePutTelegrafRequest(ctx context.Context, r *http.Request) (*platform.TelegrafConfig, error) { tc := new(platform.TelegrafConfig) if err := json.NewDecoder(r.Body).Decode(tc); err != nil { @@ -379,12 +324,14 @@ func decodePutTelegrafRequest(ctx context.Context, r *http.Request) (*platform.T // handlePostTelegraf is the HTTP handler for the POST /api/v2/telegrafs route. func (h *TelegrafHandler) handlePostTelegraf(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - tc, err := decodePostTelegrafRequest(r) - if err != nil { + + tc := new(platform.TelegrafConfig) + if err := json.NewDecoder(r.Body).Decode(tc); err != nil { h.log.Debug("Failed to decode request", zap.Error(err)) h.HandleHTTPError(ctx, err, w) return } + auth, err := pctx.GetAuthorizer(ctx) if err != nil { h.HandleHTTPError(ctx, err, w) @@ -406,12 +353,14 @@ func (h *TelegrafHandler) handlePostTelegraf(w http.ResponseWriter, r *http.Requ // handlePutTelegraf is the HTTP handler for the POST /api/v2/telegrafs route. func (h *TelegrafHandler) handlePutTelegraf(w http.ResponseWriter, r *http.Request) { ctx := r.Context() + tc, err := decodePutTelegrafRequest(ctx, r) if err != nil { h.log.Debug("Failed to decode request", zap.Error(err)) h.HandleHTTPError(ctx, err, w) return } + auth, err := pctx.GetAuthorizer(ctx) if err != nil { h.HandleHTTPError(ctx, err, w) diff --git a/http/telegraf_test.go b/http/telegraf_test.go index 190a77ca41c..eb8bce48154 100644 --- a/http/telegraf_test.go +++ b/http/telegraf_test.go @@ -12,8 +12,6 @@ import ( platform "github.com/influxdata/influxdb" "github.com/influxdata/influxdb/mock" - "github.com/influxdata/influxdb/telegraf/plugins/inputs" - "github.com/influxdata/influxdb/telegraf/plugins/outputs" "go.uber.org/zap/zaptest" ) @@ -54,11 +52,7 @@ func TestTelegrafHandler_handleGetTelegrafs(t *testing.T) { OrgID: platform.ID(2), Name: "tc1", Description: "", - Plugins: []platform.TelegrafPlugin{ - { - Config: &inputs.CPUStats{}, - }, - }, + Config: "[[inputs.cpu]]\n", }, }, 1, nil } @@ -69,35 +63,21 @@ func TestTelegrafHandler_handleGetTelegrafs(t *testing.T) { wants: wants{ statusCode: http.StatusOK, contentType: "application/json; charset=utf-8", - body: ` - { - "configurations":[ - { + body: `{ + "configurations": [ + { + "id": "0000000000000001", + "orgID": "0000000000000002", + "name": "tc1", + "config": "[[inputs.cpu]]\n", "labels": [], "links": { + "self": "/api/v2/telegrafs/0000000000000001", "labels": "/api/v2/telegrafs/0000000000000001/labels", "members": "/api/v2/telegrafs/0000000000000001/members", - "owners": "/api/v2/telegrafs/0000000000000001/owners", - "self": "/api/v2/telegrafs/0000000000000001" - }, - "id":"0000000000000001", - "orgID":"0000000000000002", - "name":"tc1", - "description":"", - "agent":{ - "collectionInterval":0 - }, - "plugins":[ - { - "name":"cpu", - "type":"input", - "comment":"", - "config":{ - + "owners": "/api/v2/telegrafs/0000000000000001/owners" } - } - ] - } + } ] }`, }, @@ -113,24 +93,7 @@ func TestTelegrafHandler_handleGetTelegrafs(t *testing.T) { OrgID: platform.ID(2), Name: "my config", Description: "my description", - Agent: platform.TelegrafAgentConfig{ - Interval: 10000, - }, - Plugins: []platform.TelegrafPlugin{ - { - Comment: "my cpu stats", - Config: &inputs.CPUStats{}, - }, - { - Comment: "my influx output", - Config: &outputs.InfluxDBV2{ - URLs: []string{"http://127.0.0.1:9999"}, - Token: "no_more_secrets", - Organization: "my_org", - Bucket: "my_bucket", - }, - }, - }, + Config: "[[inputs.cpu]]\n[[outputs.influxdb_v2]]\n", }, }, 1, nil }, @@ -139,46 +102,23 @@ func TestTelegrafHandler_handleGetTelegrafs(t *testing.T) { statusCode: http.StatusOK, contentType: "application/json; charset=utf-8", body: `{ - "configurations": [ - { + "configurations": [ + { + "id": "0000000000000001", + "orgID": "0000000000000002", + "name": "my config", + "description": "my description", + "config": "[[inputs.cpu]]\n[[outputs.influxdb_v2]]\n", "labels": [], "links": { + "self": "/api/v2/telegrafs/0000000000000001", "labels": "/api/v2/telegrafs/0000000000000001/labels", "members": "/api/v2/telegrafs/0000000000000001/members", - "owners": "/api/v2/telegrafs/0000000000000001/owners", - "self": "/api/v2/telegrafs/0000000000000001" - }, - "id": "0000000000000001", - "orgID": "0000000000000002", - "name": "my config", - "description": "my description", - "agent": { - "collectionInterval": 10000 - }, - "plugins": [ - { - "name": "cpu", - "type": "input", - "comment": "my cpu stats", - "config": {} - }, - { - "name": "influxdb_v2", - "type": "output", - "comment": "my influx output", - "config": { - "urls": [ - "http://127.0.0.1:9999" - ], - "token": "no_more_secrets", - "organization": "my_org", - "bucket": "my_bucket" - } - } - ] - } - ] - }`, + "owners": "/api/v2/telegrafs/0000000000000001/owners" + } + } + ] + }`, }, }, } @@ -236,24 +176,7 @@ func TestTelegrafHandler_handleGetTelegraf(t *testing.T) { OrgID: platform.ID(2), Name: "my config", Description: "", - Agent: platform.TelegrafAgentConfig{ - Interval: 10000, - }, - Plugins: []platform.TelegrafPlugin{ - { - Comment: "my cpu stats", - Config: &inputs.CPUStats{}, - }, - { - Comment: "my influx output", - Config: &outputs.InfluxDBV2{ - URLs: []string{"http://127.0.0.1:9999"}, - Token: "no_more_secrets", - Organization: "my_org", - Bucket: "my_bucket", - }, - }, - }, + Config: "[[inputs.cpu]]\n[[outputs.influxdb_v2]]\n", }, nil }, }, @@ -261,42 +184,18 @@ func TestTelegrafHandler_handleGetTelegraf(t *testing.T) { statusCode: http.StatusOK, contentType: "application/json; charset=utf-8", body: `{ - "id": "0000000000000001", - "orgID": "0000000000000002", - "name": "my config", - "description": "", - "agent": { - "collectionInterval": 10000 - }, - "labels": [], - "links": { - "labels": "/api/v2/telegrafs/0000000000000001/labels", - "members": "/api/v2/telegrafs/0000000000000001/members", - "owners": "/api/v2/telegrafs/0000000000000001/owners", - "self": "/api/v2/telegrafs/0000000000000001" - }, - "plugins": [ - { - "name": "cpu", - "type": "input", - "comment": "my cpu stats", - "config": {} - }, - { - "name": "influxdb_v2", - "type": "output", - "comment": "my influx output", - "config": { - "urls": [ - "http://127.0.0.1:9999" - ], - "token": "no_more_secrets", - "organization": "my_org", - "bucket": "my_bucket" - } - } - ] - }`, + "id": "0000000000000001", + "orgID": "0000000000000002", + "name": "my config", + "config": "[[inputs.cpu]]\n[[outputs.influxdb_v2]]\n", + "labels": [], + "links": { + "self": "/api/v2/telegrafs/0000000000000001", + "labels": "/api/v2/telegrafs/0000000000000001/labels", + "members": "/api/v2/telegrafs/0000000000000001/members", + "owners": "/api/v2/telegrafs/0000000000000001/owners" + } + }`, }, }, { @@ -310,24 +209,7 @@ func TestTelegrafHandler_handleGetTelegraf(t *testing.T) { OrgID: platform.ID(2), Name: "my config", Description: "", - Agent: platform.TelegrafAgentConfig{ - Interval: 10000, - }, - Plugins: []platform.TelegrafPlugin{ - { - Comment: "my cpu stats", - Config: &inputs.CPUStats{}, - }, - { - Comment: "my influx output", - Config: &outputs.InfluxDBV2{ - URLs: []string{"http://127.0.0.1:9999"}, - Token: "no_more_secrets", - Organization: "my_org", - Bucket: "my_bucket", - }, - }, - }, + Config: "[[inputs.cpu]]\n[[outputs.influxdb_v2]]\n", }, nil }, }, @@ -335,42 +217,18 @@ func TestTelegrafHandler_handleGetTelegraf(t *testing.T) { statusCode: http.StatusOK, contentType: "application/json; charset=utf-8", body: `{ - "id": "0000000000000001", - "orgID": "0000000000000002", - "name": "my config", - "description": "", - "agent": { - "collectionInterval": 10000 - }, - "labels": [], - "links": { - "labels": "/api/v2/telegrafs/0000000000000001/labels", - "members": "/api/v2/telegrafs/0000000000000001/members", - "owners": "/api/v2/telegrafs/0000000000000001/owners", - "self": "/api/v2/telegrafs/0000000000000001" - }, - "plugins": [ - { - "name": "cpu", - "type": "input", - "comment": "my cpu stats", - "config": {} - }, - { - "name": "influxdb_v2", - "type": "output", - "comment": "my influx output", - "config": { - "urls": [ - "http://127.0.0.1:9999" - ], - "token": "no_more_secrets", - "organization": "my_org", - "bucket": "my_bucket" - } - } - ] - }`, + "id": "0000000000000001", + "orgID": "0000000000000002", + "name": "my config", + "config": "[[inputs.cpu]]\n[[outputs.influxdb_v2]]\n", + "labels": [], + "links": { + "self": "/api/v2/telegrafs/0000000000000001", + "labels": "/api/v2/telegrafs/0000000000000001/labels", + "members": "/api/v2/telegrafs/0000000000000001/members", + "owners": "/api/v2/telegrafs/0000000000000001/owners" + } + }`, }, }, { @@ -383,24 +241,86 @@ func TestTelegrafHandler_handleGetTelegraf(t *testing.T) { ID: platform.ID(1), OrgID: platform.ID(2), Name: "my config", - Agent: platform.TelegrafAgentConfig{ - Interval: 10000, - }, - Plugins: []platform.TelegrafPlugin{ - { - Comment: "my cpu stats", - Config: &inputs.CPUStats{}, - }, - { - Comment: "my influx output", - Config: &outputs.InfluxDBV2{ - URLs: []string{"http://127.0.0.1:9999"}, - Token: "no_more_secrets", - Organization: "my_org", - Bucket: "my_bucket", - }, - }, - }, + Config: `# Configuration for telegraf agent +[agent] + ## Default data collection interval for all inputs + interval = "10s" + ## Rounds collection interval to 'interval' + ## ie, if interval="10s" then always collect on :00, :10, :20, etc. + round_interval = true + + ## Telegraf will send metrics to outputs in batches of at most + ## metric_batch_size metrics. + ## This controls the size of writes that Telegraf sends to output plugins. + metric_batch_size = 1000 + + ## For failed writes, telegraf will cache metric_buffer_limit metrics for each + ## output, and will flush this buffer on a successful write. Oldest metrics + ## are dropped first when this buffer fills. + ## This buffer only fills when writes fail to output plugin(s). + metric_buffer_limit = 10000 + + ## Collection jitter is used to jitter the collection by a random amount. + ## Each plugin will sleep for a random time within jitter before collecting. + ## This can be used to avoid many plugins querying things like sysfs at the + ## same time, which can have a measurable effect on the system. + collection_jitter = "0s" + + ## Default flushing interval for all outputs. Maximum flush_interval will be + ## flush_interval + flush_jitter + flush_interval = "10s" + ## Jitter the flush interval by a random amount. This is primarily to avoid + ## large write spikes for users running a large number of telegraf instances. + ## ie, a jitter of 5s and interval 10s means flushes will happen every 10-15s + flush_jitter = "0s" + + ## By default or when set to "0s", precision will be set to the same + ## timestamp order as the collection interval, with the maximum being 1s. + ## ie, when interval = "10s", precision will be "1s" + ## when interval = "250ms", precision will be "1ms" + ## Precision will NOT be used for service inputs. It is up to each individual + ## service input to set the timestamp at the appropriate precision. + ## Valid time units are "ns", "us" (or "µs"), "ms", "s". + precision = "" + + ## Logging configuration: + ## Run telegraf with debug log messages. + debug = false + ## Run telegraf in quiet mode (error log messages only). + quiet = false + ## Specify the log file name. The empty string means to log to stderr. + logfile = "" + + ## Override default hostname, if empty use os.Hostname() + hostname = "" + ## If set to true, do no set the "host" tag in the telegraf agent. + omit_hostname = false +[[inputs.cpu]] + ## Whether to report per-cpu stats or not + percpu = true + ## Whether to report total system cpu stats or not + totalcpu = true + ## If true, collect raw CPU time metrics. + collect_cpu_time = false + ## If true, compute and report the sum of all non-idle CPU states. + report_active = false +[[outputs.influxdb_v2]] + ## The URLs of the InfluxDB cluster nodes. + ## + ## Multiple URLs can be specified for a single cluster, only ONE of the + ## urls will be written to each interval. + ## urls exp: http://127.0.0.1:9999 + urls = ["http://127.0.0.1:9999"] + + ## Token for authentication. + token = "no_more_secrets" + + ## Organization is the name of the organization you wish to write to; must exist. + organization = "my_org" + + ## Destination bucket to write into. + bucket = "my_bucket" +`, }, nil }, }, @@ -470,7 +390,7 @@ func TestTelegrafHandler_handleGetTelegraf(t *testing.T) { collect_cpu_time = false ## If true, compute and report the sum of all non-idle CPU states. report_active = false -[[outputs.influxdb_v2]] +[[outputs.influxdb_v2]] ## The URLs of the InfluxDB cluster nodes. ## ## Multiple URLs can be specified for a single cluster, only ONE of the @@ -497,25 +417,86 @@ func TestTelegrafHandler_handleGetTelegraf(t *testing.T) { return &platform.TelegrafConfig{ ID: platform.ID(1), OrgID: platform.ID(2), - Name: "my config", - Agent: platform.TelegrafAgentConfig{ - Interval: 10000, - }, - Plugins: []platform.TelegrafPlugin{ - { - Comment: "my cpu stats", - Config: &inputs.CPUStats{}, - }, - { - Comment: "my influx output", - Config: &outputs.InfluxDBV2{ - URLs: []string{"http://127.0.0.1:9999"}, - Token: "no_more_secrets", - Organization: "my_org", - Bucket: "my_bucket", - }, - }, - }, + Config: `# Configuration for telegraf agent +[agent] + ## Default data collection interval for all inputs + interval = "10s" + ## Rounds collection interval to 'interval' + ## ie, if interval="10s" then always collect on :00, :10, :20, etc. + round_interval = true + + ## Telegraf will send metrics to outputs in batches of at most + ## metric_batch_size metrics. + ## This controls the size of writes that Telegraf sends to output plugins. + metric_batch_size = 1000 + + ## For failed writes, telegraf will cache metric_buffer_limit metrics for each + ## output, and will flush this buffer on a successful write. Oldest metrics + ## are dropped first when this buffer fills. + ## This buffer only fills when writes fail to output plugin(s). + metric_buffer_limit = 10000 + + ## Collection jitter is used to jitter the collection by a random amount. + ## Each plugin will sleep for a random time within jitter before collecting. + ## This can be used to avoid many plugins querying things like sysfs at the + ## same time, which can have a measurable effect on the system. + collection_jitter = "0s" + + ## Default flushing interval for all outputs. Maximum flush_interval will be + ## flush_interval + flush_jitter + flush_interval = "10s" + ## Jitter the flush interval by a random amount. This is primarily to avoid + ## large write spikes for users running a large number of telegraf instances. + ## ie, a jitter of 5s and interval 10s means flushes will happen every 10-15s + flush_jitter = "0s" + + ## By default or when set to "0s", precision will be set to the same + ## timestamp order as the collection interval, with the maximum being 1s. + ## ie, when interval = "10s", precision will be "1s" + ## when interval = "250ms", precision will be "1ms" + ## Precision will NOT be used for service inputs. It is up to each individual + ## service input to set the timestamp at the appropriate precision. + ## Valid time units are "ns", "us" (or "µs"), "ms", "s". + precision = "" + + ## Logging configuration: + ## Run telegraf with debug log messages. + debug = false + ## Run telegraf in quiet mode (error log messages only). + quiet = false + ## Specify the log file name. The empty string means to log to stderr. + logfile = "" + + ## Override default hostname, if empty use os.Hostname() + hostname = "" + ## If set to true, do no set the "host" tag in the telegraf agent. + omit_hostname = false +[[inputs.cpu]] + ## Whether to report per-cpu stats or not + percpu = true + ## Whether to report total system cpu stats or not + totalcpu = true + ## If true, collect raw CPU time metrics. + collect_cpu_time = false + ## If true, compute and report the sum of all non-idle CPU states. + report_active = false +[[outputs.influxdb_v2]] + ## The URLs of the InfluxDB cluster nodes. + ## + ## Multiple URLs can be specified for a single cluster, only ONE of the + ## urls will be written to each interval. + ## urls exp: http://127.0.0.1:9999 + urls = ["http://127.0.0.1:9999"] + + ## Token for authentication. + token = "no_more_secrets" + + ## Organization is the name of the organization you wish to write to; must exist. + organization = "my_org" + + ## Destination bucket to write into. + bucket = "my_bucket" +`, }, nil }, }, @@ -585,7 +566,7 @@ func TestTelegrafHandler_handleGetTelegraf(t *testing.T) { collect_cpu_time = false ## If true, compute and report the sum of all non-idle CPU states. report_active = false -[[outputs.influxdb_v2]] +[[outputs.influxdb_v2]] ## The URLs of the InfluxDB cluster nodes. ## ## Multiple URLs can be specified for a single cluster, only ONE of the @@ -614,24 +595,86 @@ func TestTelegrafHandler_handleGetTelegraf(t *testing.T) { ID: platform.ID(1), OrgID: platform.ID(2), Name: "my config", - Agent: platform.TelegrafAgentConfig{ - Interval: 10000, - }, - Plugins: []platform.TelegrafPlugin{ - { - Comment: "my cpu stats", - Config: &inputs.CPUStats{}, - }, - { - Comment: "my influx output", - Config: &outputs.InfluxDBV2{ - URLs: []string{"http://127.0.0.1:9999"}, - Token: "no_more_secrets", - Organization: "my_org", - Bucket: "my_bucket", - }, - }, - }, + Config: `# Configuration for telegraf agent +[agent] + ## Default data collection interval for all inputs + interval = "10s" + ## Rounds collection interval to 'interval' + ## ie, if interval="10s" then always collect on :00, :10, :20, etc. + round_interval = true + + ## Telegraf will send metrics to outputs in batches of at most + ## metric_batch_size metrics. + ## This controls the size of writes that Telegraf sends to output plugins. + metric_batch_size = 1000 + + ## For failed writes, telegraf will cache metric_buffer_limit metrics for each + ## output, and will flush this buffer on a successful write. Oldest metrics + ## are dropped first when this buffer fills. + ## This buffer only fills when writes fail to output plugin(s). + metric_buffer_limit = 10000 + + ## Collection jitter is used to jitter the collection by a random amount. + ## Each plugin will sleep for a random time within jitter before collecting. + ## This can be used to avoid many plugins querying things like sysfs at the + ## same time, which can have a measurable effect on the system. + collection_jitter = "0s" + + ## Default flushing interval for all outputs. Maximum flush_interval will be + ## flush_interval + flush_jitter + flush_interval = "10s" + ## Jitter the flush interval by a random amount. This is primarily to avoid + ## large write spikes for users running a large number of telegraf instances. + ## ie, a jitter of 5s and interval 10s means flushes will happen every 10-15s + flush_jitter = "0s" + + ## By default or when set to "0s", precision will be set to the same + ## timestamp order as the collection interval, with the maximum being 1s. + ## ie, when interval = "10s", precision will be "1s" + ## when interval = "250ms", precision will be "1ms" + ## Precision will NOT be used for service inputs. It is up to each individual + ## service input to set the timestamp at the appropriate precision. + ## Valid time units are "ns", "us" (or "µs"), "ms", "s". + precision = "" + + ## Logging configuration: + ## Run telegraf with debug log messages. + debug = false + ## Run telegraf in quiet mode (error log messages only). + quiet = false + ## Specify the log file name. The empty string means to log to stderr. + logfile = "" + + ## Override default hostname, if empty use os.Hostname() + hostname = "" + ## If set to true, do no set the "host" tag in the telegraf agent. + omit_hostname = false +[[inputs.cpu]] + ## Whether to report per-cpu stats or not + percpu = true + ## Whether to report total system cpu stats or not + totalcpu = true + ## If true, collect raw CPU time metrics. + collect_cpu_time = false + ## If true, compute and report the sum of all non-idle CPU states. + report_active = false +[[outputs.influxdb_v2]] + ## The URLs of the InfluxDB cluster nodes. + ## + ## Multiple URLs can be specified for a single cluster, only ONE of the + ## urls will be written to each interval. + ## urls exp: http://127.0.0.1:9999 + urls = ["http://127.0.0.1:9999"] + + ## Token for authentication. + token = "no_more_secrets" + + ## Organization is the name of the organization you wish to write to; must exist. + organization = "my_org" + + ## Destination bucket to write into. + bucket = "my_bucket" +`, }, nil }, }, @@ -701,7 +744,7 @@ func TestTelegrafHandler_handleGetTelegraf(t *testing.T) { collect_cpu_time = false ## If true, compute and report the sum of all non-idle CPU states. report_active = false -[[outputs.influxdb_v2]] +[[outputs.influxdb_v2]] ## The URLs of the InfluxDB cluster nodes. ## ## Multiple URLs can be specified for a single cluster, only ONE of the @@ -749,7 +792,7 @@ func TestTelegrafHandler_handleGetTelegraf(t *testing.T) { t.Errorf("%q. handleGetTelegraf() = ***%s***", tt.name, diff) } } else if string(body) != tt.wants.body { - t.Errorf("%q. handleGetTelegraf() = \n***%v***\n,\nwant\n***%v***", tt.name, string(body), tt.wants.body) + t.Errorf("%q. handleGetTelegraf() = \n***%v***\nwant\n***%v***", tt.name, string(body), tt.wants.body) } }) } @@ -772,69 +815,27 @@ func Test_newTelegrafResponses(t *testing.T) { OrgID: platform.ID(2), Name: "my config", Description: "", - Agent: platform.TelegrafAgentConfig{ - Interval: 10000, - }, - Plugins: []platform.TelegrafPlugin{ - { - Comment: "my cpu stats", - Config: &inputs.CPUStats{}, - }, - { - Comment: "my influx output", - Config: &outputs.InfluxDBV2{ - URLs: []string{"http://127.0.0.1:9999"}, - Token: "no_more_secrets", - Organization: "my_org", - Bucket: "my_bucket", - }, - }, - }, + Config: "[[inputs.cpu]]\n[[outputs.influxdb_v2]]\n", }, }, }, want: `{ - "configurations": [ - { - "labels": [ - ], - "links": { - "labels": "/api/v2/telegrafs/0000000000000001/labels", - "members": "/api/v2/telegrafs/0000000000000001/members", - "owners": "/api/v2/telegrafs/0000000000000001/owners", - "self": "/api/v2/telegrafs/0000000000000001" - }, - "id": "0000000000000001", - "orgID": "0000000000000002", - "name": "my config", - "description": "", - "agent": { - "collectionInterval": 10000 - }, - "plugins": [ - { - "name": "cpu", - "type": "input", - "comment": "my cpu stats", - "config": {} - }, - { - "name": "influxdb_v2", - "type": "output", - "comment": "my influx output", - "config": { - "urls": [ - "http://127.0.0.1:9999" - ], - "token": "no_more_secrets", - "organization": "my_org", - "bucket": "my_bucket" - } - } - ] - } - ] - }`, + "configurations": [ + { + "id": "0000000000000001", + "orgID": "0000000000000002", + "name": "my config", + "config": "[[inputs.cpu]]\n[[outputs.influxdb_v2]]\n", + "labels": [], + "links": { + "self": "/api/v2/telegrafs/0000000000000001", + "labels": "/api/v2/telegrafs/0000000000000001/labels", + "members": "/api/v2/telegrafs/0000000000000001/members", + "owners": "/api/v2/telegrafs/0000000000000001/owners" + } + } + ] + }`, }, } for _, tt := range tests { @@ -853,7 +854,6 @@ func Test_newTelegrafResponses(t *testing.T) { } func Test_newTelegrafResponse(t *testing.T) { - t.Skip("https://github.com/influxdata/influxdb/issues/12457") type args struct { tc *platform.TelegrafConfig } @@ -869,56 +869,23 @@ func Test_newTelegrafResponse(t *testing.T) { OrgID: platform.ID(2), Name: "my config", Description: "my description", - Agent: platform.TelegrafAgentConfig{ - Interval: 10000, - }, - Plugins: []platform.TelegrafPlugin{ - { - Comment: "my cpu stats", - Config: &inputs.CPUStats{}, - }, - { - Comment: "my influx output", - Config: &outputs.InfluxDBV2{ - URLs: []string{"http://127.0.0.1:9999"}, - Token: "no_more_secrets", - Organization: "my_org", - Bucket: "my_bucket", - }, - }, - }, + Config: "[[inputs.cpu]]\n[[outputs.influxdb_v2]]\n", }, }, want: `{ - "id": "0000000000000001", - "orgID": "0000000000000002", - "name": "my config", - "description": "my description", - "agent": { - "collectionInterval": 10000 - }, - "plugins": [ - { - "name": "cpu", - "type": "input", - "comment": "my cpu stats", - "config": {} - }, - { - "name": "influxdb_v2", - "type": "output", - "comment": "my influx output", - "config": { - "urls": [ - "http://127.0.0.1:9999" - ], - "token": "no_more_secrets", - "organization": "my_org", - "bucket": "my_bucket" - } - } - ] - }`, + "id": "0000000000000001", + "orgID": "0000000000000002", + "name": "my config", + "description": "my description", + "config": "[[inputs.cpu]]\n[[outputs.influxdb_v2]]\n", + "labels": [], + "links": { + "self": "/api/v2/telegrafs/0000000000000001", + "labels": "/api/v2/telegrafs/0000000000000001/labels", + "members": "/api/v2/telegrafs/0000000000000001/members", + "owners": "/api/v2/telegrafs/0000000000000001/owners" + } + }`, }, } for _, tt := range tests { @@ -929,6 +896,7 @@ func Test_newTelegrafResponse(t *testing.T) { t.Fatalf("newTelegrafResponse() JSON marshal %v", err) } if eq, diff, _ := jsonEqual(string(got), tt.want); tt.want != "" && !eq { + fmt.Println(string(got)) t.Errorf("%q. newTelegrafResponse() = ***%s***", tt.name, diff) } }) diff --git a/kv/lookup_service_test.go b/kv/lookup_service_test.go index b6345c6a658..e9c0408f35e 100644 --- a/kv/lookup_service_test.go +++ b/kv/lookup_service_test.go @@ -195,8 +195,9 @@ func testLookupName(newStore StoreFn, t *testing.T) { }, init: func(ctx context.Context, s *kv.Service) error { return s.CreateTelegrafConfig(ctx, &influxdb.TelegrafConfig{ - OrgID: influxdbtesting.MustIDBase16("0000000000000009"), - Name: "telegraf1", + OrgID: influxdbtesting.MustIDBase16("0000000000000009"), + Name: "telegraf1", + Config: "[agent]", }, existingBucketID) }, }, diff --git a/pkger/clone_resource.go b/pkger/clone_resource.go index 4fe5f869d93..3823b06a54d 100644 --- a/pkger/clone_resource.go +++ b/pkger/clone_resource.go @@ -440,7 +440,7 @@ func telegrafToResource(t influxdb.TelegrafConfig, name string) Resource { r := Resource{ fieldKind: KindTelegraf.title(), fieldName: name, - fieldTelegrafConfig: t.TOML(), + fieldTelegrafConfig: t.Config, } assignNonZeroStrings(r, map[string]string{ fieldDescription: t.Description, diff --git a/pkger/parser.go b/pkger/parser.go index 29ddca2fb58..b380f040065 100644 --- a/pkger/parser.go +++ b/pkger/parser.go @@ -12,7 +12,6 @@ import ( "strings" "time" - "github.com/BurntSushi/toml" "github.com/influxdata/influxdb" "gopkg.in/yaml.v3" ) @@ -780,11 +779,11 @@ func (p *Pkg) graphTelegrafs() *parseErr { }) sort.Sort(tele.labels) - cfgBytes := []byte(r.stringShort(fieldTelegrafConfig)) - if err := toml.Unmarshal(cfgBytes, &tele.config); err != nil { + tele.config.Config = r.stringShort(fieldTelegrafConfig) + if tele.config.Config == "" { failures = append(failures, validationErr{ Field: fieldTelegrafConfig, - Msg: err.Error(), + Msg: "no config provided", }) } diff --git a/pkger/testdata/dashboard_heatmap.yml b/pkger/testdata/dashboard_heatmap.yml index c3dc2b0c363..d17f08685d7 100644 --- a/pkger/testdata/dashboard_heatmap.yml +++ b/pkger/testdata/dashboard_heatmap.yml @@ -38,17 +38,17 @@ spec: - hex: "#fbb61a" - hex: "#f4df53" axes: - - name: x - label: x_label - prefix: x_prefix - suffix: x_suffix + - name: "x" + label: "x_label" + prefix: "x_prefix" + suffix: "x_suffix" domain: - 0 - 10 - - name: y - label: y_label - prefix: y_prefix - suffix: y_suffix + - name: "y" + label: "y_label" + prefix: "y_prefix" + suffix: "y_suffix" domain: - 0 - 100 diff --git a/telegraf.go b/telegraf.go index 3ee8779f171..27f90c05536 100644 --- a/telegraf.go +++ b/telegraf.go @@ -3,20 +3,22 @@ package influxdb import ( "context" "encoding/json" - "errors" "fmt" - "time" + "github.com/BurntSushi/toml" "github.com/influxdata/influxdb/telegraf/plugins" "github.com/influxdata/influxdb/telegraf/plugins/inputs" "github.com/influxdata/influxdb/telegraf/plugins/outputs" ) -// ErrTelegrafConfigInvalidOrgID is the error message for a missing or invalid organization ID. -const ErrTelegrafConfigInvalidOrgID = "invalid org ID" - -// ErrTelegrafConfigNotFound is the error message for a missing telegraf config. -const ErrTelegrafConfigNotFound = "telegraf configuration not found" +const ( + ErrTelegrafConfigInvalidOrgID = "invalid org ID" // ErrTelegrafConfigInvalidOrgID is the error message for a missing or invalid organization ID. + ErrTelegrafConfigNotFound = "telegraf configuration not found" // ErrTelegrafConfigNotFound is the error message for a missing telegraf config. + ErrTelegrafPluginNameUnmatch = "the telegraf plugin is name %s doesn't match the config %s" + ErrNoTelegrafPlugins = "there is no telegraf plugin in the config" + ErrUnsupportTelegrafPluginType = "unsupported telegraf plugin type %s" + ErrUnsupportTelegrafPluginName = "unsupported telegraf plugin %s, type %s" +) // ops for buckets error and buckets op logs. var ( @@ -60,318 +62,221 @@ type TelegrafConfigFilter struct { // TelegrafConfig stores telegraf config for one telegraf instance. type TelegrafConfig struct { - ID ID - OrgID ID - Name string - Description string - - Agent TelegrafAgentConfig - Plugins []TelegrafPlugin + ID ID `json:"id,omitempty"` // ID of this config object. + OrgID ID `json:"orgID,omitempty"` // OrgID is the id of the owning organization. + Name string `json:"name,omitempty"` // Name of this config object. + Description string `json:"description,omitempty"` // Decription of this config object. + Config string `json:"config,omitempty"` // ConfigTOML contains the raw toml config. + Metadata map[string]interface{} `json:"metadata,omitempty"` // Metadata for the config. } -// TOML returns the telegraf toml config string. -func (tc TelegrafConfig) TOML() string { - plugins := "" - for _, p := range tc.Plugins { - plugins += p.Config.TOML() - } - interval := time.Duration(tc.Agent.Interval * 1000000) - return fmt.Sprintf(`# Configuration for telegraf agent -[agent] - ## Default data collection interval for all inputs - interval = "%s" - ## Rounds collection interval to 'interval' - ## ie, if interval="10s" then always collect on :00, :10, :20, etc. - round_interval = true - - ## Telegraf will send metrics to outputs in batches of at most - ## metric_batch_size metrics. - ## This controls the size of writes that Telegraf sends to output plugins. - metric_batch_size = 1000 - - ## For failed writes, telegraf will cache metric_buffer_limit metrics for each - ## output, and will flush this buffer on a successful write. Oldest metrics - ## are dropped first when this buffer fills. - ## This buffer only fills when writes fail to output plugin(s). - metric_buffer_limit = 10000 - - ## Collection jitter is used to jitter the collection by a random amount. - ## Each plugin will sleep for a random time within jitter before collecting. - ## This can be used to avoid many plugins querying things like sysfs at the - ## same time, which can have a measurable effect on the system. - collection_jitter = "0s" - - ## Default flushing interval for all outputs. Maximum flush_interval will be - ## flush_interval + flush_jitter - flush_interval = "10s" - ## Jitter the flush interval by a random amount. This is primarily to avoid - ## large write spikes for users running a large number of telegraf instances. - ## ie, a jitter of 5s and interval 10s means flushes will happen every 10-15s - flush_jitter = "0s" - - ## By default or when set to "0s", precision will be set to the same - ## timestamp order as the collection interval, with the maximum being 1s. - ## ie, when interval = "10s", precision will be "1s" - ## when interval = "250ms", precision will be "1ms" - ## Precision will NOT be used for service inputs. It is up to each individual - ## service input to set the timestamp at the appropriate precision. - ## Valid time units are "ns", "us" (or "µs"), "ms", "s". - precision = "" - - ## Logging configuration: - ## Run telegraf with debug log messages. - debug = false - ## Run telegraf in quiet mode (error log messages only). - quiet = false - ## Specify the log file name. The empty string means to log to stderr. - logfile = "" - - ## Override default hostname, if empty use os.Hostname() - hostname = "" - ## If set to true, do no set the "host" tag in the telegraf agent. - omit_hostname = false -%s`, interval.String(), plugins) -} - -// telegrafConfigEncode is the helper struct for json encoding. -type telegrafConfigEncode struct { - ID *ID `json:"id"` - OrgID *ID `json:"orgID,omitempty"` - Name string `json:"name"` - Description string `json:"description"` - - Agent TelegrafAgentConfig `json:"agent"` - - Plugins []telegrafPluginEncode `json:"plugins"` -} - -// telegrafPluginEncode is the helper struct for json encoding. -type telegrafPluginEncode struct { - // Name of the telegraf plugin, exp "docker" - Name string `json:"name"` - Type plugins.Type `json:"type"` - Comment string `json:"comment,omitempty"` - Config plugins.Config `json:"config,omitempty"` -} +// UnmarshalJSON implement the json.Unmarshaler interface. +// Gets called when reading from the kv db. mostly legacy so loading old/stored configs still work. +// May not remove for a while. Primarily will get hit when user views/downloads config. +func (tc *TelegrafConfig) UnmarshalJSON(b []byte) error { + tcd := new(telegrafConfigDecode) -// telegrafConfigDecode is the helper struct for json decoding. -type telegrafConfigDecode struct { - ID *ID `json:"id,omitempty"` - OrganizationID *ID `json:"organizationID,omitempty"` - OrgID *ID `json:"orgID,omitempty"` - Name string `json:"name"` - Description string `json:"description"` + if err := json.Unmarshal(b, tcd); err != nil { + return err + } - Agent TelegrafAgentConfig `json:"agent"` + orgID := tcd.OrgID + if orgID == nil || !orgID.Valid() { + orgID = tcd.OrganizationID + } - Plugins []telegrafPluginDecode `json:"plugins"` -} + if tcd.ID != nil { + tc.ID = *tcd.ID + } -// telegrafPluginDecode is the helper struct for json decoding. -type telegrafPluginDecode struct { - // Name of the telegraf plugin, exp "docker" - Name string `json:"name"` - Type plugins.Type `json:"type"` - Comment string `json:"comment,omitempty"` - Config json.RawMessage `json:"config,omitempty"` -} + if orgID != nil { + tc.OrgID = *orgID + } -// TelegrafPlugin is the general wrapper of the telegraf plugin config -type TelegrafPlugin struct { - Comment string `json:"comment,omitempty"` - Config plugins.Config `json:"config,omitempty"` -} + tc.Name = tcd.Name + tc.Description = tcd.Description -// TelegrafAgentConfig is based telegraf/internal/config AgentConfig. -type TelegrafAgentConfig struct { - // Interval at which to gather information in miliseconds. - Interval int64 `json:"collectionInterval"` -} + // Prefer new structure; use full toml config. + tc.Config = tcd.Config + tc.Metadata = tcd.Metadata -// errors -const ( - ErrTelegrafPluginNameUnmatch = "the telegraf plugin is name %s doesn't match the config %s" - ErrNoTelegrafPlugins = "there is no telegraf plugin in the config" - ErrUnsupportTelegrafPluginType = "unsupported telegraf plugin type %s" - ErrUnsupportTelegrafPluginName = "unsupported telegraf plugin %s, type %s" -) + if tcd.Plugins != nil { + // legacy, remove after some moons. or a migration. + if len(tcd.Plugins) > 0 { + bkts, conf, err := decodePluginRaw(tcd) + if err != nil { + return err + } + tc.Config = plugins.AgentConfig + conf + tc.Metadata = map[string]interface{}{"buckets": bkts} + } else if c, ok := plugins.GetPlugin("output", "influxdb_v2"); ok { + // Handles legacy adding of default plugins (agent and output). + tc.Config = plugins.AgentConfig + c.Config + tc.Metadata = map[string]interface{}{ + "buckets": []string{}, + } + } + } else if tcd.Metadata == nil || len(tcd.Metadata) == 0 { + // Get buckets from the config. + m, err := parseMetadata(tc.Config) + if err != nil { + return err + } -// MarshalJSON implement the json.Marshaler interface. -func (tc *TelegrafConfig) MarshalJSON() ([]byte, error) { - tce := &telegrafConfigEncode{ - Name: tc.Name, - Description: tc.Description, - Agent: tc.Agent, - Plugins: make([]telegrafPluginEncode, len(tc.Plugins)), - } - if tc.OrgID != 0 { - tce.OrgID = &tc.OrgID - } - if tc.ID != 0 { - tce.ID = &tc.ID + tc.Metadata = m } - for k, p := range tc.Plugins { - tce.Plugins[k] = telegrafPluginEncode{ - Name: p.Config.PluginName(), - Type: p.Config.Type(), - Comment: p.Comment, - Config: p.Config, + + if tc.Config == "" { + return &Error{ + Code: EEmptyValue, + Msg: "no config provided", } } - return json.Marshal(tce) + + return nil } -// UnmarshalTOML implements toml.Unmarshaler interface. -func (tc *TelegrafConfig) UnmarshalTOML(data interface{}) error { - dataOk, ok := data.(map[string]interface{}) - if !ok { - return errors.New("blank string") - } - agent, ok := dataOk["agent"].(map[string]interface{}) - if !ok { - return errors.New("agent is missing") - } +type buckets []string - intervalStr, ok := agent["interval"].(string) +func (t *buckets) UnmarshalTOML(data interface{}) error { + dataOk, ok := data.(map[string]interface{}) if !ok { - return errors.New("agent interval is not string") - } - - interval, err := time.ParseDuration(intervalStr) - if err != nil { - return err - } - tc.Agent = TelegrafAgentConfig{ - Interval: interval.Nanoseconds() / 1000000, + return &Error{ + Code: EEmptyValue, + Msg: "no config to get buckets", + } } - + bkts := []string{} for tp, ps := range dataOk { - if tp == "agent" { + if tp != "outputs" { continue } plugins, ok := ps.(map[string]interface{}) if !ok { return &Error{ - Msg: "bad plugin type", + Code: EEmptyValue, + Msg: "no plugins in config to get buckets", } } for name, configDataArray := range plugins { - if configDataArray == nil { - if err := tc.parseTOMLPluginConfig(tp, name, configDataArray); err != nil { - return err - } + if name != "influxdb_v2" { continue } - for _, configData := range configDataArray.([]map[string]interface{}) { - if err := tc.parseTOMLPluginConfig(tp, name, configData); err != nil { - return err + config, ok := configDataArray.([]map[string]interface{}) + if !ok { + return &Error{ + Code: EEmptyValue, + Msg: "influxdb_v2 output has no config", + } + } + for i := range config { + if b, ok := config[i]["bucket"]; ok { + bkts = append(bkts, b.(string)) } } } } + *t = buckets(bkts) + return nil } -func (tc *TelegrafConfig) parseTOMLPluginConfig(typ, name string, configData interface{}) error { - var ok bool - var tpFn func() plugins.Config - switch typ { - case "inputs": - tpFn, ok = availableInputPlugins[name] - case "outputs": - tpFn, ok = availableOutputPlugins[name] - default: - return &Error{ - Msg: fmt.Sprintf(ErrUnsupportTelegrafPluginType, typ), - } - } +func parseMetadata(cfg string) (map[string]interface{}, error) { + bs := []string{} - if !ok { - return &Error{ - Msg: fmt.Sprintf(ErrUnsupportTelegrafPluginName, name, typ), - } + this := &buckets{} + _, err := toml.Decode(cfg, this) + if err != nil { + return nil, err } - p := tpFn() - if err := p.UnmarshalTOML(configData); err != nil { - return err + for _, i := range *this { + if i != "" { + bs = append(bs, i) + } } - tc.Plugins = append(tc.Plugins, TelegrafPlugin{ - Config: p, - }) - return nil -} -// UnmarshalJSON implement the json.Unmarshaler interface. -func (tc *TelegrafConfig) UnmarshalJSON(b []byte) error { - tcd := new(telegrafConfigDecode) - if err := json.Unmarshal(b, tcd); err != nil { - return err - } - *tc = TelegrafConfig{ - Name: tcd.Name, - Description: tcd.Description, - Agent: tcd.Agent, - Plugins: make([]TelegrafPlugin, len(tcd.Plugins)), - } - if tcd.ID != nil { - tc.ID = *tcd.ID - } - if orgID := tcd.OrgID; orgID != nil && orgID.Valid() { - tc.OrgID = *orgID - } else if tcd.OrganizationID != nil { - tc.OrgID = *tcd.OrganizationID - } - return decodePluginRaw(tcd, tc) + return map[string]interface{}{"buckets": bs}, nil } -func decodePluginRaw(tcd *telegrafConfigDecode, tc *TelegrafConfig) (err error) { +// return bucket, config, error +func decodePluginRaw(tcd *telegrafConfigDecode) ([]string, string, error) { op := "unmarshal telegraf config raw plugin" - for k, pr := range tcd.Plugins { + ps := "" + bucket := []string{} + + for _, pr := range tcd.Plugins { var tpFn func() plugins.Config - var config plugins.Config var ok bool + switch pr.Type { - case plugins.Input: + case "input": tpFn, ok = availableInputPlugins[pr.Name] - case plugins.Output: + case "output": tpFn, ok = availableOutputPlugins[pr.Name] default: - return &Error{ + return nil, "", &Error{ Code: EInvalid, - Msg: fmt.Sprintf(ErrUnsupportTelegrafPluginType, pr.Type), Op: op, + Msg: fmt.Sprintf(ErrUnsupportTelegrafPluginType, pr.Type), } } - if ok { - config = tpFn() - // if pr.Config if empty, make it a blank obj, - // so it will still go to the unmarshalling process to validate. - if len(string(pr.Config)) == 0 { - pr.Config = []byte("{}") - } - if err = json.Unmarshal(pr.Config, config); err != nil { - return &Error{ - Code: EInvalid, - Err: err, - Op: op, - } + + if !ok { + return nil, "", &Error{ + Code: EInvalid, + Op: op, + Msg: fmt.Sprintf(ErrUnsupportTelegrafPluginName, pr.Name, pr.Type), } - tc.Plugins[k] = TelegrafPlugin{ - Comment: pr.Comment, - Config: config, + } + + config := tpFn() + // if pr.Config if empty, make it a blank obj, + // so it will still go to the unmarshalling process to validate. + if len(string(pr.Config)) == 0 { + pr.Config = []byte("{}") + } + + if err := json.Unmarshal(pr.Config, config); err != nil { + return nil, "", &Error{ + Code: EInvalid, + Err: err, + Op: op, } - continue } - return &Error{ - Code: EInvalid, - Op: op, - Msg: fmt.Sprintf(ErrUnsupportTelegrafPluginName, pr.Name, pr.Type), + + if pr.Name == "influxdb_v2" { + if b := config.(*outputs.InfluxDBV2).Bucket; b != "" { + bucket = []string{b} + } } + ps += config.TOML() } - return nil + + return bucket, ps, nil +} + +// telegrafConfigDecode is the helper struct for json decoding. legacy. +type telegrafConfigDecode struct { + ID *ID `json:"id,omitempty"` + OrganizationID *ID `json:"organizationID,omitempty"` + OrgID *ID `json:"orgID,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + Config string `json:"config,omitempty"` + Plugins []telegrafPluginDecode `json:"plugins,omitempty"` + Metadata map[string]interface{} `json:"metadata,omitempty"` +} + +// telegrafPluginDecode is the helper struct for json decoding. legacy. +type telegrafPluginDecode struct { + Type string `json:"type,omitempty"` // Type of the plugin. + Name string `json:"name,omitempty"` // Name of the plugin. + Alias string `json:"alias,omitempty"` // Alias of the plugin. + Description string `json:"description,omitempty"` // Description of the plugin. + Config json.RawMessage `json:"config,omitempty"` // Config is the currently stored plugin configuration. } var availableInputPlugins = map[string](func() plugins.Config){ diff --git a/telegraf_test.go b/telegraf_test.go index 0201b3a15bc..cb153c619c6 100644 --- a/telegraf_test.go +++ b/telegraf_test.go @@ -3,16 +3,15 @@ package influxdb import ( "encoding/json" "fmt" - "reflect" "sort" "testing" - "github.com/BurntSushi/toml" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/influxdata/influxdb/telegraf/plugins" "github.com/influxdata/influxdb/telegraf/plugins/inputs" "github.com/influxdata/influxdb/telegraf/plugins/outputs" + "github.com/stretchr/testify/require" ) var telegrafCmpOptions = cmp.Options{ @@ -23,7 +22,6 @@ var telegrafCmpOptions = cmp.Options{ inputs.File{}, outputs.File{}, outputs.InfluxDBV2{}, - unsupportedPlugin{}, ), cmp.Transformer("Sort", func(in []*TelegrafConfig) []*TelegrafConfig { out := append([]*TelegrafConfig(nil), in...) @@ -34,46 +32,7 @@ var telegrafCmpOptions = cmp.Options{ }), } -type unsupportedPluginType struct { - Field string `json:"field"` -} - -func (u *unsupportedPluginType) TOML() string { - return "" -} - -func (u *unsupportedPluginType) PluginName() string { - return "bad_type" -} - -func (u *unsupportedPluginType) Type() plugins.Type { - return plugins.Aggregator -} - -func (u *unsupportedPluginType) UnmarshalTOML(data interface{}) error { - return nil -} - -type unsupportedPlugin struct { - Field string `json:"field"` -} - -func (u *unsupportedPlugin) TOML() string { - return "" -} - -func (u *unsupportedPlugin) PluginName() string { - return "kafka" -} - -func (u *unsupportedPlugin) Type() plugins.Type { - return plugins.Output -} - -func (u *unsupportedPlugin) UnmarshalTOML(data interface{}) error { - return nil -} - +// tests backwards compatibillity with the current plugin aware system. func TestTelegrafConfigJSONDecodeWithoutID(t *testing.T) { s := `{ "name": "config 2", @@ -115,34 +74,198 @@ func TestTelegrafConfigJSONDecodeWithoutID(t *testing.T) { }` want := &TelegrafConfig{ Name: "config 2", - Agent: TelegrafAgentConfig{ - Interval: 120000, - }, - Plugins: []TelegrafPlugin{ - { - Comment: "cpu collect cpu metrics", - Config: &inputs.CPUStats{}, - }, - { - Config: &inputs.Kernel{}, - }, - { - Config: &inputs.Kubernetes{ - URL: "http://1.1.1.1:12", - }, - }, - { - Comment: "3", - Config: &outputs.InfluxDBV2{ - URLs: []string{ - "http://127.0.0.1:9999", - }, - Token: "token1", - Organization: "org", - Bucket: "bucket", - }, - }, - }, + Config: `# Configuration for telegraf agent +[agent] + ## Default data collection interval for all inputs + interval = "10s" + ## Rounds collection interval to 'interval' + ## ie, if interval="10s" then always collect on :00, :10, :20, etc. + round_interval = true + + ## Telegraf will send metrics to outputs in batches of at most + ## metric_batch_size metrics. + ## This controls the size of writes that Telegraf sends to output plugins. + metric_batch_size = 1000 + + ## For failed writes, telegraf will cache metric_buffer_limit metrics for each + ## output, and will flush this buffer on a successful write. Oldest metrics + ## are dropped first when this buffer fills. + ## This buffer only fills when writes fail to output plugin(s). + metric_buffer_limit = 10000 + + ## Collection jitter is used to jitter the collection by a random amount. + ## Each plugin will sleep for a random time within jitter before collecting. + ## This can be used to avoid many plugins querying things like sysfs at the + ## same time, which can have a measurable effect on the system. + collection_jitter = "0s" + + ## Default flushing interval for all outputs. Maximum flush_interval will be + ## flush_interval + flush_jitter + flush_interval = "10s" + ## Jitter the flush interval by a random amount. This is primarily to avoid + ## large write spikes for users running a large number of telegraf instances. + ## ie, a jitter of 5s and interval 10s means flushes will happen every 10-15s + flush_jitter = "0s" + + ## By default or when set to "0s", precision will be set to the same + ## timestamp order as the collection interval, with the maximum being 1s. + ## ie, when interval = "10s", precision will be "1s" + ## when interval = "250ms", precision will be "1ms" + ## Precision will NOT be used for service inputs. It is up to each individual + ## service input to set the timestamp at the appropriate precision. + ## Valid time units are "ns", "us" (or "µs"), "ms", "s". + precision = "" + + ## Logging configuration: + ## Run telegraf with debug log messages. + debug = false + ## Run telegraf in quiet mode (error log messages only). + quiet = false + ## Specify the log file name. The empty string means to log to stderr. + logfile = "" + + ## Override default hostname, if empty use os.Hostname() + hostname = "" + ## If set to true, do no set the "host" tag in the telegraf agent. + omit_hostname = false +[[inputs.cpu]] + ## Whether to report per-cpu stats or not + percpu = true + ## Whether to report total system cpu stats or not + totalcpu = true + ## If true, collect raw CPU time metrics. + collect_cpu_time = false + ## If true, compute and report the sum of all non-idle CPU states. + report_active = false +[[inputs.kernel]] +[[inputs.kubernetes]] + ## URL for the kubelet + ## exp: http://1.1.1.1:10255 + url = "http://1.1.1.1:12" +[[outputs.influxdb_v2]] + ## The URLs of the InfluxDB cluster nodes. + ## + ## Multiple URLs can be specified for a single cluster, only ONE of the + ## urls will be written to each interval. + ## urls exp: http://127.0.0.1:9999 + urls = ["http://127.0.0.1:9999"] + + ## Token for authentication. + token = "token1" + + ## Organization is the name of the organization you wish to write to; must exist. + organization = "org" + + ## Destination bucket to write into. + bucket = "bucket" +`, + Metadata: map[string]interface{}{"buckets": []string{"bucket"}}, + } + got := new(TelegrafConfig) + err := json.Unmarshal([]byte(s), got) + if err != nil { + t.Fatal("json decode error", err.Error()) + } + if diff := cmp.Diff(got, want, telegrafCmpOptions...); diff != "" { + t.Errorf("telegraf configs are different -got/+want\ndiff %s", diff) + } +} + +// tests forwards compatibillity with the new plugin unaware system. +func TestTelegrafConfigJSONDecodeTOML(t *testing.T) { + s := `{ + "name": "config 2", + "config": "# Configuration for telegraf agent\n[agent]\n ## Default data collection interval for all inputs\n interval = \"10s\"\n ## Rounds collection interval to 'interval'\n ## ie, if interval=\"10s\" then always collect on :00, :10, :20, etc.\n round_interval = true\n\n ## Telegraf will send metrics to outputs in batches of at most\n ## metric_batch_size metrics.\n ## This controls the size of writes that Telegraf sends to output plugins.\n metric_batch_size = 1000\n\n ## For failed writes, telegraf will cache metric_buffer_limit metrics for each\n ## output, and will flush this buffer on a successful write. Oldest metrics\n ## are dropped first when this buffer fills.\n ## This buffer only fills when writes fail to output plugin(s).\n metric_buffer_limit = 10000\n\n ## Collection jitter is used to jitter the collection by a random amount.\n ## Each plugin will sleep for a random time within jitter before collecting.\n ## This can be used to avoid many plugins querying things like sysfs at the\n ## same time, which can have a measurable effect on the system.\n collection_jitter = \"0s\"\n\n ## Default flushing interval for all outputs. Maximum flush_interval will be\n ## flush_interval + flush_jitter\n flush_interval = \"10s\"\n ## Jitter the flush interval by a random amount. This is primarily to avoid\n ## large write spikes for users running a large number of telegraf instances.\n ## ie, a jitter of 5s and interval 10s means flushes will happen every 10-15s\n flush_jitter = \"0s\"\n\n ## By default or when set to \"0s\", precision will be set to the same\n ## timestamp order as the collection interval, with the maximum being 1s.\n ## ie, when interval = \"10s\", precision will be \"1s\"\n ## when interval = \"250ms\", precision will be \"1ms\"\n ## Precision will NOT be used for service inputs. It is up to each individual\n ## service input to set the timestamp at the appropriate precision.\n ## Valid time units are \"ns\", \"us\" (or \"µs\"), \"ms\", \"s\".\n precision = \"\"\n\n ## Logging configuration:\n ## Run telegraf with debug log messages.\n debug = false\n ## Run telegraf in quiet mode (error log messages only).\n quiet = false\n ## Specify the log file name. The empty string means to log to stderr.\n logfile = \"\"\n\n ## Override default hostname, if empty use os.Hostname()\n hostname = \"\"\n ## If set to true, do no set the \"host\" tag in the telegraf agent.\n omit_hostname = false\n[[inputs.cpu]]\n ## Whether to report per-cpu stats or not\n percpu = true\n ## Whether to report total system cpu stats or not\n totalcpu = true\n ## If true, collect raw CPU time metrics.\n collect_cpu_time = false\n ## If true, compute and report the sum of all non-idle CPU states.\n report_active = false\n[[inputs.kernel]]\n[[inputs.kubernetes]]\n ## URL for the kubelet\n ## exp: http://1.1.1.1:10255\n url = \"http://1.1.1.1:12\"\n[[outputs.influxdb_v2]]\n ## The URLs of the InfluxDB cluster nodes.\n ##\n ## Multiple URLs can be specified for a single cluster, only ONE of the\n ## urls will be written to each interval.\n ## urls exp: http://127.0.0.1:9999\n urls = [\"http://127.0.0.1:9999\"]\n\n ## Token for authentication.\n token = \"token1\"\n\n ## Organization is the name of the organization you wish to write to; must exist.\n organization = \"org\"\n\n ## Destination bucket to write into.\n bucket = \"bucket\"\n" + }` + + want := &TelegrafConfig{ + Name: "config 2", + Config: `# Configuration for telegraf agent +[agent] + ## Default data collection interval for all inputs + interval = "10s" + ## Rounds collection interval to 'interval' + ## ie, if interval="10s" then always collect on :00, :10, :20, etc. + round_interval = true + + ## Telegraf will send metrics to outputs in batches of at most + ## metric_batch_size metrics. + ## This controls the size of writes that Telegraf sends to output plugins. + metric_batch_size = 1000 + + ## For failed writes, telegraf will cache metric_buffer_limit metrics for each + ## output, and will flush this buffer on a successful write. Oldest metrics + ## are dropped first when this buffer fills. + ## This buffer only fills when writes fail to output plugin(s). + metric_buffer_limit = 10000 + + ## Collection jitter is used to jitter the collection by a random amount. + ## Each plugin will sleep for a random time within jitter before collecting. + ## This can be used to avoid many plugins querying things like sysfs at the + ## same time, which can have a measurable effect on the system. + collection_jitter = "0s" + + ## Default flushing interval for all outputs. Maximum flush_interval will be + ## flush_interval + flush_jitter + flush_interval = "10s" + ## Jitter the flush interval by a random amount. This is primarily to avoid + ## large write spikes for users running a large number of telegraf instances. + ## ie, a jitter of 5s and interval 10s means flushes will happen every 10-15s + flush_jitter = "0s" + + ## By default or when set to "0s", precision will be set to the same + ## timestamp order as the collection interval, with the maximum being 1s. + ## ie, when interval = "10s", precision will be "1s" + ## when interval = "250ms", precision will be "1ms" + ## Precision will NOT be used for service inputs. It is up to each individual + ## service input to set the timestamp at the appropriate precision. + ## Valid time units are "ns", "us" (or "µs"), "ms", "s". + precision = "" + + ## Logging configuration: + ## Run telegraf with debug log messages. + debug = false + ## Run telegraf in quiet mode (error log messages only). + quiet = false + ## Specify the log file name. The empty string means to log to stderr. + logfile = "" + + ## Override default hostname, if empty use os.Hostname() + hostname = "" + ## If set to true, do no set the "host" tag in the telegraf agent. + omit_hostname = false +[[inputs.cpu]] + ## Whether to report per-cpu stats or not + percpu = true + ## Whether to report total system cpu stats or not + totalcpu = true + ## If true, collect raw CPU time metrics. + collect_cpu_time = false + ## If true, compute and report the sum of all non-idle CPU states. + report_active = false +[[inputs.kernel]] +[[inputs.kubernetes]] + ## URL for the kubelet + ## exp: http://1.1.1.1:10255 + url = "http://1.1.1.1:12" +[[outputs.influxdb_v2]] + ## The URLs of the InfluxDB cluster nodes. + ## + ## Multiple URLs can be specified for a single cluster, only ONE of the + ## urls will be written to each interval. + ## urls exp: http://127.0.0.1:9999 + urls = ["http://127.0.0.1:9999"] + + ## Token for authentication. + token = "token1" + + ## Organization is the name of the organization you wish to write to; must exist. + organization = "org" + + ## Destination bucket to write into. + bucket = "bucket" +`, + Metadata: map[string]interface{}{"buckets": []string{"bucket"}}, } got := new(TelegrafConfig) err := json.Unmarshal([]byte(s), got) @@ -159,37 +282,41 @@ func TestTelegrafConfigJSONCompatibleMode(t *testing.T) { id2, _ := IDFromString("020f755c3c082222") id3, _ := IDFromString("020f755c3c082223") cases := []struct { - name string - src []byte - cfg *TelegrafConfig - err error + name string + src []byte + cfg *TelegrafConfig + expMeta map[string]interface{} + err error }{ { name: "newest", src: []byte(`{"id":"020f755c3c082000","orgID":"020f755c3c082222","plugins":[]}`), cfg: &TelegrafConfig{ - ID: *id1, - OrgID: *id2, - Plugins: []TelegrafPlugin{}, + ID: *id1, + OrgID: *id2, + Config: "# Configuration for telegraf agent\n[agent]\n ## Default data collection interval for all inputs\n interval = \"10s\"\n ## Rounds collection interval to 'interval'\n ## ie, if interval=\"10s\" then always collect on :00, :10, :20, etc.\n round_interval = true\n\n ## Telegraf will send metrics to outputs in batches of at most\n ## metric_batch_size metrics.\n ## This controls the size of writes that Telegraf sends to output plugins.\n metric_batch_size = 1000\n\n ## For failed writes, telegraf will cache metric_buffer_limit metrics for each\n ## output, and will flush this buffer on a successful write. Oldest metrics\n ## are dropped first when this buffer fills.\n ## This buffer only fills when writes fail to output plugin(s).\n metric_buffer_limit = 10000\n\n ## Collection jitter is used to jitter the collection by a random amount.\n ## Each plugin will sleep for a random time within jitter before collecting.\n ## This can be used to avoid many plugins querying things like sysfs at the\n ## same time, which can have a measurable effect on the system.\n collection_jitter = \"0s\"\n\n ## Default flushing interval for all outputs. Maximum flush_interval will be\n ## flush_interval + flush_jitter\n flush_interval = \"10s\"\n ## Jitter the flush interval by a random amount. This is primarily to avoid\n ## large write spikes for users running a large number of telegraf instances.\n ## ie, a jitter of 5s and interval 10s means flushes will happen every 10-15s\n flush_jitter = \"0s\"\n\n ## By default or when set to \"0s\", precision will be set to the same\n ## timestamp order as the collection interval, with the maximum being 1s.\n ## ie, when interval = \"10s\", precision will be \"1s\"\n ## when interval = \"250ms\", precision will be \"1ms\"\n ## Precision will NOT be used for service inputs. It is up to each individual\n ## service input to set the timestamp at the appropriate precision.\n ## Valid time units are \"ns\", \"us\" (or \"µs\"), \"ms\", \"s\".\n precision = \"\"\n\n ## Logging configuration:\n ## Run telegraf with debug log messages.\n debug = false\n ## Run telegraf in quiet mode (error log messages only).\n quiet = false\n ## Specify the log file name. The empty string means to log to stderr.\n logfile = \"\"\n\n ## Override default hostname, if empty use os.Hostname()\n hostname = \"\"\n ## If set to true, do no set the \"host\" tag in the telegraf agent.\n omit_hostname = false\n# Configuration for sending metrics to InfluxDB\n[[outputs.influxdb_v2]]\n # alias=\"influxdb_v2\"\n ## The URLs of the InfluxDB cluster nodes.\n ##\n ## Multiple URLs can be specified for a single cluster, only ONE of the\n ## urls will be written to each interval.\n ## ex: urls = [\"https://us-west-2-1.aws.cloud2.influxdata.com\"]\n urls = [\"http://127.0.0.1:9999\"]\n\n ## Token for authentication.\n token = \"\"\n\n ## Organization is the name of the organization you wish to write to; must exist.\n organization = \"\"\n\n ## Destination bucket to write into.\n bucket = \"\"\n\n ## The value of this tag will be used to determine the bucket. If this\n ## tag is not set the 'bucket' option is used as the default.\n # bucket_tag = \"\"\n\n ## If true, the bucket tag will not be added to the metric.\n # exclude_bucket_tag = false\n\n ## Timeout for HTTP messages.\n # timeout = \"5s\"\n\n ## Additional HTTP headers\n # http_headers = {\"X-Special-Header\" = \"Special-Value\"}\n\n ## HTTP Proxy override, if unset values the standard proxy environment\n ## variables are consulted to determine which proxy, if any, should be used.\n # http_proxy = \"http://corporate.proxy:3128\"\n\n ## HTTP User-Agent\n # user_agent = \"telegraf\"\n\n ## Content-Encoding for write request body, can be set to \"gzip\" to\n ## compress body or \"identity\" to apply no encoding.\n # content_encoding = \"gzip\"\n\n ## Enable or disable uint support for writing uints influxdb 2.0.\n # influx_uint_support = false\n\n ## Optional TLS Config for use on HTTP connections.\n # tls_ca = \"/etc/telegraf/ca.pem\"\n # tls_cert = \"/etc/telegraf/cert.pem\"\n # tls_key = \"/etc/telegraf/key.pem\"\n ## Use TLS but skip chain & host verification\n # insecure_skip_verify = false\n\n", }, + expMeta: map[string]interface{}{"buckets": []string{}}, }, { name: "old", src: []byte(`{"id":"020f755c3c082000","organizationID":"020f755c3c082222","plugins":[]}`), cfg: &TelegrafConfig{ - ID: *id1, - OrgID: *id2, - Plugins: []TelegrafPlugin{}, + ID: *id1, + OrgID: *id2, + Config: "# Configuration for telegraf agent\n[agent]\n ## Default data collection interval for all inputs\n interval = \"10s\"\n ## Rounds collection interval to 'interval'\n ## ie, if interval=\"10s\" then always collect on :00, :10, :20, etc.\n round_interval = true\n\n ## Telegraf will send metrics to outputs in batches of at most\n ## metric_batch_size metrics.\n ## This controls the size of writes that Telegraf sends to output plugins.\n metric_batch_size = 1000\n\n ## For failed writes, telegraf will cache metric_buffer_limit metrics for each\n ## output, and will flush this buffer on a successful write. Oldest metrics\n ## are dropped first when this buffer fills.\n ## This buffer only fills when writes fail to output plugin(s).\n metric_buffer_limit = 10000\n\n ## Collection jitter is used to jitter the collection by a random amount.\n ## Each plugin will sleep for a random time within jitter before collecting.\n ## This can be used to avoid many plugins querying things like sysfs at the\n ## same time, which can have a measurable effect on the system.\n collection_jitter = \"0s\"\n\n ## Default flushing interval for all outputs. Maximum flush_interval will be\n ## flush_interval + flush_jitter\n flush_interval = \"10s\"\n ## Jitter the flush interval by a random amount. This is primarily to avoid\n ## large write spikes for users running a large number of telegraf instances.\n ## ie, a jitter of 5s and interval 10s means flushes will happen every 10-15s\n flush_jitter = \"0s\"\n\n ## By default or when set to \"0s\", precision will be set to the same\n ## timestamp order as the collection interval, with the maximum being 1s.\n ## ie, when interval = \"10s\", precision will be \"1s\"\n ## when interval = \"250ms\", precision will be \"1ms\"\n ## Precision will NOT be used for service inputs. It is up to each individual\n ## service input to set the timestamp at the appropriate precision.\n ## Valid time units are \"ns\", \"us\" (or \"µs\"), \"ms\", \"s\".\n precision = \"\"\n\n ## Logging configuration:\n ## Run telegraf with debug log messages.\n debug = false\n ## Run telegraf in quiet mode (error log messages only).\n quiet = false\n ## Specify the log file name. The empty string means to log to stderr.\n logfile = \"\"\n\n ## Override default hostname, if empty use os.Hostname()\n hostname = \"\"\n ## If set to true, do no set the \"host\" tag in the telegraf agent.\n omit_hostname = false\n# Configuration for sending metrics to InfluxDB\n[[outputs.influxdb_v2]]\n # alias=\"influxdb_v2\"\n ## The URLs of the InfluxDB cluster nodes.\n ##\n ## Multiple URLs can be specified for a single cluster, only ONE of the\n ## urls will be written to each interval.\n ## ex: urls = [\"https://us-west-2-1.aws.cloud2.influxdata.com\"]\n urls = [\"http://127.0.0.1:9999\"]\n\n ## Token for authentication.\n token = \"\"\n\n ## Organization is the name of the organization you wish to write to; must exist.\n organization = \"\"\n\n ## Destination bucket to write into.\n bucket = \"\"\n\n ## The value of this tag will be used to determine the bucket. If this\n ## tag is not set the 'bucket' option is used as the default.\n # bucket_tag = \"\"\n\n ## If true, the bucket tag will not be added to the metric.\n # exclude_bucket_tag = false\n\n ## Timeout for HTTP messages.\n # timeout = \"5s\"\n\n ## Additional HTTP headers\n # http_headers = {\"X-Special-Header\" = \"Special-Value\"}\n\n ## HTTP Proxy override, if unset values the standard proxy environment\n ## variables are consulted to determine which proxy, if any, should be used.\n # http_proxy = \"http://corporate.proxy:3128\"\n\n ## HTTP User-Agent\n # user_agent = \"telegraf\"\n\n ## Content-Encoding for write request body, can be set to \"gzip\" to\n ## compress body or \"identity\" to apply no encoding.\n # content_encoding = \"gzip\"\n\n ## Enable or disable uint support for writing uints influxdb 2.0.\n # influx_uint_support = false\n\n ## Optional TLS Config for use on HTTP connections.\n # tls_ca = \"/etc/telegraf/ca.pem\"\n # tls_cert = \"/etc/telegraf/cert.pem\"\n # tls_key = \"/etc/telegraf/key.pem\"\n ## Use TLS but skip chain & host verification\n # insecure_skip_verify = false\n\n", }, + expMeta: map[string]interface{}{"buckets": []string{}}, }, { name: "conflict", src: []byte(`{"id":"020f755c3c082000","organizationID":"020f755c3c082222","orgID":"020f755c3c082223","plugins":[]}`), cfg: &TelegrafConfig{ - ID: *id1, - OrgID: *id3, - Plugins: []TelegrafPlugin{}, + ID: *id1, + OrgID: *id3, + Config: "# Configuration for telegraf agent\n[agent]\n ## Default data collection interval for all inputs\n interval = \"10s\"\n ## Rounds collection interval to 'interval'\n ## ie, if interval=\"10s\" then always collect on :00, :10, :20, etc.\n round_interval = true\n\n ## Telegraf will send metrics to outputs in batches of at most\n ## metric_batch_size metrics.\n ## This controls the size of writes that Telegraf sends to output plugins.\n metric_batch_size = 1000\n\n ## For failed writes, telegraf will cache metric_buffer_limit metrics for each\n ## output, and will flush this buffer on a successful write. Oldest metrics\n ## are dropped first when this buffer fills.\n ## This buffer only fills when writes fail to output plugin(s).\n metric_buffer_limit = 10000\n\n ## Collection jitter is used to jitter the collection by a random amount.\n ## Each plugin will sleep for a random time within jitter before collecting.\n ## This can be used to avoid many plugins querying things like sysfs at the\n ## same time, which can have a measurable effect on the system.\n collection_jitter = \"0s\"\n\n ## Default flushing interval for all outputs. Maximum flush_interval will be\n ## flush_interval + flush_jitter\n flush_interval = \"10s\"\n ## Jitter the flush interval by a random amount. This is primarily to avoid\n ## large write spikes for users running a large number of telegraf instances.\n ## ie, a jitter of 5s and interval 10s means flushes will happen every 10-15s\n flush_jitter = \"0s\"\n\n ## By default or when set to \"0s\", precision will be set to the same\n ## timestamp order as the collection interval, with the maximum being 1s.\n ## ie, when interval = \"10s\", precision will be \"1s\"\n ## when interval = \"250ms\", precision will be \"1ms\"\n ## Precision will NOT be used for service inputs. It is up to each individual\n ## service input to set the timestamp at the appropriate precision.\n ## Valid time units are \"ns\", \"us\" (or \"µs\"), \"ms\", \"s\".\n precision = \"\"\n\n ## Logging configuration:\n ## Run telegraf with debug log messages.\n debug = false\n ## Run telegraf in quiet mode (error log messages only).\n quiet = false\n ## Specify the log file name. The empty string means to log to stderr.\n logfile = \"\"\n\n ## Override default hostname, if empty use os.Hostname()\n hostname = \"\"\n ## If set to true, do no set the \"host\" tag in the telegraf agent.\n omit_hostname = false\n# Configuration for sending metrics to InfluxDB\n[[outputs.influxdb_v2]]\n # alias=\"influxdb_v2\"\n ## The URLs of the InfluxDB cluster nodes.\n ##\n ## Multiple URLs can be specified for a single cluster, only ONE of the\n ## urls will be written to each interval.\n ## ex: urls = [\"https://us-west-2-1.aws.cloud2.influxdata.com\"]\n urls = [\"http://127.0.0.1:9999\"]\n\n ## Token for authentication.\n token = \"\"\n\n ## Organization is the name of the organization you wish to write to; must exist.\n organization = \"\"\n\n ## Destination bucket to write into.\n bucket = \"\"\n\n ## The value of this tag will be used to determine the bucket. If this\n ## tag is not set the 'bucket' option is used as the default.\n # bucket_tag = \"\"\n\n ## If true, the bucket tag will not be added to the metric.\n # exclude_bucket_tag = false\n\n ## Timeout for HTTP messages.\n # timeout = \"5s\"\n\n ## Additional HTTP headers\n # http_headers = {\"X-Special-Header\" = \"Special-Value\"}\n\n ## HTTP Proxy override, if unset values the standard proxy environment\n ## variables are consulted to determine which proxy, if any, should be used.\n # http_proxy = \"http://corporate.proxy:3128\"\n\n ## HTTP User-Agent\n # user_agent = \"telegraf\"\n\n ## Content-Encoding for write request body, can be set to \"gzip\" to\n ## compress body or \"identity\" to apply no encoding.\n # content_encoding = \"gzip\"\n\n ## Enable or disable uint support for writing uints influxdb 2.0.\n # influx_uint_support = false\n\n ## Optional TLS Config for use on HTTP connections.\n # tls_ca = \"/etc/telegraf/ca.pem\"\n # tls_cert = \"/etc/telegraf/cert.pem\"\n # tls_key = \"/etc/telegraf/key.pem\"\n ## Use TLS but skip chain & host verification\n # insecure_skip_verify = false\n\n", }, + expMeta: map[string]interface{}{"buckets": []string{}}, }, } for _, c := range cases { @@ -200,6 +327,8 @@ func TestTelegrafConfigJSONCompatibleMode(t *testing.T) { t.Fatalf("%s decode failed, got err: %v, should be %v", c.name, err, c.err) } + c.cfg.Metadata = c.expMeta + // todo:this might not set buckets but should if diff := cmp.Diff(got, c.cfg, telegrafCmpOptions...); c.err == nil && diff != "" { t.Errorf("failed %s, telegraf configs are different -got/+want\ndiff %s", c.name, diff) } @@ -211,61 +340,83 @@ func TestTelegrafConfigJSON(t *testing.T) { id1, _ := IDFromString("020f755c3c082000") id2, _ := IDFromString("020f755c3c082222") cases := []struct { - name string - cfg *TelegrafConfig - err error + name string + expect *TelegrafConfig + cfg string + err error }{ { name: "regular config", - cfg: &TelegrafConfig{ - ID: *id1, - OrgID: *id2, - Name: "n1", - Agent: TelegrafAgentConfig{ - Interval: 4000, + cfg: fmt.Sprintf(`{ + "ID": "%v", + "OrgID": "%v", + "Name": "n1", + "Agent": { + "Interval": 4000 }, - Plugins: []TelegrafPlugin{ + "Plugins": [ { - Comment: "comment1", - Config: &inputs.File{ - Files: []string{"f1", "f2"}, - }, + "name": "file", + "type": "input", + "comment": "comment1", + "config": { + "files": ["f1", "f2"] + } }, { - Comment: "comment2", - Config: &inputs.CPUStats{}, + "name": "cpu", + "type": "input", + "comment": "comment2", + "config": {} }, { - Comment: "comment3", - Config: &outputs.File{Files: []outputs.FileConfig{ - {Typ: "stdout"}, - }}, + "name": "file", + "type": "output", + "comment": "comment3", + "config": { + "files": [ + { + "type": "stdout" + } + ] + } }, { - Comment: "comment4", - Config: &outputs.InfluxDBV2{ - URLs: []string{"url1", "url2"}, - Token: "tok1", - }, - }, - }, + "name": "influxdb_v2", + "type": "output", + "comment": "comment4", + "config": { + "URLs": ["url1", "url2"], + "Token": "tok1" + } + } + ] + }`, *id1, *id2), + expect: &TelegrafConfig{ + ID: *id1, + OrgID: *id2, + Name: "n1", + Config: "# Configuration for telegraf agent\n[agent]\n ## Default data collection interval for all inputs\n interval = \"10s\"\n ## Rounds collection interval to 'interval'\n ## ie, if interval=\"10s\" then always collect on :00, :10, :20, etc.\n round_interval = true\n\n ## Telegraf will send metrics to outputs in batches of at most\n ## metric_batch_size metrics.\n ## This controls the size of writes that Telegraf sends to output plugins.\n metric_batch_size = 1000\n\n ## For failed writes, telegraf will cache metric_buffer_limit metrics for each\n ## output, and will flush this buffer on a successful write. Oldest metrics\n ## are dropped first when this buffer fills.\n ## This buffer only fills when writes fail to output plugin(s).\n metric_buffer_limit = 10000\n\n ## Collection jitter is used to jitter the collection by a random amount.\n ## Each plugin will sleep for a random time within jitter before collecting.\n ## This can be used to avoid many plugins querying things like sysfs at the\n ## same time, which can have a measurable effect on the system.\n collection_jitter = \"0s\"\n\n ## Default flushing interval for all outputs. Maximum flush_interval will be\n ## flush_interval + flush_jitter\n flush_interval = \"10s\"\n ## Jitter the flush interval by a random amount. This is primarily to avoid\n ## large write spikes for users running a large number of telegraf instances.\n ## ie, a jitter of 5s and interval 10s means flushes will happen every 10-15s\n flush_jitter = \"0s\"\n\n ## By default or when set to \"0s\", precision will be set to the same\n ## timestamp order as the collection interval, with the maximum being 1s.\n ## ie, when interval = \"10s\", precision will be \"1s\"\n ## when interval = \"250ms\", precision will be \"1ms\"\n ## Precision will NOT be used for service inputs. It is up to each individual\n ## service input to set the timestamp at the appropriate precision.\n ## Valid time units are \"ns\", \"us\" (or \"µs\"), \"ms\", \"s\".\n precision = \"\"\n\n ## Logging configuration:\n ## Run telegraf with debug log messages.\n debug = false\n ## Run telegraf in quiet mode (error log messages only).\n quiet = false\n ## Specify the log file name. The empty string means to log to stderr.\n logfile = \"\"\n\n ## Override default hostname, if empty use os.Hostname()\n hostname = \"\"\n ## If set to true, do no set the \"host\" tag in the telegraf agent.\n omit_hostname = false\n[[inputs.file]]\t\n ## Files to parse each interval.\n ## These accept standard unix glob matching rules, but with the addition of\n ## ** as a \"super asterisk\". ie:\n ## /var/log/**.log -> recursively find all .log files in /var/log\n ## /var/log/*/*.log -> find all .log files with a parent dir in /var/log\n ## /var/log/apache.log -> only read the apache log file\n files = [\"f1\", \"f2\"]\n\n ## The dataformat to be read from files\n ## Each data format has its own unique set of configuration options, read\n ## more about them here:\n ## https://github.com/influxdata/telegraf/blob/master/docs/DATA_FORMATS_INPUT.md\n data_format = \"influx\"\n[[inputs.cpu]]\n ## Whether to report per-cpu stats or not\n percpu = true\n ## Whether to report total system cpu stats or not\n totalcpu = true\n ## If true, collect raw CPU time metrics.\n collect_cpu_time = false\n ## If true, compute and report the sum of all non-idle CPU states.\n report_active = false\n[[outputs.file]]\n ## Files to write to, \"stdout\" is a specially handled file.\n files = [\"stdout\"]\n[[outputs.influxdb_v2]]\t\n ## The URLs of the InfluxDB cluster nodes.\n ##\n ## Multiple URLs can be specified for a single cluster, only ONE of the\n ## urls will be written to each interval.\n ## urls exp: http://127.0.0.1:9999\n urls = [\"url1\", \"url2\"]\n\n ## Token for authentication.\n token = \"tok1\"\n\n ## Organization is the name of the organization you wish to write to; must exist.\n organization = \"\"\n\n ## Destination bucket to write into.\n bucket = \"\"\n", + Metadata: map[string]interface{}{"buckets": []string{}}, }, }, { name: "unsupported plugin type", - cfg: &TelegrafConfig{ - ID: *id1, - OrgID: *id2, - Name: "n1", - Plugins: []TelegrafPlugin{ + cfg: fmt.Sprintf(`{ + "ID": "%v", + "OrgID": "%v", + "Name": "n1", + "Plugins": [ { - Comment: "comment3", - Config: &unsupportedPluginType{ - Field: "f1", - }, - }, - }, - }, + "name": "bad_type", + "type": "aggregator", + "Comment": "comment3", + "Config": { + "Field": "f1" + } + } + ] + }`, *id1, *id2), err: &Error{ Code: EInvalid, Msg: fmt.Sprintf(ErrUnsupportTelegrafPluginType, "aggregator"), @@ -274,18 +425,20 @@ func TestTelegrafConfigJSON(t *testing.T) { }, { name: "unsupported plugin", - cfg: &TelegrafConfig{ - ID: *id1, - OrgID: *id2, - Name: "n1", - Plugins: []TelegrafPlugin{ + cfg: fmt.Sprintf(`{ + "ID": "%v", + "OrgID": "%v", + "Name": "n1", + "Plugins": [ { - Config: &unsupportedPlugin{ - Field: "f2", - }, - }, - }, - }, + "name": "kafka", + "type": "output", + "Config": { + "Field": "f2" + } + } + ] + }`, *id1, *id2), err: &Error{ Code: EInvalid, Msg: fmt.Sprintf(ErrUnsupportTelegrafPluginName, "kafka", plugins.Output), @@ -294,67 +447,69 @@ func TestTelegrafConfigJSON(t *testing.T) { }, } for _, c := range cases { - result, err := json.Marshal(c.cfg) - // encode testing - if err != nil { - t.Fatalf("%s encode failed, got: %v, should be nil", c.name, err) - } got := new(TelegrafConfig) - err = json.Unmarshal([]byte(result), got) + err := json.Unmarshal([]byte(c.cfg), got) if diff := cmp.Diff(err, c.err); diff != "" { t.Fatalf("%s decode failed, got err: %v, should be %v", c.name, err, c.err) } - if diff := cmp.Diff(got, c.cfg, telegrafCmpOptions...); c.err == nil && diff != "" { + if diff := cmp.Diff(got, c.expect, telegrafCmpOptions...); c.err == nil && diff != "" { t.Errorf("failed %s, telegraf configs are different -got/+want\ndiff %s", c.name, diff) } } } -func TestTOML(t *testing.T) { +func TestLegacyStruct(t *testing.T) { id1, _ := IDFromString("020f755c3c082000") - tc := &TelegrafConfig{ - ID: *id1, - Name: "n1", - Agent: TelegrafAgentConfig{ - Interval: 4000, + telConfOld := fmt.Sprintf(`{ + "id": "%v", + "name": "n1", + "agent": { + "interval": 10000 }, - Plugins: []TelegrafPlugin{ + "plugins": [ { - Comment: "comment1", - Config: &inputs.File{ - Files: []string{"f1", "f2"}, - }, + "name": "file", + "type": "input", + "comment": "comment1", + "config": { + "files": ["f1", "f2"] + } }, { - Comment: "comment2", - Config: &inputs.CPUStats{}, + "name": "cpu", + "type": "input", + "comment": "comment2" }, { - Comment: "comment3", - Config: &outputs.File{Files: []outputs.FileConfig{ - {Typ: "stdout"}, - }}, + "name": "file", + "type": "output", + "comment": "comment3", + "config": {"files": [ + {"type": "stdout"} + ]} }, { - Comment: "comment4", - Config: &outputs.InfluxDBV2{ - URLs: []string{ + "name": "influxdb_v2", + "type": "output", + "comment": "comment4", + "config": { + "urls": [ "url1", - "url2", - }, - Token: "token1", - Organization: "org1", - Bucket: "bucket1", - }, - }, - }, - } + "url2" + ], + "token": "token1", + "organization": "org1", + "bucket": "bucket1" + } + } + ] + }`, *id1) want := `# Configuration for telegraf agent [agent] ## Default data collection interval for all inputs - interval = "4s" + interval = "10s" ## Rounds collection interval to 'interval' ## ie, if interval="10s" then always collect on :00, :10, :20, etc. round_interval = true @@ -448,15 +603,10 @@ func TestTOML(t *testing.T) { ## Destination bucket to write into. bucket = "bucket1" ` - if result := tc.TOML(); result != want { - t.Fatalf("telegraf config's toml is incorrect, got %s", result) - } - tcr := new(TelegrafConfig) - err := toml.Unmarshal([]byte(want), tcr) - if err != nil { - t.Fatalf("telegraf toml parsing issue %s", err.Error()) - } - if reflect.DeepEqual(tcr, tc) { - t.Fatalf("telegraf toml parsing issue, want %q, got %q", tc, tcr) + tc := &TelegrafConfig{} + require.NoError(t, json.Unmarshal([]byte(telConfOld), tc)) + + if tc.Config != want { + t.Fatalf("telegraf config's toml is incorrect, got %+v", tc.Config) } } diff --git a/testing/telegraf.go b/testing/telegraf.go index 5bb0cc350ba..02fd8d30dac 100644 --- a/testing/telegraf.go +++ b/testing/telegraf.go @@ -1,7 +1,6 @@ package testing import ( - "bytes" "context" "fmt" "sort" @@ -40,19 +39,6 @@ var telegrafCmpOptions = cmp.Options{ }), } -var userResourceMappingCmpOptions = cmp.Options{ - cmp.Comparer(func(x, y []byte) bool { - return bytes.Equal(x, y) - }), - cmp.Transformer("Sort", func(in []*platform.UserResourceMapping) []*platform.UserResourceMapping { - out := append([]*platform.UserResourceMapping(nil), in...) - sort.Slice(out, func(i, j int) bool { - return out[i].ResourceID.String() > out[j].ResourceID.String() - }) - return out - }), -} - // TelegrafConfigStore tests all the service functions. func TelegrafConfigStore( init func(TelegrafConfigFields, *testing.T) (platform.TelegrafConfigStore, func()), t *testing.T, @@ -138,26 +124,10 @@ func CreateTelegrafConfig( args: args{ userID: MustIDBase16(threeID), telegrafConfig: &platform.TelegrafConfig{ - OrgID: MustIDBase16(twoID), - Name: "name1", - Agent: platform.TelegrafAgentConfig{ - Interval: 1000, - }, - Plugins: []platform.TelegrafPlugin{ - { - Comment: "comment1", - Config: &inputs.CPUStats{}, - }, - { - Comment: "comment2", - Config: &outputs.InfluxDBV2{ - URLs: []string{"localhost/9999"}, - Token: "token1", - Organization: "org1", - Bucket: "bucket1", - }, - }, - }, + OrgID: MustIDBase16(twoID), + Name: "name1", + Config: "[[inputs.cpu]]\n[[outputs.influxdb_v2]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, }, }, wants: wants{ @@ -171,27 +141,11 @@ func CreateTelegrafConfig( }, telegrafs: []*platform.TelegrafConfig{ { - ID: MustIDBase16(oneID), - OrgID: MustIDBase16(twoID), - Name: "name1", - Agent: platform.TelegrafAgentConfig{ - Interval: 1000, - }, - Plugins: []platform.TelegrafPlugin{ - { - Comment: "comment1", - Config: &inputs.CPUStats{}, - }, - { - Comment: "comment2", - Config: &outputs.InfluxDBV2{ - URLs: []string{"localhost/9999"}, - Token: "token1", - Organization: "org1", - Bucket: "bucket1", - }, - }, - }, + ID: MustIDBase16(oneID), + OrgID: MustIDBase16(twoID), + Name: "name1", + Config: "[[inputs.cpu]]\n[[outputs.influxdb_v2]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, }, }, }, @@ -202,18 +156,11 @@ func CreateTelegrafConfig( IDGenerator: mock.NewIDGenerator(twoID, t), TelegrafConfigs: []*platform.TelegrafConfig{ { - ID: MustIDBase16(oneID), - OrgID: MustIDBase16(twoID), - Name: "tc1", - Agent: platform.TelegrafAgentConfig{ - Interval: 4000, - }, - Plugins: []platform.TelegrafPlugin{ - { - Comment: "comment1", - Config: &inputs.MemStats{}, - }, - }, + ID: MustIDBase16(oneID), + OrgID: MustIDBase16(twoID), + Name: "tc1", + Config: "[[inputs.mem_stats]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, }, }, UserResourceMappings: []*platform.UserResourceMapping{ @@ -228,66 +175,27 @@ func CreateTelegrafConfig( args: args{ userID: MustIDBase16(threeID), telegrafConfig: &platform.TelegrafConfig{ - OrgID: MustIDBase16(twoID), - Name: "name2", - Agent: platform.TelegrafAgentConfig{ - Interval: 1001, - }, - Plugins: []platform.TelegrafPlugin{ - { - Comment: "comment2", - Config: &inputs.CPUStats{}, - }, - { - Comment: "comment3", - Config: &outputs.InfluxDBV2{ - URLs: []string{"localhost/9999"}, - Token: "token3", - Organization: "org3", - Bucket: "bucket3", - }, - }, - }, + OrgID: MustIDBase16(twoID), + Name: "name2", + Config: "[[inputs.cpu]]\n[[outputs.influxdb_v2]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, // for inmem test as it doesn't unmarshal.. }, }, wants: wants{ telegrafs: []*platform.TelegrafConfig{ { - ID: MustIDBase16(oneID), - OrgID: MustIDBase16(twoID), - Name: "tc1", - Agent: platform.TelegrafAgentConfig{ - Interval: 4000, - }, - Plugins: []platform.TelegrafPlugin{ - { - Comment: "comment1", - Config: &inputs.MemStats{}, - }, - }, - }, - { - ID: MustIDBase16(twoID), - OrgID: MustIDBase16(twoID), - Name: "name2", - Agent: platform.TelegrafAgentConfig{ - Interval: 1001, - }, - Plugins: []platform.TelegrafPlugin{ - { - Comment: "comment2", - Config: &inputs.CPUStats{}, - }, - { - Comment: "comment3", - Config: &outputs.InfluxDBV2{ - URLs: []string{"localhost/9999"}, - Token: "token3", - Organization: "org3", - Bucket: "bucket3", - }, - }, - }, + ID: MustIDBase16(oneID), + OrgID: MustIDBase16(twoID), + Name: "tc1", + Config: "[[inputs.mem_stats]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, + }, + { + ID: MustIDBase16(twoID), + OrgID: MustIDBase16(twoID), + Name: "name2", + Config: "[[inputs.cpu]]\n[[outputs.influxdb_v2]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, }, }, userResourceMapping: []*platform.UserResourceMapping{ @@ -379,31 +287,18 @@ func FindTelegrafConfigByID( fields: TelegrafConfigFields{ TelegrafConfigs: []*platform.TelegrafConfig{ { - ID: MustIDBase16(oneID), - OrgID: MustIDBase16(twoID), - Name: "tc1", - Plugins: []platform.TelegrafPlugin{ - { - Config: &inputs.CPUStats{}, - }, - }, - }, - { - ID: MustIDBase16(twoID), - OrgID: MustIDBase16(twoID), - Name: "tc2", - Plugins: []platform.TelegrafPlugin{ - { - Comment: "comment1", - Config: &inputs.File{ - Files: []string{"f1", "f2"}, - }, - }, - { - Comment: "comment2", - Config: &inputs.MemStats{}, - }, - }, + ID: MustIDBase16(oneID), + OrgID: MustIDBase16(twoID), + Name: "tc1", + Config: "[[inputs.cpu]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, + }, + { + ID: MustIDBase16(twoID), + OrgID: MustIDBase16(twoID), + Name: "tc2", + Config: "[[inputs.file]]\n[[inputs.mem]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, }, }, }, @@ -419,31 +314,16 @@ func FindTelegrafConfigByID( fields: TelegrafConfigFields{ TelegrafConfigs: []*platform.TelegrafConfig{ { - ID: MustIDBase16(oneID), - OrgID: MustIDBase16(twoID), - Name: "tc1", - Plugins: []platform.TelegrafPlugin{ - { - Config: &inputs.CPUStats{}, - }, - }, - }, - { - ID: MustIDBase16(twoID), - OrgID: MustIDBase16(twoID), - Name: "tc2", - Plugins: []platform.TelegrafPlugin{ - { - Comment: "comment1", - Config: &inputs.File{ - Files: []string{"f1", "f2"}, - }, - }, - { - Comment: "comment2", - Config: &inputs.MemStats{}, - }, - }, + ID: MustIDBase16(oneID), + OrgID: MustIDBase16(twoID), + Name: "tc1", + Config: "[[inputs.cpu]]\n", + }, + { + ID: MustIDBase16(twoID), + OrgID: MustIDBase16(twoID), + Name: "tc2", + Config: "[[inputs.file]]\n[[inputs.mem]]\n", }, }, }, @@ -462,31 +342,18 @@ func FindTelegrafConfigByID( fields: TelegrafConfigFields{ TelegrafConfigs: []*platform.TelegrafConfig{ { - ID: MustIDBase16(oneID), - OrgID: MustIDBase16(threeID), - Name: "tc1", - Plugins: []platform.TelegrafPlugin{ - { - Config: &inputs.CPUStats{}, - }, - }, - }, - { - ID: MustIDBase16(twoID), - OrgID: MustIDBase16(threeID), - Name: "tc2", - Plugins: []platform.TelegrafPlugin{ - { - Comment: "comment1", - Config: &inputs.File{ - Files: []string{"f1", "f2"}, - }, - }, - { - Comment: "comment2", - Config: &inputs.MemStats{}, - }, - }, + ID: MustIDBase16(oneID), + OrgID: MustIDBase16(threeID), + Name: "tc1", + Config: "[[inputs.cpu]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, + }, + { + ID: MustIDBase16(twoID), + OrgID: MustIDBase16(threeID), + Name: "tc2", + Config: "[[inputs.file]]\n[[inputs.mem]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, }, }, }, @@ -495,21 +362,11 @@ func FindTelegrafConfigByID( }, wants: wants{ telegrafConfig: &platform.TelegrafConfig{ - ID: MustIDBase16(twoID), - OrgID: MustIDBase16(threeID), - Name: "tc2", - Plugins: []platform.TelegrafPlugin{ - { - Comment: "comment1", - Config: &inputs.File{ - Files: []string{"f1", "f2"}, - }, - }, - { - Comment: "comment2", - Config: &inputs.MemStats{}, - }, - }, + ID: MustIDBase16(twoID), + OrgID: MustIDBase16(threeID), + Name: "tc2", + Config: "[[inputs.file]]\n[[inputs.mem]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, }, }, }, @@ -592,31 +449,18 @@ func FindTelegrafConfigs( }, TelegrafConfigs: []*platform.TelegrafConfig{ { - ID: MustIDBase16(oneID), - OrgID: MustIDBase16(threeID), - Name: "tc1", - Plugins: []platform.TelegrafPlugin{ - { - Config: &inputs.CPUStats{}, - }, - }, - }, - { - ID: MustIDBase16(twoID), - OrgID: MustIDBase16(threeID), - Name: "tc2", - Plugins: []platform.TelegrafPlugin{ - { - Comment: "comment1", - Config: &inputs.File{ - Files: []string{"f1", "f2"}, - }, - }, - { - Comment: "comment2", - Config: &inputs.MemStats{}, - }, - }, + ID: MustIDBase16(oneID), + OrgID: MustIDBase16(threeID), + Name: "tc1", + Config: "[[inputs.cpu]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, + }, + { + ID: MustIDBase16(twoID), + OrgID: MustIDBase16(threeID), + Name: "tc2", + Config: "[[inputs.file]]\n[[inputs.mem]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, }, }, }, @@ -631,31 +475,18 @@ func FindTelegrafConfigs( wants: wants{ telegrafConfigs: []*platform.TelegrafConfig{ { - ID: MustIDBase16(oneID), - OrgID: MustIDBase16(threeID), - Name: "tc1", - Plugins: []platform.TelegrafPlugin{ - { - Config: &inputs.CPUStats{}, - }, - }, - }, - { - ID: MustIDBase16(twoID), - OrgID: MustIDBase16(threeID), - Name: "tc2", - Plugins: []platform.TelegrafPlugin{ - { - Comment: "comment1", - Config: &inputs.File{ - Files: []string{"f1", "f2"}, - }, - }, - { - Comment: "comment2", - Config: &inputs.MemStats{}, - }, - }, + ID: MustIDBase16(oneID), + OrgID: MustIDBase16(threeID), + Name: "tc1", + Config: "[[inputs.cpu]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, + }, + { + ID: MustIDBase16(twoID), + OrgID: MustIDBase16(threeID), + Name: "tc2", + Config: "[[inputs.file]]\n[[inputs.mem]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, }, }, }, @@ -679,31 +510,18 @@ func FindTelegrafConfigs( }, TelegrafConfigs: []*platform.TelegrafConfig{ { - ID: MustIDBase16(oneID), - OrgID: MustIDBase16(fourID), - Name: "tc1", - Plugins: []platform.TelegrafPlugin{ - { - Config: &inputs.CPUStats{}, - }, - }, - }, - { - ID: MustIDBase16(twoID), - OrgID: MustIDBase16(fourID), - Name: "tc2", - Plugins: []platform.TelegrafPlugin{ - { - Comment: "comment1", - Config: &inputs.File{ - Files: []string{"f1", "f2"}, - }, - }, - { - Comment: "comment2", - Config: &inputs.MemStats{}, - }, - }, + ID: MustIDBase16(oneID), + OrgID: MustIDBase16(fourID), + Name: "tc1", + Config: "[[inputs.cpu]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, + }, + { + ID: MustIDBase16(twoID), + OrgID: MustIDBase16(fourID), + Name: "tc2", + Config: "[[inputs.file]]\n[[inputs.mem]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, }, }, }, @@ -719,14 +537,11 @@ func FindTelegrafConfigs( wants: wants{ telegrafConfigs: []*platform.TelegrafConfig{ { - ID: MustIDBase16(oneID), - OrgID: MustIDBase16(fourID), - Name: "tc1", - Plugins: []platform.TelegrafPlugin{ - { - Config: &inputs.CPUStats{}, - }, - }, + ID: MustIDBase16(oneID), + OrgID: MustIDBase16(fourID), + Name: "tc1", + Config: "[[inputs.cpu]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, }, }, }, @@ -756,41 +571,25 @@ func FindTelegrafConfigs( }, TelegrafConfigs: []*platform.TelegrafConfig{ { - ID: MustIDBase16(oneID), - OrgID: MustIDBase16(fourID), - Name: "tc1", - Plugins: []platform.TelegrafPlugin{ - { - Config: &inputs.CPUStats{}, - }, - }, - }, - { - ID: MustIDBase16(twoID), - OrgID: MustIDBase16(fourID), - Name: "tc2", - Plugins: []platform.TelegrafPlugin{ - { - Comment: "comment1", - Config: &inputs.File{ - Files: []string{"f1", "f2"}, - }, - }, - { - Comment: "comment2", - Config: &inputs.MemStats{}, - }, - }, - }, - { - ID: MustIDBase16(fourID), - OrgID: MustIDBase16(oneID), - Name: "tc3", - Plugins: []platform.TelegrafPlugin{ - { - Config: &inputs.CPUStats{}, - }, - }, + ID: MustIDBase16(oneID), + OrgID: MustIDBase16(fourID), + Name: "tc1", + Config: "[[inputs.cpu]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, + }, + { + ID: MustIDBase16(twoID), + OrgID: MustIDBase16(fourID), + Name: "tc2", + Config: "[[inputs.file]]\n[[inputs.mem]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, + }, + { + ID: MustIDBase16(fourID), + OrgID: MustIDBase16(oneID), + Name: "tc3", + Config: "[[inputs.cpu]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, }, }, }, @@ -802,14 +601,11 @@ func FindTelegrafConfigs( wants: wants{ telegrafConfigs: []*platform.TelegrafConfig{ { - ID: MustIDBase16(fourID), - OrgID: MustIDBase16(oneID), - Name: "tc3", - Plugins: []platform.TelegrafPlugin{ - { - Config: &inputs.CPUStats{}, - }, - }, + ID: MustIDBase16(fourID), + OrgID: MustIDBase16(oneID), + Name: "tc3", + Config: "[[inputs.cpu]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, }, }, }, @@ -839,41 +635,25 @@ func FindTelegrafConfigs( }, TelegrafConfigs: []*platform.TelegrafConfig{ { - ID: MustIDBase16(oneID), - OrgID: MustIDBase16(fourID), - Name: "tc1", - Plugins: []platform.TelegrafPlugin{ - { - Config: &inputs.CPUStats{}, - }, - }, - }, - { - ID: MustIDBase16(twoID), - OrgID: MustIDBase16(fourID), - Name: "tc2", - Plugins: []platform.TelegrafPlugin{ - { - Comment: "comment1", - Config: &inputs.File{ - Files: []string{"f1", "f2"}, - }, - }, - { - Comment: "comment2", - Config: &inputs.MemStats{}, - }, - }, - }, - { - ID: MustIDBase16(fourID), - OrgID: MustIDBase16(oneID), - Name: "tc3", - Plugins: []platform.TelegrafPlugin{ - { - Config: &inputs.CPUStats{}, - }, - }, + ID: MustIDBase16(oneID), + OrgID: MustIDBase16(fourID), + Name: "tc1", + Config: "[[inputs.cpu]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, + }, + { + ID: MustIDBase16(twoID), + OrgID: MustIDBase16(fourID), + Name: "tc2", + Config: "[[inputs.file]]\n[[inputs.mem]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, + }, + { + ID: MustIDBase16(fourID), + OrgID: MustIDBase16(oneID), + Name: "tc3", + Config: "[[inputs.cpu]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, }, }, }, @@ -890,14 +670,11 @@ func FindTelegrafConfigs( wants: wants{ telegrafConfigs: []*platform.TelegrafConfig{ { - ID: MustIDBase16(fourID), - OrgID: MustIDBase16(oneID), - Name: "tc3", - Plugins: []platform.TelegrafPlugin{ - { - Config: &inputs.CPUStats{}, - }, - }, + ID: MustIDBase16(fourID), + OrgID: MustIDBase16(oneID), + Name: "tc3", + Config: "[[inputs.cpu]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, }, }, }, @@ -921,31 +698,16 @@ func FindTelegrafConfigs( }, TelegrafConfigs: []*platform.TelegrafConfig{ { - ID: MustIDBase16(oneID), - OrgID: MustIDBase16(threeID), - Name: "tc1", - Plugins: []platform.TelegrafPlugin{ - { - Config: &inputs.CPUStats{}, - }, - }, - }, - { - ID: MustIDBase16(twoID), - OrgID: MustIDBase16(threeID), - Name: "tc2", - Plugins: []platform.TelegrafPlugin{ - { - Comment: "comment1", - Config: &inputs.File{ - Files: []string{"f1", "f2"}, - }, - }, - { - Comment: "comment2", - Config: &inputs.MemStats{}, - }, - }, + ID: MustIDBase16(oneID), + OrgID: MustIDBase16(threeID), + Name: "tc1", + Config: "[[inputs.cpu]]\n", + }, + { + ID: MustIDBase16(twoID), + OrgID: MustIDBase16(threeID), + Name: "tc2", + Config: "[[inputs.file]]\n[[inputs.mem]]\n", }, }, }, @@ -977,31 +739,16 @@ func FindTelegrafConfigs( }, TelegrafConfigs: []*platform.TelegrafConfig{ { - ID: MustIDBase16(oneID), - OrgID: MustIDBase16(threeID), - Name: "tc1", - Plugins: []platform.TelegrafPlugin{ - { - Config: &inputs.CPUStats{}, - }, - }, - }, - { - ID: MustIDBase16(twoID), - OrgID: MustIDBase16(threeID), - Name: "tc2", - Plugins: []platform.TelegrafPlugin{ - { - Comment: "comment1", - Config: &inputs.File{ - Files: []string{"f1", "f2"}, - }, - }, - { - Comment: "comment2", - Config: &inputs.MemStats{}, - }, - }, + ID: MustIDBase16(oneID), + OrgID: MustIDBase16(threeID), + Name: "tc1", + Config: "[[inputs.cpu]]\n", + }, + { + ID: MustIDBase16(twoID), + OrgID: MustIDBase16(threeID), + Name: "tc2", + Config: "[[inputs.file]]\n[[inputs.mem]]\n", }, }, }, @@ -1074,31 +821,16 @@ func UpdateTelegrafConfig( fields: TelegrafConfigFields{ TelegrafConfigs: []*platform.TelegrafConfig{ { - ID: MustIDBase16(oneID), - OrgID: MustIDBase16(fourID), - Name: "tc1", - Plugins: []platform.TelegrafPlugin{ - { - Config: &inputs.CPUStats{}, - }, - }, - }, - { - ID: MustIDBase16(twoID), - OrgID: MustIDBase16(fourID), - Name: "tc2", - Plugins: []platform.TelegrafPlugin{ - { - Comment: "comment1", - Config: &inputs.File{ - Files: []string{"f1", "f2"}, - }, - }, - { - Comment: "comment2", - Config: &inputs.MemStats{}, - }, - }, + ID: MustIDBase16(oneID), + OrgID: MustIDBase16(fourID), + Name: "tc1", + Config: "[[inputs.cpu]]\n", + }, + { + ID: MustIDBase16(twoID), + OrgID: MustIDBase16(fourID), + Name: "tc2", + Config: "[[inputs.file]]\n[[inputs.mem]]\n", }, }, }, @@ -1106,19 +838,8 @@ func UpdateTelegrafConfig( userID: MustIDBase16(threeID), id: MustIDBase16(fourID), telegrafConfig: &platform.TelegrafConfig{ - Name: "tc2", - Plugins: []platform.TelegrafPlugin{ - { - Comment: "comment1", - Config: &inputs.File{ - Files: []string{"f1", "f2"}, - }, - }, - { - Comment: "comment2", - Config: &inputs.MemStats{}, - }, - }, + Name: "tc2", + Config: "[[inputs.file]]\n[[inputs.mem]]\n", }, }, wants: wants{ @@ -1129,35 +850,21 @@ func UpdateTelegrafConfig( }, }, { - name: "regular update", fields: TelegrafConfigFields{ TelegrafConfigs: []*platform.TelegrafConfig{ { - ID: MustIDBase16(oneID), - OrgID: MustIDBase16(fourID), - Name: "tc1", - Plugins: []platform.TelegrafPlugin{ - { - Config: &inputs.CPUStats{}, - }, - }, - }, - { - ID: MustIDBase16(twoID), - OrgID: MustIDBase16(fourID), - Name: "tc2", - Plugins: []platform.TelegrafPlugin{ - { - Comment: "comment1", - Config: &inputs.File{ - Files: []string{"f1", "f2"}, - }, - }, - { - Comment: "comment2", - Config: &inputs.MemStats{}, - }, - }, + ID: MustIDBase16(oneID), + OrgID: MustIDBase16(fourID), + Name: "tc1", + Config: "[[inputs.cpu]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, + }, + { + ID: MustIDBase16(twoID), + OrgID: MustIDBase16(fourID), + Name: "tc2", + Config: "[[inputs.file]]\n[[inputs.mem]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, }, }, }, @@ -1165,35 +872,17 @@ func UpdateTelegrafConfig( userID: MustIDBase16(fourID), id: MustIDBase16(twoID), telegrafConfig: &platform.TelegrafConfig{ - OrgID: MustIDBase16(oneID), // notice this get ignored - ie., resulting TelegrafConfig will have OrgID equal to fourID - Name: "tc2", - Plugins: []platform.TelegrafPlugin{ - { - Comment: "comment3", - Config: &inputs.CPUStats{}, - }, - { - Comment: "comment2", - Config: &inputs.MemStats{}, - }, - }, + OrgID: MustIDBase16(oneID), // notice this get ignored - ie., resulting TelegrafConfig will have OrgID equal to fourID + Name: "tc2", + Config: "[[inputs.file]]\n[[inputs.mem]]\n", }, }, wants: wants{ telegrafConfig: &platform.TelegrafConfig{ - ID: MustIDBase16(twoID), - OrgID: MustIDBase16(fourID), - Name: "tc2", - Plugins: []platform.TelegrafPlugin{ - { - Comment: "comment3", - Config: &inputs.CPUStats{}, - }, - { - Comment: "comment2", - Config: &inputs.MemStats{}, - }, - }, + ID: MustIDBase16(twoID), + OrgID: MustIDBase16(fourID), + Name: "tc2", + Config: "[[inputs.file]]\n[[inputs.mem]]\n", }, }, }, @@ -1202,38 +891,16 @@ func UpdateTelegrafConfig( fields: TelegrafConfigFields{ TelegrafConfigs: []*platform.TelegrafConfig{ { - ID: MustIDBase16(oneID), - OrgID: MustIDBase16(oneID), - Name: "tc1", - Plugins: []platform.TelegrafPlugin{ - { - Config: &inputs.CPUStats{}, - }, - }, - }, - { - ID: MustIDBase16(twoID), - OrgID: MustIDBase16(oneID), - Name: "tc2", - Plugins: []platform.TelegrafPlugin{ - { - Comment: "comment1", - Config: &inputs.File{ - Files: []string{"f1", "f2"}, - }, - }, - { - Comment: "comment2", - Config: &inputs.Kubernetes{ - URL: "http://1.2.3.4", - }, - }, - { - Config: &inputs.Kubernetes{ - URL: "123", - }, - }, - }, + ID: MustIDBase16(oneID), + OrgID: MustIDBase16(oneID), + Name: "tc1", + Config: "[[inputs.cpu]]\n", + }, + { + ID: MustIDBase16(twoID), + OrgID: MustIDBase16(oneID), + Name: "tc2", + Config: "[[inputs.file]]\n[[inputs.kubernetes]]\n[[inputs.kubernetes]]\n", }, }, }, @@ -1241,52 +908,16 @@ func UpdateTelegrafConfig( userID: MustIDBase16(fourID), id: MustIDBase16(twoID), telegrafConfig: &platform.TelegrafConfig{ - Name: "tc2", - Plugins: []platform.TelegrafPlugin{ - { - Comment: "comment1", - Config: &inputs.File{ - Files: []string{"f1", "f2", "f3"}, - }, - }, - { - Comment: "comment2", - Config: &inputs.Kubernetes{ - URL: "http://1.2.3.5", - }, - }, - { - Config: &inputs.Kubernetes{ - URL: "1234", - }, - }, - }, + Name: "tc2", + Config: "[[inputs.file]]\n[[inputs.kubernetes]]\n[[inputs.kubernetes]]\n", }, }, wants: wants{ telegrafConfig: &platform.TelegrafConfig{ - ID: MustIDBase16(twoID), - OrgID: MustIDBase16(oneID), - Name: "tc2", - Plugins: []platform.TelegrafPlugin{ - { - Comment: "comment1", - Config: &inputs.File{ - Files: []string{"f1", "f2", "f3"}, - }, - }, - { - Comment: "comment2", - Config: &inputs.Kubernetes{ - URL: "http://1.2.3.5", - }, - }, - { - Config: &inputs.Kubernetes{ - URL: "1234", - }, - }, - }, + ID: MustIDBase16(twoID), + OrgID: MustIDBase16(oneID), + Name: "tc2", + Config: "[[inputs.file]]\n[[inputs.kubernetes]]\n[[inputs.kubernetes]]\n", }, }, }, @@ -1308,6 +939,7 @@ func UpdateTelegrafConfig( } } if diff := cmp.Diff(tc, tt.wants.telegrafConfig, telegrafCmpOptions...); tt.wants.err == nil && diff != "" { + fmt.Println(tc.Metadata, tt.wants.telegrafConfig.Metadata) t.Errorf("telegraf configs are different -got/+want\ndiff %s", diff) } }) @@ -1354,31 +986,18 @@ func DeleteTelegrafConfig( }, TelegrafConfigs: []*platform.TelegrafConfig{ { - ID: MustIDBase16(oneID), - OrgID: MustIDBase16(fourID), - Name: "tc1", - Plugins: []platform.TelegrafPlugin{ - { - Config: &inputs.CPUStats{}, - }, - }, - }, - { - ID: MustIDBase16(twoID), - OrgID: MustIDBase16(fourID), - Name: "tc2", - Plugins: []platform.TelegrafPlugin{ - { - Comment: "comment1", - Config: &inputs.File{ - Files: []string{"f1", "f2"}, - }, - }, - { - Comment: "comment2", - Config: &inputs.MemStats{}, - }, - }, + ID: MustIDBase16(oneID), + OrgID: MustIDBase16(fourID), + Name: "tc1", + Config: "[[inputs.cpu]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, + }, + { + ID: MustIDBase16(twoID), + OrgID: MustIDBase16(fourID), + Name: "tc2", + Config: "[[inputs.file]]\n[[inputs.mem]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, }, }, }, @@ -1404,31 +1023,18 @@ func DeleteTelegrafConfig( }, telegrafConfigs: []*platform.TelegrafConfig{ { - ID: MustIDBase16(oneID), - OrgID: MustIDBase16(fourID), - Name: "tc1", - Plugins: []platform.TelegrafPlugin{ - { - Config: &inputs.CPUStats{}, - }, - }, - }, - { - ID: MustIDBase16(twoID), - OrgID: MustIDBase16(fourID), - Name: "tc2", - Plugins: []platform.TelegrafPlugin{ - { - Comment: "comment1", - Config: &inputs.File{ - Files: []string{"f1", "f2"}, - }, - }, - { - Comment: "comment2", - Config: &inputs.MemStats{}, - }, - }, + ID: MustIDBase16(oneID), + OrgID: MustIDBase16(fourID), + Name: "tc1", + Config: "[[inputs.cpu]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, + }, + { + ID: MustIDBase16(twoID), + OrgID: MustIDBase16(fourID), + Name: "tc2", + Config: "[[inputs.file]]\n[[inputs.mem]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, }, }, }, @@ -1452,31 +1058,18 @@ func DeleteTelegrafConfig( }, TelegrafConfigs: []*platform.TelegrafConfig{ { - ID: MustIDBase16(oneID), - OrgID: MustIDBase16(threeID), - Name: "tc1", - Plugins: []platform.TelegrafPlugin{ - { - Config: &inputs.CPUStats{}, - }, - }, - }, - { - ID: MustIDBase16(twoID), - OrgID: MustIDBase16(threeID), - Name: "tc2", - Plugins: []platform.TelegrafPlugin{ - { - Comment: "comment1", - Config: &inputs.File{ - Files: []string{"f1", "f2"}, - }, - }, - { - Comment: "comment2", - Config: &inputs.MemStats{}, - }, - }, + ID: MustIDBase16(oneID), + OrgID: MustIDBase16(threeID), + Name: "tc1", + Config: "[[inputs.cpu]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, + }, + { + ID: MustIDBase16(twoID), + OrgID: MustIDBase16(threeID), + Name: "tc2", + Config: "[[inputs.file]]\n[[inputs.mem]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, }, }, }, @@ -1502,31 +1095,18 @@ func DeleteTelegrafConfig( }, telegrafConfigs: []*platform.TelegrafConfig{ { - ID: MustIDBase16(oneID), - OrgID: MustIDBase16(threeID), - Name: "tc1", - Plugins: []platform.TelegrafPlugin{ - { - Config: &inputs.CPUStats{}, - }, - }, - }, - { - ID: MustIDBase16(twoID), - OrgID: MustIDBase16(threeID), - Name: "tc2", - Plugins: []platform.TelegrafPlugin{ - { - Comment: "comment1", - Config: &inputs.File{ - Files: []string{"f1", "f2"}, - }, - }, - { - Comment: "comment2", - Config: &inputs.MemStats{}, - }, - }, + ID: MustIDBase16(oneID), + OrgID: MustIDBase16(threeID), + Name: "tc1", + Config: "[[inputs.cpu]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, + }, + { + ID: MustIDBase16(twoID), + OrgID: MustIDBase16(threeID), + Name: "tc2", + Config: "[[inputs.file]]\n[[inputs.mem]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, }, }, }, @@ -1550,31 +1130,18 @@ func DeleteTelegrafConfig( }, TelegrafConfigs: []*platform.TelegrafConfig{ { - ID: MustIDBase16(oneID), - OrgID: MustIDBase16(twoID), - Name: "tc1", - Plugins: []platform.TelegrafPlugin{ - { - Config: &inputs.CPUStats{}, - }, - }, - }, - { - ID: MustIDBase16(twoID), - OrgID: MustIDBase16(twoID), - Name: "tc2", - Plugins: []platform.TelegrafPlugin{ - { - Comment: "comment1", - Config: &inputs.File{ - Files: []string{"f1", "f2"}, - }, - }, - { - Comment: "comment2", - Config: &inputs.MemStats{}, - }, - }, + ID: MustIDBase16(oneID), + OrgID: MustIDBase16(twoID), + Name: "tc1", + Config: "[[inputs.cpu]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, + }, + { + ID: MustIDBase16(twoID), + OrgID: MustIDBase16(twoID), + Name: "tc2", + Config: "[[inputs.file]]\n[[inputs.mem]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, }, }, }, @@ -1593,14 +1160,11 @@ func DeleteTelegrafConfig( }, telegrafConfigs: []*platform.TelegrafConfig{ { - ID: MustIDBase16(oneID), - OrgID: MustIDBase16(twoID), - Name: "tc1", - Plugins: []platform.TelegrafPlugin{ - { - Config: &inputs.CPUStats{}, - }, - }, + ID: MustIDBase16(oneID), + OrgID: MustIDBase16(twoID), + Name: "tc1", + Config: "[[inputs.cpu]]\n", + Metadata: map[string]interface{}{"buckets": []interface{}{}}, }, }, }, diff --git a/testing/user_resource_mapping_service.go b/testing/user_resource_mapping_service.go index 316c8e4dbc9..fb2e4a7ae98 100644 --- a/testing/user_resource_mapping_service.go +++ b/testing/user_resource_mapping_service.go @@ -11,6 +11,19 @@ import ( platform "github.com/influxdata/influxdb" ) +var userResourceMappingCmpOptions = cmp.Options{ + cmp.Comparer(func(x, y []byte) bool { + return bytes.Equal(x, y) + }), + cmp.Transformer("Sort", func(in []*platform.UserResourceMapping) []*platform.UserResourceMapping { + out := append([]*platform.UserResourceMapping(nil), in...) + sort.Slice(out, func(i, j int) bool { + return out[i].ResourceID.String() > out[j].ResourceID.String() + }) + return out + }), +} + var mappingCmpOptions = cmp.Options{ cmp.Comparer(func(x, y []byte) bool { return bytes.Equal(x, y) diff --git a/ui/src/telegrafs/actions/index.ts b/ui/src/telegrafs/actions/index.ts index 6d92fe5b7ac..3333914c5d6 100644 --- a/ui/src/telegrafs/actions/index.ts +++ b/ui/src/telegrafs/actions/index.ts @@ -2,8 +2,7 @@ import {client} from 'src/utils/api' // Types -import {RemoteDataState, GetState} from 'src/types' -import {ITelegraf as Telegraf, ILabel as Label} from '@influxdata/influx' +import {RemoteDataState, GetState, Telegraf, Label} from 'src/types' import {Dispatch, ThunkAction} from 'redux-thunk' // Actions diff --git a/ui/src/telegrafs/components/CollectorCard.tsx b/ui/src/telegrafs/components/CollectorCard.tsx index 62feb9f372c..34f21b5d587 100644 --- a/ui/src/telegrafs/components/CollectorCard.tsx +++ b/ui/src/telegrafs/components/CollectorCard.tsx @@ -23,19 +23,17 @@ import {viewableLabels} from 'src/labels/selectors' import {DEFAULT_COLLECTOR_NAME} from 'src/dashboards/constants' // Types -import {AppState, Organization} from 'src/types' -import {ILabel, ITelegraf as Telegraf} from '@influxdata/influx' +import {AppState, Organization, Label, Telegraf} from 'src/types' interface OwnProps { collector: Telegraf - bucket: string onDelete: (telegraf: Telegraf) => void onUpdate: (telegraf: Telegraf) => void onFilterChange: (searchTerm: string) => void } interface StateProps { - labels: ILabel[] + labels: Label[] org: Organization } @@ -49,7 +47,7 @@ type Props = OwnProps & StateProps & DispatchProps class CollectorRow extends PureComponent { public render() { - const {collector, bucket, org} = this.props + const {collector, org} = this.props return ( { labels={this.labels} metaData={[ - Bucket: {bucket} + {/* todo(glinton): verify what sets this. It seems like it is using the 'config' section of 'influxdb_v2' output?? */} + Bucket: {collector.metadata.buckets.join(', ')} , <> { private get labels(): JSX.Element { const {collector, labels, onFilterChange} = this.props - const collectorLabels = viewableLabels(collector.labels) + // todo(glinton): track down `Label` drift and remove `as Label[]` + const collectorLabels = viewableLabels(collector.labels as Label[]) return ( { ) } - private handleAddLabel = async (label: ILabel) => { + private handleAddLabel = async (label: Label) => { const {collector, onAddLabels} = this.props await onAddLabels(collector.id, [label]) } - private handleRemoveLabel = async (label: ILabel) => { + private handleRemoveLabel = async (label: Label) => { const {collector, onRemoveLabels} = this.props await onRemoveLabels(collector.id, [label]) } - private handleCreateLabel = async (label: ILabel) => { + private handleCreateLabel = async (label: Label) => { const {name, properties} = label await this.props.onCreateLabel(name, properties) } diff --git a/ui/src/telegrafs/components/CollectorList.tsx b/ui/src/telegrafs/components/CollectorList.tsx index f2bafd809b0..11f10053b8b 100644 --- a/ui/src/telegrafs/components/CollectorList.tsx +++ b/ui/src/telegrafs/components/CollectorList.tsx @@ -1,35 +1,43 @@ // Libraries import React, {PureComponent} from 'react' import _ from 'lodash' +import {connect} from 'react-redux' import memoizeOne from 'memoize-one' // Components import {ResourceList} from '@influxdata/clockface' import CollectorRow from 'src/telegrafs/components/CollectorCard' +import FilterList from 'src/shared/components/Filter' // Types -import {ITelegraf as Telegraf} from '@influxdata/influx' import {Sort} from '@influxdata/clockface' import {SortTypes, getSortedResources} from 'src/shared/utils/sort' +import {AppState, Telegraf} from 'src/types' +import {updateTelegraf, deleteTelegraf} from '../actions' -//Utils -import {getDeep} from 'src/utils/wrappers' +type SortKey = keyof Telegraf -type SortKey = keyof Telegraf | 'plugins.0.config.bucket' - -interface Props { - collectors: Telegraf[] +interface OwnProps { emptyState: JSX.Element - onDelete: (telegraf: Telegraf) => void - onUpdate: (telegraf: Telegraf) => void - onFilterChange: (searchTerm: string) => void sortKey: string sortDirection: Sort sortType: SortTypes onClickColumn: (nextSort: Sort, sortKey: SortKey) => void + onFilterChange: (searchTerm: string) => void +} + +interface StateProps { + collectors: Telegraf[] +} + +interface DispatchProps { + onUpdateTelegraf: typeof updateTelegraf + onDeleteTelegraf: typeof deleteTelegraf } -export default class CollectorList extends PureComponent { +type Props = OwnProps & StateProps & DispatchProps + +class CollectorList extends PureComponent { private memGetSortedResources = memoizeOne( getSortedResources ) @@ -38,37 +46,31 @@ export default class CollectorList extends PureComponent { const {emptyState, sortKey, sortDirection, onClickColumn} = this.props return ( - <> - - - - - - {this.collectorsList} - - - + + + + + + {this.collectorsList} + + ) } - private get headerKeys(): SortKey[] { - return ['name', 'plugins.0.config.bucket'] - } - public get collectorsList(): JSX.Element[] { const { collectors, sortKey, sortDirection, sortType, - onDelete, - onUpdate, + onDeleteTelegraf, + onUpdateTelegraf, onFilterChange, } = this.props const sortedCollectors = this.memGetSortedResources( @@ -83,12 +85,78 @@ export default class CollectorList extends PureComponent { (collector, 'plugins.0.config.bucket', '')} - onDelete={onDelete} - onUpdate={onUpdate} + onDelete={(telegraf: Telegraf) => + onDeleteTelegraf(telegraf.id, telegraf.name) + } + onUpdate={onUpdateTelegraf} onFilterChange={onFilterChange} /> )) } } } + +const mstp = (state: AppState): StateProps => ({ + collectors: state.telegrafs.list, +}) + +const mdtp: DispatchProps = { + onUpdateTelegraf: updateTelegraf, + onDeleteTelegraf: deleteTelegraf, +} + +connect( + mstp, + mdtp +)(CollectorList) + +type FilteredOwnProps = OwnProps & { + searchTerm: string +} + +type FilteredProps = Props & FilteredOwnProps + +class FilteredCollectorList extends PureComponent { + render() { + const { + searchTerm, + collectors, + emptyState, + onFilterChange, + sortKey, + sortDirection, + sortType, + onClickColumn, + onUpdateTelegraf, + onDeleteTelegraf, + } = this.props + return ( + + searchTerm={searchTerm} + searchKeys={['metadata.buckets[]', 'name', 'labels[].name']} + list={collectors} + > + {cs => ( + + )} + + ) + } +} + +const FilteredList = connect( + mstp, + mdtp +)(FilteredCollectorList) + +export {FilteredCollectorList, FilteredList} diff --git a/ui/src/telegrafs/components/Collectors.test.tsx b/ui/src/telegrafs/components/Collectors.test.tsx deleted file mode 100644 index 294a8c5cd0c..00000000000 --- a/ui/src/telegrafs/components/Collectors.test.tsx +++ /dev/null @@ -1,34 +0,0 @@ -// Libraries -import React from 'react' -import {shallow} from 'enzyme' - -// Components -import CollectorList from 'src/telegrafs/components/CollectorList' - -// Constants -import {telegraf} from 'mocks/dummyData' - -const setup = (override?) => { - const props = { - collectors: telegraf, - emptyState: <>, - onDelete: jest.fn(), - onUpdate: jest.fn(), - onOpenInstructions: jest.fn(), - onOpenTelegrafConfig: jest.fn(), - ...override, - } - - const wrapper = shallow() - - return {wrapper} -} - -describe('CollectorList', () => { - describe('rendering', () => { - it('renders', () => { - const {wrapper} = setup() - expect(wrapper.exists()).toBe(true) - }) - }) -}) diff --git a/ui/src/telegrafs/components/Collectors.tsx b/ui/src/telegrafs/components/Collectors.tsx index 7c1ce09c8c9..6b69afe940b 100644 --- a/ui/src/telegrafs/components/Collectors.tsx +++ b/ui/src/telegrafs/components/Collectors.tsx @@ -18,9 +18,8 @@ import { } from '@influxdata/clockface' import SearchWidget from 'src/shared/components/search_widget/SearchWidget' import SettingsTabbedPageHeader from 'src/settings/components/SettingsTabbedPageHeader' -import CollectorList from 'src/telegrafs/components/CollectorList' +import {FilteredList} from 'src/telegrafs/components/CollectorList' import TelegrafExplainer from 'src/telegrafs/components/TelegrafExplainer' -import FilterList from 'src/shared/components/Filter' import NoBucketsWarning from 'src/buckets/components/NoBucketsWarning' import GetResources, {ResourceType} from 'src/shared/components/GetResources' @@ -32,8 +31,7 @@ import {updateTelegraf, deleteTelegraf} from 'src/telegrafs/actions' import {ErrorHandling} from 'src/shared/decorators/errors' // Types -import {ITelegraf as Telegraf} from '@influxdata/influx' -import {OverlayState, AppState, Bucket} from 'src/types' +import {Telegraf, OverlayState, AppState, Bucket} from 'src/types' import { setDataLoadersType, setTelegrafConfigID, @@ -44,7 +42,7 @@ import {DataLoaderType} from 'src/types/dataLoaders' import {SortTypes} from 'src/shared/utils/sort' interface StateProps { - collectors: Telegraf[] + hasTelegrafs: boolean orgName: string buckets: Bucket[] } @@ -89,14 +87,9 @@ class Collectors extends PureComponent { } } - public static defaultProps = { - collectors: [], - } - public render() { - const {collectors} = this.props + const {hasTelegrafs} = this.props const {searchTerm, sortKey, sortDirection, sortType} = this.state - const hasTelegrafs = collectors && collectors.length > 0 return ( <> { widthMD={hasTelegrafs ? Columns.Ten : Columns.Twelve} > - + - {cs => ( - - )} - + emptyState={this.emptyState} + onFilterChange={this.handleFilterUpdate} + sortKey={sortKey} + sortDirection={sortDirection} + sortType={sortType} + onClickColumn={this.handleClickColumn} + /> {hasTelegrafs && ( @@ -268,14 +247,6 @@ class Collectors extends PureComponent { ) } - private handleDeleteTelegraf = (telegraf: Telegraf) => { - this.props.onDeleteTelegraf(telegraf.id, telegraf.name) - } - - private handleUpdateTelegraf = (telegraf: Telegraf) => { - this.props.onUpdateTelegraf(telegraf) - } - private handleFilterChange = (searchTerm: string): void => { this.handleFilterUpdate(searchTerm) } @@ -286,7 +257,7 @@ class Collectors extends PureComponent { } const mstp = ({telegrafs, orgs: {org}, buckets}: AppState): StateProps => { return { - collectors: telegrafs.list, + hasTelegrafs: telegrafs.list && telegrafs.list.length > 0, orgName: org.name, buckets: buckets.list, } diff --git a/ui/src/telegrafs/components/TelegrafConfigOverlay.tsx b/ui/src/telegrafs/components/TelegrafConfigOverlay.tsx index 074bf4ad7d8..09610b8a5dc 100644 --- a/ui/src/telegrafs/components/TelegrafConfigOverlay.tsx +++ b/ui/src/telegrafs/components/TelegrafConfigOverlay.tsx @@ -20,8 +20,7 @@ import { import {downloadTextFile} from 'src/shared/utils/download' // Types -import {AppState} from 'src/types' -import {ITelegraf as Telegraf} from '@influxdata/influx' +import {AppState, Telegraf} from 'src/types' interface OwnProps { onClose: () => void diff --git a/ui/src/telegrafs/reducers/index.ts b/ui/src/telegrafs/reducers/index.ts index afa67b66339..a5fb0bca827 100644 --- a/ui/src/telegrafs/reducers/index.ts +++ b/ui/src/telegrafs/reducers/index.ts @@ -2,9 +2,8 @@ import {produce} from 'immer' // Types -import {RemoteDataState} from 'src/types' +import {RemoteDataState, Telegraf} from 'src/types' import {Action} from 'src/telegrafs/actions' -import {ITelegraf as Telegraf} from '@influxdata/influx' const initialState = (): TelegrafsState => ({ status: RemoteDataState.NotStarted, @@ -30,7 +29,18 @@ export const telegrafsReducer = ( draftState.status = status if (list) { - draftState.list = list + draftState.list = list.map(telegraf => { + if (!telegraf.metadata) { + telegraf.metadata = { + buckets: [], + } + } + if (!telegraf.metadata.buckets) { + telegraf.metadata.buckets = [] + } + + return telegraf + }) } return diff --git a/ui/src/types/index.ts b/ui/src/types/index.ts index 23b799f80ee..2fcb2e019ed 100644 --- a/ui/src/types/index.ts +++ b/ui/src/types/index.ts @@ -26,6 +26,7 @@ export * from './shared' export * from './sources' export * from './stores' export * from './tasks' +export * from './telegraf' export * from './templates' export * from './timeMachine' export * from './members' diff --git a/ui/src/types/telegraf.ts b/ui/src/types/telegraf.ts new file mode 100644 index 00000000000..0c2dee963c1 --- /dev/null +++ b/ui/src/types/telegraf.ts @@ -0,0 +1,6 @@ +import {Telegraf as GenTelegraf} from 'src/client' +import {Label} from 'src/types' + +export interface Telegraf extends GenTelegraf { + label?: Label[] +}