2015-11-25 05:22:11 +08:00
package config
import (
2021-02-13 00:38:40 +08:00
"net/http"
"net/http/httptest"
2016-04-02 03:53:34 +08:00
"os"
2020-11-23 23:40:32 +08:00
"strings"
2015-11-25 05:22:11 +08:00
"testing"
"time"
2019-04-26 11:19:58 +08:00
"github.com/influxdata/telegraf/internal"
2020-05-05 02:09:10 +08:00
"github.com/influxdata/telegraf/models"
2016-01-21 02:57:35 +08:00
"github.com/influxdata/telegraf/plugins/inputs"
"github.com/influxdata/telegraf/plugins/inputs/exec"
2019-04-26 11:19:58 +08:00
"github.com/influxdata/telegraf/plugins/inputs/http_listener_v2"
2016-01-21 02:57:35 +08:00
"github.com/influxdata/telegraf/plugins/inputs/memcached"
"github.com/influxdata/telegraf/plugins/inputs/procstat"
2020-10-20 22:16:22 +08:00
"github.com/influxdata/telegraf/plugins/outputs/azure_monitor"
2019-04-26 11:19:58 +08:00
httpOut "github.com/influxdata/telegraf/plugins/outputs/http"
2016-02-06 08:36:35 +08:00
"github.com/influxdata/telegraf/plugins/parsers"
2015-11-25 05:22:11 +08:00
"github.com/stretchr/testify/assert"
2019-04-26 11:19:58 +08:00
"github.com/stretchr/testify/require"
2015-11-25 05:22:11 +08:00
)
2016-04-02 03:53:34 +08:00
func TestConfig_LoadSingleInputWithEnvVars ( t * testing . T ) {
c := NewConfig ( )
err := os . Setenv ( "MY_TEST_SERVER" , "192.168.1.1" )
assert . NoError ( t , err )
err = os . Setenv ( "TEST_INTERVAL" , "10s" )
assert . NoError ( t , err )
c . LoadConfig ( "./testdata/single_plugin_env_vars.toml" )
memcached := inputs . Inputs [ "memcached" ] ( ) . ( * memcached . Memcached )
memcached . Servers = [ ] string { "192.168.1.1" }
2016-07-28 19:31:11 +08:00
filter := models . Filter {
2016-04-13 07:06:27 +08:00
NameDrop : [ ] string { "metricname2" } ,
2019-03-30 07:02:10 +08:00
NamePass : [ ] string { "metricname1" , "ip_192.168.1.1_name" } ,
2016-04-13 07:06:27 +08:00
FieldDrop : [ ] string { "other" , "stuff" } ,
FieldPass : [ ] string { "some" , "strings" } ,
2016-07-28 19:31:11 +08:00
TagDrop : [ ] models . TagFilter {
2018-10-20 04:32:54 +08:00
{
2016-04-13 07:06:27 +08:00
Name : "badtag" ,
Filter : [ ] string { "othertag" } ,
2016-04-02 03:53:34 +08:00
} ,
2016-04-13 07:06:27 +08:00
} ,
2016-07-28 19:31:11 +08:00
TagPass : [ ] models . TagFilter {
2018-10-20 04:32:54 +08:00
{
2016-04-13 07:06:27 +08:00
Name : "goodtag" ,
Filter : [ ] string { "mytag" } ,
2016-04-02 03:53:34 +08:00
} ,
} ,
2016-04-13 07:06:27 +08:00
}
2016-09-05 23:16:37 +08:00
assert . NoError ( t , filter . Compile ( ) )
2016-07-28 19:31:11 +08:00
mConfig := & models . InputConfig {
2016-04-13 07:06:27 +08:00
Name : "memcached" ,
Filter : filter ,
2016-04-02 03:53:34 +08:00
Interval : 10 * time . Second ,
}
mConfig . Tags = make ( map [ string ] string )
assert . Equal ( t , memcached , c . Inputs [ 0 ] . Input ,
"Testdata did not produce a correct memcached struct." )
assert . Equal ( t , mConfig , c . Inputs [ 0 ] . Config ,
"Testdata did not produce correct memcached metadata." )
}
2016-01-08 04:39:43 +08:00
func TestConfig_LoadSingleInput ( t * testing . T ) {
2015-11-25 05:22:11 +08:00
c := NewConfig ( )
c . LoadConfig ( "./testdata/single_plugin.toml" )
2016-01-08 04:39:43 +08:00
memcached := inputs . Inputs [ "memcached" ] ( ) . ( * memcached . Memcached )
2015-11-25 05:22:11 +08:00
memcached . Servers = [ ] string { "localhost" }
2016-07-28 19:31:11 +08:00
filter := models . Filter {
2016-04-13 07:06:27 +08:00
NameDrop : [ ] string { "metricname2" } ,
NamePass : [ ] string { "metricname1" } ,
FieldDrop : [ ] string { "other" , "stuff" } ,
FieldPass : [ ] string { "some" , "strings" } ,
2016-07-28 19:31:11 +08:00
TagDrop : [ ] models . TagFilter {
2018-10-20 04:32:54 +08:00
{
2016-04-13 07:06:27 +08:00
Name : "badtag" ,
Filter : [ ] string { "othertag" } ,
2015-11-25 05:22:11 +08:00
} ,
2016-04-13 07:06:27 +08:00
} ,
2016-07-28 19:31:11 +08:00
TagPass : [ ] models . TagFilter {
2018-10-20 04:32:54 +08:00
{
2016-04-13 07:06:27 +08:00
Name : "goodtag" ,
Filter : [ ] string { "mytag" } ,
2015-11-25 05:22:11 +08:00
} ,
} ,
2016-04-13 07:06:27 +08:00
}
2016-09-05 23:16:37 +08:00
assert . NoError ( t , filter . Compile ( ) )
2016-07-28 19:31:11 +08:00
mConfig := & models . InputConfig {
2016-04-13 07:06:27 +08:00
Name : "memcached" ,
Filter : filter ,
2015-11-25 05:22:11 +08:00
Interval : 5 * time . Second ,
}
2016-01-08 01:23:38 +08:00
mConfig . Tags = make ( map [ string ] string )
2015-11-25 05:22:11 +08:00
2016-01-08 04:39:43 +08:00
assert . Equal ( t , memcached , c . Inputs [ 0 ] . Input ,
2015-11-25 05:22:11 +08:00
"Testdata did not produce a correct memcached struct." )
2016-01-08 04:39:43 +08:00
assert . Equal ( t , mConfig , c . Inputs [ 0 ] . Config ,
2015-11-25 05:22:11 +08:00
"Testdata did not produce correct memcached metadata." )
}
func TestConfig_LoadDirectory ( t * testing . T ) {
c := NewConfig ( )
err := c . LoadConfig ( "./testdata/single_plugin.toml" )
if err != nil {
t . Error ( err )
}
err = c . LoadDirectory ( "./testdata/subconfig" )
if err != nil {
t . Error ( err )
}
2016-01-08 04:39:43 +08:00
memcached := inputs . Inputs [ "memcached" ] ( ) . ( * memcached . Memcached )
2015-11-25 05:22:11 +08:00
memcached . Servers = [ ] string { "localhost" }
2016-07-28 19:31:11 +08:00
filter := models . Filter {
2016-04-13 07:06:27 +08:00
NameDrop : [ ] string { "metricname2" } ,
NamePass : [ ] string { "metricname1" } ,
FieldDrop : [ ] string { "other" , "stuff" } ,
FieldPass : [ ] string { "some" , "strings" } ,
2016-07-28 19:31:11 +08:00
TagDrop : [ ] models . TagFilter {
2018-10-20 04:32:54 +08:00
{
2016-04-13 07:06:27 +08:00
Name : "badtag" ,
Filter : [ ] string { "othertag" } ,
2015-11-25 05:22:11 +08:00
} ,
2016-04-13 07:06:27 +08:00
} ,
2016-07-28 19:31:11 +08:00
TagPass : [ ] models . TagFilter {
2018-10-20 04:32:54 +08:00
{
2016-04-13 07:06:27 +08:00
Name : "goodtag" ,
Filter : [ ] string { "mytag" } ,
2015-11-25 05:22:11 +08:00
} ,
} ,
2016-04-13 07:06:27 +08:00
}
2016-09-05 23:16:37 +08:00
assert . NoError ( t , filter . Compile ( ) )
2016-07-28 19:31:11 +08:00
mConfig := & models . InputConfig {
2016-04-13 07:06:27 +08:00
Name : "memcached" ,
Filter : filter ,
2015-11-25 05:22:11 +08:00
Interval : 5 * time . Second ,
}
2016-01-08 01:23:38 +08:00
mConfig . Tags = make ( map [ string ] string )
2016-01-08 04:39:43 +08:00
assert . Equal ( t , memcached , c . Inputs [ 0 ] . Input ,
2015-11-25 05:22:11 +08:00
"Testdata did not produce a correct memcached struct." )
2016-01-08 04:39:43 +08:00
assert . Equal ( t , mConfig , c . Inputs [ 0 ] . Config ,
2015-11-25 05:22:11 +08:00
"Testdata did not produce correct memcached metadata." )
2016-01-08 04:39:43 +08:00
ex := inputs . Inputs [ "exec" ] ( ) . ( * exec . Exec )
2018-08-23 10:26:48 +08:00
p , err := parsers . NewParser ( & parsers . Config {
MetricName : "exec" ,
DataFormat : "json" ,
2020-01-22 02:10:02 +08:00
JSONStrict : true ,
2018-08-23 10:26:48 +08:00
} )
2016-02-06 08:36:35 +08:00
assert . NoError ( t , err )
ex . SetParser ( p )
2016-01-08 01:23:38 +08:00
ex . Command = "/usr/bin/myothercollector --foo=bar"
2016-07-28 19:31:11 +08:00
eConfig := & models . InputConfig {
2016-01-08 04:39:43 +08:00
Name : "exec" ,
MeasurementSuffix : "_myothercollector" ,
}
2016-01-08 01:23:38 +08:00
eConfig . Tags = make ( map [ string ] string )
2019-10-08 03:18:36 +08:00
exec := c . Inputs [ 1 ] . Input . ( * exec . Exec )
require . NotNil ( t , exec . Log )
exec . Log = nil
2016-01-08 04:39:43 +08:00
assert . Equal ( t , ex , c . Inputs [ 1 ] . Input ,
2015-11-25 05:22:11 +08:00
"Merged Testdata did not produce a correct exec struct." )
2016-01-08 04:39:43 +08:00
assert . Equal ( t , eConfig , c . Inputs [ 1 ] . Config ,
2015-11-25 05:22:11 +08:00
"Merged Testdata did not produce correct exec metadata." )
memcached . Servers = [ ] string { "192.168.1.1" }
2016-01-08 04:39:43 +08:00
assert . Equal ( t , memcached , c . Inputs [ 2 ] . Input ,
2015-11-25 05:22:11 +08:00
"Testdata did not produce a correct memcached struct." )
2016-01-08 04:39:43 +08:00
assert . Equal ( t , mConfig , c . Inputs [ 2 ] . Config ,
2015-11-25 05:22:11 +08:00
"Testdata did not produce correct memcached metadata." )
2016-01-08 04:39:43 +08:00
pstat := inputs . Inputs [ "procstat" ] ( ) . ( * procstat . Procstat )
2016-01-08 01:23:38 +08:00
pstat . PidFile = "/var/run/grafana-server.pid"
2015-11-25 05:22:11 +08:00
2016-07-28 19:31:11 +08:00
pConfig := & models . InputConfig { Name : "procstat" }
2016-01-08 01:23:38 +08:00
pConfig . Tags = make ( map [ string ] string )
2015-11-25 05:22:11 +08:00
2016-01-08 04:39:43 +08:00
assert . Equal ( t , pstat , c . Inputs [ 3 ] . Input ,
2015-11-25 05:22:11 +08:00
"Merged Testdata did not produce a correct procstat struct." )
2016-01-08 04:39:43 +08:00
assert . Equal ( t , pConfig , c . Inputs [ 3 ] . Config ,
2015-11-25 05:22:11 +08:00
"Merged Testdata did not produce correct procstat metadata." )
}
2019-04-26 11:19:58 +08:00
func TestConfig_LoadSpecialTypes ( t * testing . T ) {
c := NewConfig ( )
err := c . LoadConfig ( "./testdata/special_types.toml" )
assert . NoError ( t , err )
require . Equal ( t , 1 , len ( c . Inputs ) )
inputHTTPListener , ok := c . Inputs [ 0 ] . Input . ( * http_listener_v2 . HTTPListenerV2 )
assert . Equal ( t , true , ok )
// Tests telegraf duration parsing.
assert . Equal ( t , internal . Duration { Duration : time . Second } , inputHTTPListener . WriteTimeout )
// Tests telegraf size parsing.
assert . Equal ( t , internal . Size { Size : 1024 * 1024 } , inputHTTPListener . MaxBodySize )
// Tests toml multiline basic strings.
2020-11-23 23:40:32 +08:00
assert . Equal ( t , "/path/to/my/cert" , strings . TrimRight ( inputHTTPListener . TLSCert , "\r\n" ) )
2019-04-26 11:19:58 +08:00
}
func TestConfig_FieldNotDefined ( t * testing . T ) {
c := NewConfig ( )
err := c . LoadConfig ( "./testdata/invalid_field.toml" )
require . Error ( t , err , "invalid field name" )
2020-11-04 05:40:57 +08:00
assert . Equal ( t , "Error loading config file ./testdata/invalid_field.toml: plugin inputs.http_listener_v2: line 1: configuration specified the fields [\"not_a_field\"], but they weren't used" , err . Error ( ) )
2019-04-26 11:19:58 +08:00
}
func TestConfig_WrongFieldType ( t * testing . T ) {
c := NewConfig ( )
err := c . LoadConfig ( "./testdata/wrong_field_type.toml" )
require . Error ( t , err , "invalid field type" )
2020-11-04 05:40:57 +08:00
assert . Equal ( t , "Error loading config file ./testdata/wrong_field_type.toml: error parsing http_listener_v2, line 2: (http_listener_v2.HTTPListenerV2.Port) cannot unmarshal TOML string into int" , err . Error ( ) )
2019-04-26 11:19:58 +08:00
c = NewConfig ( )
err = c . LoadConfig ( "./testdata/wrong_field_type2.toml" )
require . Error ( t , err , "invalid field type2" )
2020-11-04 05:40:57 +08:00
assert . Equal ( t , "Error loading config file ./testdata/wrong_field_type2.toml: error parsing http_listener_v2, line 2: (http_listener_v2.HTTPListenerV2.Methods) cannot unmarshal TOML string into []string" , err . Error ( ) )
2019-04-26 11:19:58 +08:00
}
func TestConfig_InlineTables ( t * testing . T ) {
// #4098
c := NewConfig ( )
err := c . LoadConfig ( "./testdata/inline_table.toml" )
assert . NoError ( t , err )
require . Equal ( t , 2 , len ( c . Outputs ) )
outputHTTP , ok := c . Outputs [ 1 ] . Output . ( * httpOut . HTTP )
assert . Equal ( t , true , ok )
assert . Equal ( t , map [ string ] string { "Authorization" : "Token $TOKEN" , "Content-Type" : "application/json" } , outputHTTP . Headers )
assert . Equal ( t , [ ] string { "org_id" } , c . Outputs [ 0 ] . Config . Filter . TagInclude )
}
func TestConfig_SliceComment ( t * testing . T ) {
t . Skipf ( "Skipping until #3642 is resolved" )
c := NewConfig ( )
err := c . LoadConfig ( "./testdata/slice_comment.toml" )
assert . NoError ( t , err )
require . Equal ( t , 1 , len ( c . Outputs ) )
outputHTTP , ok := c . Outputs [ 0 ] . Output . ( * httpOut . HTTP )
assert . Equal ( t , [ ] string { "test" } , outputHTTP . Scopes )
assert . Equal ( t , true , ok )
}
func TestConfig_BadOrdering ( t * testing . T ) {
// #3444: when not using inline tables, care has to be taken so subsequent configuration
// doesn't become part of the table. This is not a bug, but TOML syntax.
c := NewConfig ( )
err := c . LoadConfig ( "./testdata/non_slice_slice.toml" )
require . Error ( t , err , "bad ordering" )
2020-11-04 05:40:57 +08:00
assert . Equal ( t , "Error loading config file ./testdata/non_slice_slice.toml: error parsing http array, line 4: cannot unmarshal TOML array into string (need slice)" , err . Error ( ) )
2019-04-26 11:19:58 +08:00
}
2020-10-20 22:16:22 +08:00
func TestConfig_AzureMonitorNamespacePrefix ( t * testing . T ) {
// #8256 Cannot use empty string as the namespace prefix
c := NewConfig ( )
defaultPrefixConfig := ` [[outputs.azure_monitor]] `
err := c . LoadConfigData ( [ ] byte ( defaultPrefixConfig ) )
assert . NoError ( t , err )
azureMonitor , ok := c . Outputs [ 0 ] . Output . ( * azure_monitor . AzureMonitor )
assert . Equal ( t , "Telegraf/" , azureMonitor . NamespacePrefix )
assert . Equal ( t , true , ok )
c = NewConfig ( )
customPrefixConfig := ` [ [ outputs . azure_monitor ] ]
namespace_prefix = "" `
err = c . LoadConfigData ( [ ] byte ( customPrefixConfig ) )
assert . NoError ( t , err )
azureMonitor , ok = c . Outputs [ 0 ] . Output . ( * azure_monitor . AzureMonitor )
assert . Equal ( t , "" , azureMonitor . NamespacePrefix )
assert . Equal ( t , true , ok )
}
2021-02-13 00:38:40 +08:00
func TestConfig_URLRetries3Fails ( t * testing . T ) {
httpLoadConfigRetryInterval = 0 * time . Second
responseCounter := 0
ts := httptest . NewServer ( http . HandlerFunc ( func ( w http . ResponseWriter , r * http . Request ) {
w . WriteHeader ( http . StatusNotFound )
responseCounter ++
} ) )
defer ts . Close ( )
c := NewConfig ( )
err := c . LoadConfig ( ts . URL )
require . Error ( t , err )
require . Equal ( t , 4 , responseCounter )
}
func TestConfig_URLRetries3FailsThenPasses ( t * testing . T ) {
httpLoadConfigRetryInterval = 0 * time . Second
responseCounter := 0
ts := httptest . NewServer ( http . HandlerFunc ( func ( w http . ResponseWriter , r * http . Request ) {
if responseCounter <= 2 {
w . WriteHeader ( http . StatusNotFound )
} else {
w . WriteHeader ( http . StatusOK )
}
responseCounter ++
} ) )
defer ts . Close ( )
c := NewConfig ( )
err := c . LoadConfig ( ts . URL )
require . NoError ( t , err )
require . Equal ( t , 4 , responseCounter )
}