feat(secretstores): convert many output plugins (#12497)
This commit is contained in:
parent
607bfdbc97
commit
f5c2c4abf0
|
|
@ -91,6 +91,26 @@ func (s *Secret) Empty() bool {
|
||||||
return !s.notempty
|
return !s.notempty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EqualTo performs a constant-time comparison of the secret to the given reference
|
||||||
|
func (s *Secret) EqualTo(ref []byte) (bool, error) {
|
||||||
|
if s.enclave == nil {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(s.unlinked) > 0 {
|
||||||
|
return false, fmt.Errorf("unlinked parts in secret: %v", strings.Join(s.unlinked, ";"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a locked-buffer of the secret to perform the comparison
|
||||||
|
lockbuf, err := s.enclave.Open()
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("opening enclave failed: %v", err)
|
||||||
|
}
|
||||||
|
defer lockbuf.Destroy()
|
||||||
|
|
||||||
|
return lockbuf.EqualTo(ref), nil
|
||||||
|
}
|
||||||
|
|
||||||
// Get return the string representation of the secret
|
// Get return the string representation of the secret
|
||||||
func (s *Secret) Get() ([]byte, error) {
|
func (s *Secret) Get() ([]byte, error) {
|
||||||
if s.enclave == nil {
|
if s.enclave == nil {
|
||||||
|
|
|
||||||
|
|
@ -433,6 +433,20 @@ func TestSecretStoreInvalidKeys(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSecretEqualTo(t *testing.T) {
|
||||||
|
mysecret := "a wonderful test"
|
||||||
|
s := NewSecret([]byte(mysecret))
|
||||||
|
defer s.Destroy()
|
||||||
|
|
||||||
|
equal, err := s.EqualTo([]byte(mysecret))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.True(t, equal)
|
||||||
|
|
||||||
|
equal, err = s.EqualTo([]byte("some random text"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.False(t, equal)
|
||||||
|
}
|
||||||
|
|
||||||
func TestSecretStoreInvalidReference(t *testing.T) {
|
func TestSecretStoreInvalidReference(t *testing.T) {
|
||||||
// Make sure we clean-up our mess
|
// Make sure we clean-up our mess
|
||||||
defer func() { unlinkedSecrets = make([]*Secret, 0) }()
|
defer func() { unlinkedSecrets = make([]*Secret, 0) }()
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ package amqp
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
_ "embed"
|
_ "embed"
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -47,8 +48,8 @@ type AMQP struct {
|
||||||
ExchangePassive bool `toml:"exchange_passive"`
|
ExchangePassive bool `toml:"exchange_passive"`
|
||||||
ExchangeDurability string `toml:"exchange_durability"`
|
ExchangeDurability string `toml:"exchange_durability"`
|
||||||
ExchangeArguments map[string]string `toml:"exchange_arguments"`
|
ExchangeArguments map[string]string `toml:"exchange_arguments"`
|
||||||
Username string `toml:"username"`
|
Username config.Secret `toml:"username"`
|
||||||
Password string `toml:"password"`
|
Password config.Secret `toml:"password"`
|
||||||
MaxMessages int `toml:"max_messages"`
|
MaxMessages int `toml:"max_messages"`
|
||||||
AuthMethod string `toml:"auth_method"`
|
AuthMethod string `toml:"auth_method"`
|
||||||
RoutingTag string `toml:"routing_tag"`
|
RoutingTag string `toml:"routing_tag"`
|
||||||
|
|
@ -293,11 +294,21 @@ func (q *AMQP) makeClientConfig() (*ClientConfig, error) {
|
||||||
var auth []amqp.Authentication
|
var auth []amqp.Authentication
|
||||||
if strings.ToUpper(q.AuthMethod) == "EXTERNAL" {
|
if strings.ToUpper(q.AuthMethod) == "EXTERNAL" {
|
||||||
auth = []amqp.Authentication{&externalAuth{}}
|
auth = []amqp.Authentication{&externalAuth{}}
|
||||||
} else if q.Username != "" || q.Password != "" {
|
} else if !q.Username.Empty() || !q.Password.Empty() {
|
||||||
|
username, err := q.Username.Get()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("getting username failed: %w", err)
|
||||||
|
}
|
||||||
|
defer config.ReleaseSecret(username)
|
||||||
|
password, err := q.Password.Get()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("getting password failed: %w", err)
|
||||||
|
}
|
||||||
|
defer config.ReleaseSecret(password)
|
||||||
auth = []amqp.Authentication{
|
auth = []amqp.Authentication{
|
||||||
&amqp.PlainAuth{
|
&amqp.PlainAuth{
|
||||||
Username: q.Username,
|
Username: string(username),
|
||||||
Password: q.Password,
|
Password: string(password),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -114,8 +114,8 @@ func TestConnect(t *testing.T) {
|
||||||
name: "username password",
|
name: "username password",
|
||||||
output: &AMQP{
|
output: &AMQP{
|
||||||
URL: "amqp://foo:bar@localhost",
|
URL: "amqp://foo:bar@localhost",
|
||||||
Username: "telegraf",
|
Username: config.NewSecret([]byte("telegraf")),
|
||||||
Password: "pa$$word",
|
Password: config.NewSecret([]byte("pa$$word")),
|
||||||
connect: func(_ *ClientConfig) (Client, error) {
|
connect: func(_ *ClientConfig) (Client, error) {
|
||||||
return NewMockClient(), nil
|
return NewMockClient(), nil
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ var sampleConfig string
|
||||||
// Dynatrace Configuration for the Dynatrace output plugin
|
// Dynatrace Configuration for the Dynatrace output plugin
|
||||||
type Dynatrace struct {
|
type Dynatrace struct {
|
||||||
URL string `toml:"url"`
|
URL string `toml:"url"`
|
||||||
APIToken string `toml:"api_token"`
|
APIToken config.Secret `toml:"api_token"`
|
||||||
Prefix string `toml:"prefix"`
|
Prefix string `toml:"prefix"`
|
||||||
Log telegraf.Logger `toml:"-"`
|
Log telegraf.Logger `toml:"-"`
|
||||||
Timeout config.Duration `toml:"timeout"`
|
Timeout config.Duration `toml:"timeout"`
|
||||||
|
|
@ -151,8 +151,13 @@ func (d *Dynatrace) send(msg string) error {
|
||||||
}
|
}
|
||||||
req.Header.Add("Content-Type", "text/plain; charset=UTF-8")
|
req.Header.Add("Content-Type", "text/plain; charset=UTF-8")
|
||||||
|
|
||||||
if len(d.APIToken) != 0 {
|
if !d.APIToken.Empty() {
|
||||||
req.Header.Add("Authorization", "Api-Token "+d.APIToken)
|
token, err := d.APIToken.Get()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("getting token failed: %w", err)
|
||||||
|
}
|
||||||
|
req.Header.Add("Authorization", "Api-Token "+string(token))
|
||||||
|
config.ReleaseSecret(token)
|
||||||
}
|
}
|
||||||
// add user-agent header to identify metric source
|
// add user-agent header to identify metric source
|
||||||
req.Header.Add("User-Agent", "telegraf")
|
req.Header.Add("User-Agent", "telegraf")
|
||||||
|
|
@ -184,7 +189,7 @@ func (d *Dynatrace) Init() error {
|
||||||
d.Log.Infof("Dynatrace URL is empty, defaulting to OneAgent metrics interface")
|
d.Log.Infof("Dynatrace URL is empty, defaulting to OneAgent metrics interface")
|
||||||
d.URL = apiconstants.GetDefaultOneAgentEndpoint()
|
d.URL = apiconstants.GetDefaultOneAgentEndpoint()
|
||||||
}
|
}
|
||||||
if d.URL != apiconstants.GetDefaultOneAgentEndpoint() && len(d.APIToken) == 0 {
|
if d.URL != apiconstants.GetDefaultOneAgentEndpoint() && d.APIToken.Empty() {
|
||||||
d.Log.Errorf("Dynatrace api_token is a required field for Dynatrace output")
|
d.Log.Errorf("Dynatrace api_token is a required field for Dynatrace output")
|
||||||
return fmt.Errorf("api_token is a required field for Dynatrace output")
|
return fmt.Errorf("api_token is a required field for Dynatrace output")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ func TestNilMetrics(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
d.URL = ts.URL
|
d.URL = ts.URL
|
||||||
d.APIToken = "123"
|
d.APIToken = config.NewSecret([]byte("123"))
|
||||||
d.Log = testutil.Logger{}
|
d.Log = testutil.Logger{}
|
||||||
err := d.Init()
|
err := d.Init()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
@ -58,7 +58,7 @@ func TestEmptyMetricsSlice(t *testing.T) {
|
||||||
d := &Dynatrace{}
|
d := &Dynatrace{}
|
||||||
|
|
||||||
d.URL = ts.URL
|
d.URL = ts.URL
|
||||||
d.APIToken = "123"
|
d.APIToken = config.NewSecret([]byte("123"))
|
||||||
d.Log = testutil.Logger{}
|
d.Log = testutil.Logger{}
|
||||||
|
|
||||||
err := d.Init()
|
err := d.Init()
|
||||||
|
|
@ -82,7 +82,7 @@ func TestMockURL(t *testing.T) {
|
||||||
d := &Dynatrace{}
|
d := &Dynatrace{}
|
||||||
|
|
||||||
d.URL = ts.URL
|
d.URL = ts.URL
|
||||||
d.APIToken = "123"
|
d.APIToken = config.NewSecret([]byte("123"))
|
||||||
d.Log = testutil.Logger{}
|
d.Log = testutil.Logger{}
|
||||||
|
|
||||||
err := d.Init()
|
err := d.Init()
|
||||||
|
|
@ -153,7 +153,7 @@ func TestSendMetrics(t *testing.T) {
|
||||||
|
|
||||||
d := &Dynatrace{
|
d := &Dynatrace{
|
||||||
URL: ts.URL,
|
URL: ts.URL,
|
||||||
APIToken: "123",
|
APIToken: config.NewSecret([]byte("123")),
|
||||||
Log: testutil.Logger{},
|
Log: testutil.Logger{},
|
||||||
AddCounterMetrics: []string{},
|
AddCounterMetrics: []string{},
|
||||||
}
|
}
|
||||||
|
|
@ -230,7 +230,7 @@ func TestSendSingleMetricWithUnorderedTags(t *testing.T) {
|
||||||
d := &Dynatrace{}
|
d := &Dynatrace{}
|
||||||
|
|
||||||
d.URL = ts.URL
|
d.URL = ts.URL
|
||||||
d.APIToken = "123"
|
d.APIToken = config.NewSecret([]byte("123"))
|
||||||
d.Log = testutil.Logger{}
|
d.Log = testutil.Logger{}
|
||||||
err := d.Init()
|
err := d.Init()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
@ -271,7 +271,7 @@ func TestSendMetricWithoutTags(t *testing.T) {
|
||||||
d := &Dynatrace{}
|
d := &Dynatrace{}
|
||||||
|
|
||||||
d.URL = ts.URL
|
d.URL = ts.URL
|
||||||
d.APIToken = "123"
|
d.APIToken = config.NewSecret([]byte("123"))
|
||||||
d.Log = testutil.Logger{}
|
d.Log = testutil.Logger{}
|
||||||
err := d.Init()
|
err := d.Init()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
@ -318,7 +318,7 @@ func TestSendMetricWithUpperCaseTagKeys(t *testing.T) {
|
||||||
d := &Dynatrace{}
|
d := &Dynatrace{}
|
||||||
|
|
||||||
d.URL = ts.URL
|
d.URL = ts.URL
|
||||||
d.APIToken = "123"
|
d.APIToken = config.NewSecret([]byte("123"))
|
||||||
d.Log = testutil.Logger{}
|
d.Log = testutil.Logger{}
|
||||||
err := d.Init()
|
err := d.Init()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
@ -359,7 +359,7 @@ func TestSendBooleanMetricWithoutTags(t *testing.T) {
|
||||||
d := &Dynatrace{}
|
d := &Dynatrace{}
|
||||||
|
|
||||||
d.URL = ts.URL
|
d.URL = ts.URL
|
||||||
d.APIToken = "123"
|
d.APIToken = config.NewSecret([]byte("123"))
|
||||||
d.Log = testutil.Logger{}
|
d.Log = testutil.Logger{}
|
||||||
err := d.Init()
|
err := d.Init()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
@ -402,7 +402,7 @@ func TestSendMetricWithDefaultDimensions(t *testing.T) {
|
||||||
d := &Dynatrace{DefaultDimensions: map[string]string{"dim": "value"}}
|
d := &Dynatrace{DefaultDimensions: map[string]string{"dim": "value"}}
|
||||||
|
|
||||||
d.URL = ts.URL
|
d.URL = ts.URL
|
||||||
d.APIToken = "123"
|
d.APIToken = config.NewSecret([]byte("123"))
|
||||||
d.Log = testutil.Logger{}
|
d.Log = testutil.Logger{}
|
||||||
err := d.Init()
|
err := d.Init()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
@ -445,7 +445,7 @@ func TestMetricDimensionsOverrideDefault(t *testing.T) {
|
||||||
d := &Dynatrace{DefaultDimensions: map[string]string{"dim": "default"}}
|
d := &Dynatrace{DefaultDimensions: map[string]string{"dim": "default"}}
|
||||||
|
|
||||||
d.URL = ts.URL
|
d.URL = ts.URL
|
||||||
d.APIToken = "123"
|
d.APIToken = config.NewSecret([]byte("123"))
|
||||||
d.Log = testutil.Logger{}
|
d.Log = testutil.Logger{}
|
||||||
err := d.Init()
|
err := d.Init()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
@ -487,7 +487,7 @@ func TestStaticDimensionsOverrideMetric(t *testing.T) {
|
||||||
d := &Dynatrace{DefaultDimensions: map[string]string{"dim": "default"}}
|
d := &Dynatrace{DefaultDimensions: map[string]string{"dim": "default"}}
|
||||||
|
|
||||||
d.URL = ts.URL
|
d.URL = ts.URL
|
||||||
d.APIToken = "123"
|
d.APIToken = config.NewSecret([]byte("123"))
|
||||||
d.Log = testutil.Logger{}
|
d.Log = testutil.Logger{}
|
||||||
err := d.Init()
|
err := d.Init()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
@ -533,7 +533,7 @@ func TestSendUnsupportedMetric(t *testing.T) {
|
||||||
logStub := loggerStub{}
|
logStub := loggerStub{}
|
||||||
|
|
||||||
d.URL = ts.URL
|
d.URL = ts.URL
|
||||||
d.APIToken = "123"
|
d.APIToken = config.NewSecret([]byte("123"))
|
||||||
d.Log = logStub
|
d.Log = logStub
|
||||||
err := d.Init()
|
err := d.Init()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ import (
|
||||||
var sampleConfig string
|
var sampleConfig string
|
||||||
|
|
||||||
type Elasticsearch struct {
|
type Elasticsearch struct {
|
||||||
AuthBearerToken string `toml:"auth_bearer_token"`
|
AuthBearerToken config.Secret `toml:"auth_bearer_token"`
|
||||||
DefaultPipeline string `toml:"default_pipeline"`
|
DefaultPipeline string `toml:"default_pipeline"`
|
||||||
DefaultTagValue string `toml:"default_tag_value"`
|
DefaultTagValue string `toml:"default_tag_value"`
|
||||||
EnableGzip bool `toml:"enable_gzip"`
|
EnableGzip bool `toml:"enable_gzip"`
|
||||||
|
|
@ -40,12 +40,12 @@ type Elasticsearch struct {
|
||||||
IndexName string `toml:"index_name"`
|
IndexName string `toml:"index_name"`
|
||||||
ManageTemplate bool `toml:"manage_template"`
|
ManageTemplate bool `toml:"manage_template"`
|
||||||
OverwriteTemplate bool `toml:"overwrite_template"`
|
OverwriteTemplate bool `toml:"overwrite_template"`
|
||||||
Password string `toml:"password"`
|
Username config.Secret `toml:"username"`
|
||||||
|
Password config.Secret `toml:"password"`
|
||||||
TemplateName string `toml:"template_name"`
|
TemplateName string `toml:"template_name"`
|
||||||
Timeout config.Duration `toml:"timeout"`
|
Timeout config.Duration `toml:"timeout"`
|
||||||
URLs []string `toml:"urls"`
|
URLs []string `toml:"urls"`
|
||||||
UsePipeline string `toml:"use_pipeline"`
|
UsePipeline string `toml:"use_pipeline"`
|
||||||
Username string `toml:"username"`
|
|
||||||
Log telegraf.Logger `toml:"-"`
|
Log telegraf.Logger `toml:"-"`
|
||||||
majorReleaseNumber int
|
majorReleaseNumber int
|
||||||
pipelineName string
|
pipelineName string
|
||||||
|
|
@ -182,19 +182,11 @@ func (a *Elasticsearch) Connect() error {
|
||||||
elastic.SetGzip(a.EnableGzip),
|
elastic.SetGzip(a.EnableGzip),
|
||||||
)
|
)
|
||||||
|
|
||||||
if a.Username != "" && a.Password != "" {
|
authOptions, err := a.getAuthOptions()
|
||||||
clientOptions = append(clientOptions,
|
if err != nil {
|
||||||
elastic.SetBasicAuth(a.Username, a.Password),
|
return err
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if a.AuthBearerToken != "" {
|
|
||||||
clientOptions = append(clientOptions,
|
|
||||||
elastic.SetHeaders(http.Header{
|
|
||||||
"Authorization": []string{fmt.Sprintf("Bearer %s", a.AuthBearerToken)},
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
clientOptions = append(clientOptions, authOptions...)
|
||||||
|
|
||||||
if time.Duration(a.HealthCheckInterval) == 0 {
|
if time.Duration(a.HealthCheckInterval) == 0 {
|
||||||
clientOptions = append(clientOptions,
|
clientOptions = append(clientOptions,
|
||||||
|
|
@ -470,6 +462,37 @@ func (a *Elasticsearch) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *Elasticsearch) getAuthOptions() ([]elastic.ClientOptionFunc, error) {
|
||||||
|
var fns []elastic.ClientOptionFunc
|
||||||
|
|
||||||
|
if !a.Username.Empty() && !a.Password.Empty() {
|
||||||
|
username, err := a.Username.Get()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("getting username failed: %w", err)
|
||||||
|
}
|
||||||
|
defer config.ReleaseSecret(username)
|
||||||
|
password, err := a.Password.Get()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("getting password failed: %w", err)
|
||||||
|
}
|
||||||
|
defer config.ReleaseSecret(password)
|
||||||
|
|
||||||
|
fns = append(fns, elastic.SetBasicAuth(string(username), string(password)))
|
||||||
|
}
|
||||||
|
|
||||||
|
if !a.AuthBearerToken.Empty() {
|
||||||
|
token, err := a.AuthBearerToken.Get()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("getting token failed: %w", err)
|
||||||
|
}
|
||||||
|
defer config.ReleaseSecret(token)
|
||||||
|
|
||||||
|
auth := []string{"Bearer " + string(token)}
|
||||||
|
fns = append(fns, elastic.SetHeaders(http.Header{"Authorization": auth}))
|
||||||
|
}
|
||||||
|
return fns, nil
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
outputs.Add("elasticsearch", func() telegraf.Output {
|
outputs.Add("elasticsearch", func() telegraf.Output {
|
||||||
return &Elasticsearch{
|
return &Elasticsearch{
|
||||||
|
|
|
||||||
|
|
@ -746,7 +746,7 @@ func TestAuthorizationHeaderWhenBearerTokenIsPresent(t *testing.T) {
|
||||||
EnableGzip: false,
|
EnableGzip: false,
|
||||||
ManageTemplate: false,
|
ManageTemplate: false,
|
||||||
Log: testutil.Logger{},
|
Log: testutil.Logger{},
|
||||||
AuthBearerToken: "0123456789abcdef",
|
AuthBearerToken: config.NewSecret([]byte("0123456789abcdef")),
|
||||||
}
|
}
|
||||||
|
|
||||||
err := e.Connect()
|
err := e.Connect()
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import (
|
||||||
"github.com/hashicorp/go-uuid"
|
"github.com/hashicorp/go-uuid"
|
||||||
|
|
||||||
"github.com/influxdata/telegraf"
|
"github.com/influxdata/telegraf"
|
||||||
|
"github.com/influxdata/telegraf/config"
|
||||||
"github.com/influxdata/telegraf/plugins/outputs"
|
"github.com/influxdata/telegraf/plugins/outputs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -31,8 +32,8 @@ type metricMeta struct {
|
||||||
type Groundwork struct {
|
type Groundwork struct {
|
||||||
Server string `toml:"url"`
|
Server string `toml:"url"`
|
||||||
AgentID string `toml:"agent_id"`
|
AgentID string `toml:"agent_id"`
|
||||||
Username string `toml:"username"`
|
Username config.Secret `toml:"username"`
|
||||||
Password string `toml:"password"`
|
Password config.Secret `toml:"password"`
|
||||||
DefaultAppType string `toml:"default_app_type"`
|
DefaultAppType string `toml:"default_app_type"`
|
||||||
DefaultHost string `toml:"default_host"`
|
DefaultHost string `toml:"default_host"`
|
||||||
DefaultServiceState string `toml:"default_service_state"`
|
DefaultServiceState string `toml:"default_service_state"`
|
||||||
|
|
@ -53,10 +54,10 @@ func (g *Groundwork) Init() error {
|
||||||
if g.AgentID == "" {
|
if g.AgentID == "" {
|
||||||
return errors.New(`no "agent_id" provided`)
|
return errors.New(`no "agent_id" provided`)
|
||||||
}
|
}
|
||||||
if g.Username == "" {
|
if g.Username.Empty() {
|
||||||
return errors.New(`no "username" provided`)
|
return errors.New(`no "username" provided`)
|
||||||
}
|
}
|
||||||
if g.Password == "" {
|
if g.Password.Empty() {
|
||||||
return errors.New(`no "password" provided`)
|
return errors.New(`no "password" provided`)
|
||||||
}
|
}
|
||||||
if g.DefaultAppType == "" {
|
if g.DefaultAppType == "" {
|
||||||
|
|
@ -72,13 +73,23 @@ func (g *Groundwork) Init() error {
|
||||||
return errors.New(`invalid "default_service_state" provided`)
|
return errors.New(`invalid "default_service_state" provided`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
username, err := g.Username.Get()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("getting username failed: %w", err)
|
||||||
|
}
|
||||||
|
defer config.ReleaseSecret(username)
|
||||||
|
password, err := g.Password.Get()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("getting password failed: %w", err)
|
||||||
|
}
|
||||||
|
defer config.ReleaseSecret(password)
|
||||||
g.client = clients.GWClient{
|
g.client = clients.GWClient{
|
||||||
AppName: "telegraf",
|
AppName: "telegraf",
|
||||||
AppType: g.DefaultAppType,
|
AppType: g.DefaultAppType,
|
||||||
GWConnection: &clients.GWConnection{
|
GWConnection: &clients.GWConnection{
|
||||||
HostName: g.Server,
|
HostName: g.Server,
|
||||||
UserName: g.Username,
|
UserName: string(username),
|
||||||
Password: g.Password,
|
Password: string(password),
|
||||||
IsDynamicInventory: true,
|
IsDynamicInventory: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import (
|
||||||
v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4"
|
v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4"
|
||||||
|
|
||||||
"github.com/influxdata/telegraf"
|
"github.com/influxdata/telegraf"
|
||||||
|
"github.com/influxdata/telegraf/config"
|
||||||
"github.com/influxdata/telegraf/internal"
|
"github.com/influxdata/telegraf/internal"
|
||||||
internalaws "github.com/influxdata/telegraf/plugins/common/aws"
|
internalaws "github.com/influxdata/telegraf/plugins/common/aws"
|
||||||
httpconfig "github.com/influxdata/telegraf/plugins/common/http"
|
httpconfig "github.com/influxdata/telegraf/plugins/common/http"
|
||||||
|
|
@ -43,8 +44,8 @@ const (
|
||||||
type HTTP struct {
|
type HTTP struct {
|
||||||
URL string `toml:"url"`
|
URL string `toml:"url"`
|
||||||
Method string `toml:"method"`
|
Method string `toml:"method"`
|
||||||
Username string `toml:"username"`
|
Username config.Secret `toml:"username"`
|
||||||
Password string `toml:"password"`
|
Password config.Secret `toml:"password"`
|
||||||
Headers map[string]string `toml:"headers"`
|
Headers map[string]string `toml:"headers"`
|
||||||
ContentEncoding string `toml:"content_encoding"`
|
ContentEncoding string `toml:"content_encoding"`
|
||||||
UseBatchFormat bool `toml:"use_batch_format"`
|
UseBatchFormat bool `toml:"use_batch_format"`
|
||||||
|
|
@ -180,8 +181,19 @@ func (h *HTTP) writeMetric(reqBody []byte) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if h.Username != "" || h.Password != "" {
|
if !h.Username.Empty() || !h.Password.Empty() {
|
||||||
req.SetBasicAuth(h.Username, h.Password)
|
username, err := h.Username.Get()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("getting username failed: %w", err)
|
||||||
|
}
|
||||||
|
defer config.ReleaseSecret(username)
|
||||||
|
password, err := h.Password.Get()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("getting password failed: %w", err)
|
||||||
|
}
|
||||||
|
defer config.ReleaseSecret(password)
|
||||||
|
|
||||||
|
req.SetBasicAuth(string(username), string(password))
|
||||||
}
|
}
|
||||||
|
|
||||||
// google api auth
|
// google api auth
|
||||||
|
|
|
||||||
|
|
@ -395,55 +395,46 @@ func TestBasicAuth(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
plugin *HTTP
|
username string
|
||||||
|
password string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "default",
|
name: "default",
|
||||||
plugin: &HTTP{
|
|
||||||
URL: u.String(),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "username only",
|
name: "username only",
|
||||||
plugin: &HTTP{
|
username: "username",
|
||||||
URL: u.String(),
|
|
||||||
Username: "username",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "password only",
|
name: "password only",
|
||||||
plugin: &HTTP{
|
password: "pa$$word",
|
||||||
URL: u.String(),
|
|
||||||
Password: "pa$$word",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "username and password",
|
name: "username and password",
|
||||||
plugin: &HTTP{
|
username: "username",
|
||||||
URL: u.String(),
|
password: "pa$$word",
|
||||||
Username: "username",
|
|
||||||
Password: "pa$$word",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
plugin := &HTTP{
|
||||||
|
URL: u.String(),
|
||||||
|
Username: config.NewSecret([]byte(tt.username)),
|
||||||
|
Password: config.NewSecret([]byte(tt.password)),
|
||||||
|
}
|
||||||
ts.Config.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
ts.Config.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
username, password, _ := r.BasicAuth()
|
username, password, _ := r.BasicAuth()
|
||||||
require.Equal(t, tt.plugin.Username, username)
|
require.Equal(t, tt.username, username)
|
||||||
require.Equal(t, tt.plugin.Password, password)
|
require.Equal(t, tt.password, password)
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
})
|
})
|
||||||
|
|
||||||
serializer := influx.NewSerializer()
|
serializer := influx.NewSerializer()
|
||||||
tt.plugin.SetSerializer(serializer)
|
plugin.SetSerializer(serializer)
|
||||||
err = tt.plugin.Connect()
|
require.NoError(t, plugin.Connect())
|
||||||
require.NoError(t, err)
|
require.NoError(t, plugin.Write([]telegraf.Metric{getMetric()}))
|
||||||
|
|
||||||
err = tt.plugin.Write([]telegraf.Metric{getMetric()})
|
|
||||||
require.NoError(t, err)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/influxdata/telegraf"
|
"github.com/influxdata/telegraf"
|
||||||
|
"github.com/influxdata/telegraf/config"
|
||||||
"github.com/influxdata/telegraf/internal"
|
"github.com/influxdata/telegraf/internal"
|
||||||
"github.com/influxdata/telegraf/plugins/serializers/influx"
|
"github.com/influxdata/telegraf/plugins/serializers/influx"
|
||||||
)
|
)
|
||||||
|
|
@ -88,8 +89,8 @@ type HTTPConfig struct {
|
||||||
URL *url.URL
|
URL *url.URL
|
||||||
UserAgent string
|
UserAgent string
|
||||||
Timeout time.Duration
|
Timeout time.Duration
|
||||||
Username string
|
Username config.Secret
|
||||||
Password string
|
Password config.Secret
|
||||||
TLSConfig *tls.Config
|
TLSConfig *tls.Config
|
||||||
Proxy *url.URL
|
Proxy *url.URL
|
||||||
Headers map[string]string
|
Headers map[string]string
|
||||||
|
|
@ -451,9 +452,11 @@ func (c *httpClient) makeQueryRequest(query string) (*http.Request, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
c.addHeaders(req)
|
if err := c.addHeaders(req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return req, nil
|
return req, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *httpClient) makeWriteRequest(address string, body io.Reader) (*http.Request, error) {
|
func (c *httpClient) makeWriteRequest(address string, body io.Reader) (*http.Request, error) {
|
||||||
|
|
@ -465,7 +468,9 @@ func (c *httpClient) makeWriteRequest(address string, body io.Reader) (*http.Req
|
||||||
}
|
}
|
||||||
|
|
||||||
req.Header.Set("Content-Type", "text/plain; charset=utf-8")
|
req.Header.Set("Content-Type", "text/plain; charset=utf-8")
|
||||||
c.addHeaders(req)
|
if err := c.addHeaders(req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
if c.config.ContentEncoding == "gzip" {
|
if c.config.ContentEncoding == "gzip" {
|
||||||
req.Header.Set("Content-Encoding", "gzip")
|
req.Header.Set("Content-Encoding", "gzip")
|
||||||
|
|
@ -491,14 +496,27 @@ func (c *httpClient) requestBodyReader(metrics []telegraf.Metric) (io.ReadCloser
|
||||||
return io.NopCloser(reader), nil
|
return io.NopCloser(reader), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *httpClient) addHeaders(req *http.Request) {
|
func (c *httpClient) addHeaders(req *http.Request) error {
|
||||||
if c.config.Username != "" || c.config.Password != "" {
|
if !c.config.Username.Empty() || !c.config.Password.Empty() {
|
||||||
req.SetBasicAuth(c.config.Username, c.config.Password)
|
username, err := c.config.Username.Get()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("getting username failed: %w", err)
|
||||||
|
}
|
||||||
|
defer config.ReleaseSecret(username)
|
||||||
|
password, err := c.config.Password.Get()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("getting password failed: %w", err)
|
||||||
|
}
|
||||||
|
defer config.ReleaseSecret(password)
|
||||||
|
|
||||||
|
req.SetBasicAuth(string(username), string(password))
|
||||||
}
|
}
|
||||||
|
|
||||||
for header, value := range c.config.Headers {
|
for header, value := range c.config.Headers {
|
||||||
req.Header.Set(header, value)
|
req.Header.Set(header, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *httpClient) validateResponse(response io.ReadCloser) (io.ReadCloser, error) {
|
func (c *httpClient) validateResponse(response io.ReadCloser) (io.ReadCloser, error) {
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/influxdata/telegraf"
|
"github.com/influxdata/telegraf"
|
||||||
|
"github.com/influxdata/telegraf/config"
|
||||||
"github.com/influxdata/telegraf/internal"
|
"github.com/influxdata/telegraf/internal"
|
||||||
"github.com/influxdata/telegraf/metric"
|
"github.com/influxdata/telegraf/metric"
|
||||||
"github.com/influxdata/telegraf/plugins/outputs/influxdb"
|
"github.com/influxdata/telegraf/plugins/outputs/influxdb"
|
||||||
|
|
@ -91,8 +92,8 @@ func TestHTTP_CreateDatabase(t *testing.T) {
|
||||||
name: "send basic auth",
|
name: "send basic auth",
|
||||||
config: influxdb.HTTPConfig{
|
config: influxdb.HTTPConfig{
|
||||||
URL: u,
|
URL: u,
|
||||||
Username: "guy",
|
Username: config.NewSecret([]byte("guy")),
|
||||||
Password: "smiley",
|
Password: config.NewSecret([]byte("smiley")),
|
||||||
Database: "telegraf",
|
Database: "telegraf",
|
||||||
},
|
},
|
||||||
database: "telegraf",
|
database: "telegraf",
|
||||||
|
|
@ -302,8 +303,8 @@ func TestHTTP_Write(t *testing.T) {
|
||||||
config: influxdb.HTTPConfig{
|
config: influxdb.HTTPConfig{
|
||||||
URL: u,
|
URL: u,
|
||||||
Database: "telegraf",
|
Database: "telegraf",
|
||||||
Username: "guy",
|
Username: config.NewSecret([]byte("guy")),
|
||||||
Password: "smiley",
|
Password: config.NewSecret([]byte("smiley")),
|
||||||
Log: testutil.Logger{},
|
Log: testutil.Logger{},
|
||||||
},
|
},
|
||||||
queryHandlerFunc: func(t *testing.T, w http.ResponseWriter, r *http.Request) {
|
queryHandlerFunc: func(t *testing.T, w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
|
||||||
|
|
@ -38,8 +38,8 @@ type Client interface {
|
||||||
type InfluxDB struct {
|
type InfluxDB struct {
|
||||||
URL string `toml:"url" deprecated:"0.1.9;2.0.0;use 'urls' instead"`
|
URL string `toml:"url" deprecated:"0.1.9;2.0.0;use 'urls' instead"`
|
||||||
URLs []string `toml:"urls"`
|
URLs []string `toml:"urls"`
|
||||||
Username string `toml:"username"`
|
Username config.Secret `toml:"username"`
|
||||||
Password string `toml:"password"`
|
Password config.Secret `toml:"password"`
|
||||||
Database string `toml:"database"`
|
Database string `toml:"database"`
|
||||||
DatabaseTag string `toml:"database_tag"`
|
DatabaseTag string `toml:"database_tag"`
|
||||||
ExcludeDatabaseTag bool `toml:"exclude_database_tag"`
|
ExcludeDatabaseTag bool `toml:"exclude_database_tag"`
|
||||||
|
|
|
||||||
|
|
@ -121,8 +121,8 @@ func TestConnectHTTPConfig(t *testing.T) {
|
||||||
RetentionPolicy: "default",
|
RetentionPolicy: "default",
|
||||||
WriteConsistency: "any",
|
WriteConsistency: "any",
|
||||||
Timeout: config.Duration(5 * time.Second),
|
Timeout: config.Duration(5 * time.Second),
|
||||||
Username: "guy",
|
Username: config.NewSecret([]byte("guy")),
|
||||||
Password: "smiley",
|
Password: config.NewSecret([]byte("smiley")),
|
||||||
UserAgent: "telegraf",
|
UserAgent: "telegraf",
|
||||||
HTTPProxy: "http://localhost:8086",
|
HTTPProxy: "http://localhost:8086",
|
||||||
HTTPHeaders: map[string]string{
|
HTTPHeaders: map[string]string{
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/influxdata/telegraf"
|
"github.com/influxdata/telegraf"
|
||||||
|
"github.com/influxdata/telegraf/config"
|
||||||
"github.com/influxdata/telegraf/internal"
|
"github.com/influxdata/telegraf/internal"
|
||||||
"github.com/influxdata/telegraf/plugins/serializers/influx"
|
"github.com/influxdata/telegraf/plugins/serializers/influx"
|
||||||
)
|
)
|
||||||
|
|
@ -41,7 +42,7 @@ const (
|
||||||
|
|
||||||
type HTTPConfig struct {
|
type HTTPConfig struct {
|
||||||
URL *url.URL
|
URL *url.URL
|
||||||
Token string
|
Token config.Secret
|
||||||
Organization string
|
Organization string
|
||||||
Bucket string
|
Bucket string
|
||||||
BucketTag string
|
BucketTag string
|
||||||
|
|
@ -74,59 +75,66 @@ type httpClient struct {
|
||||||
log telegraf.Logger
|
log telegraf.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHTTPClient(config *HTTPConfig) (*httpClient, error) {
|
func NewHTTPClient(cfg *HTTPConfig) (*httpClient, error) {
|
||||||
if config.URL == nil {
|
if cfg.URL == nil {
|
||||||
return nil, ErrMissingURL
|
return nil, ErrMissingURL
|
||||||
}
|
}
|
||||||
|
|
||||||
timeout := config.Timeout
|
timeout := cfg.Timeout
|
||||||
if timeout == 0 {
|
if timeout == 0 {
|
||||||
timeout = defaultRequestTimeout
|
timeout = defaultRequestTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
userAgent := config.UserAgent
|
userAgent := cfg.UserAgent
|
||||||
if userAgent == "" {
|
if userAgent == "" {
|
||||||
userAgent = internal.ProductToken()
|
userAgent = internal.ProductToken()
|
||||||
}
|
}
|
||||||
|
|
||||||
var headers = make(map[string]string, len(config.Headers)+2)
|
var headers = make(map[string]string, len(cfg.Headers)+2)
|
||||||
headers["User-Agent"] = userAgent
|
headers["User-Agent"] = userAgent
|
||||||
headers["Authorization"] = "Token " + config.Token
|
|
||||||
for k, v := range config.Headers {
|
token, err := cfg.Token.Get()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("getting token failed: %w", err)
|
||||||
|
}
|
||||||
|
headers["Authorization"] = "Token " + string(token)
|
||||||
|
config.ReleaseSecret(token)
|
||||||
|
|
||||||
|
for k, v := range cfg.Headers {
|
||||||
headers[k] = v
|
headers[k] = v
|
||||||
}
|
}
|
||||||
|
|
||||||
var proxy func(*http.Request) (*url.URL, error)
|
var proxy func(*http.Request) (*url.URL, error)
|
||||||
if config.Proxy != nil {
|
if cfg.Proxy != nil {
|
||||||
proxy = http.ProxyURL(config.Proxy)
|
proxy = http.ProxyURL(cfg.Proxy)
|
||||||
} else {
|
} else {
|
||||||
proxy = http.ProxyFromEnvironment
|
proxy = http.ProxyFromEnvironment
|
||||||
}
|
}
|
||||||
|
|
||||||
serializer := config.Serializer
|
serializer := cfg.Serializer
|
||||||
if serializer == nil {
|
if serializer == nil {
|
||||||
serializer = influx.NewSerializer()
|
serializer = influx.NewSerializer()
|
||||||
}
|
}
|
||||||
|
|
||||||
var transport *http.Transport
|
var transport *http.Transport
|
||||||
switch config.URL.Scheme {
|
switch cfg.URL.Scheme {
|
||||||
case "http", "https":
|
case "http", "https":
|
||||||
transport = &http.Transport{
|
transport = &http.Transport{
|
||||||
Proxy: proxy,
|
Proxy: proxy,
|
||||||
TLSClientConfig: config.TLSConfig,
|
TLSClientConfig: cfg.TLSConfig,
|
||||||
}
|
}
|
||||||
case "unix":
|
case "unix":
|
||||||
transport = &http.Transport{
|
transport = &http.Transport{
|
||||||
Dial: func(_, _ string) (net.Conn, error) {
|
Dial: func(_, _ string) (net.Conn, error) {
|
||||||
return net.DialTimeout(
|
return net.DialTimeout(
|
||||||
config.URL.Scheme,
|
cfg.URL.Scheme,
|
||||||
config.URL.Path,
|
cfg.URL.Path,
|
||||||
timeout,
|
timeout,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unsupported scheme %q", config.URL.Scheme)
|
return nil, fmt.Errorf("unsupported scheme %q", cfg.URL.Scheme)
|
||||||
}
|
}
|
||||||
|
|
||||||
client := &httpClient{
|
client := &httpClient{
|
||||||
|
|
@ -135,15 +143,15 @@ func NewHTTPClient(config *HTTPConfig) (*httpClient, error) {
|
||||||
Timeout: timeout,
|
Timeout: timeout,
|
||||||
Transport: transport,
|
Transport: transport,
|
||||||
},
|
},
|
||||||
url: config.URL,
|
url: cfg.URL,
|
||||||
ContentEncoding: config.ContentEncoding,
|
ContentEncoding: cfg.ContentEncoding,
|
||||||
Timeout: timeout,
|
Timeout: timeout,
|
||||||
Headers: headers,
|
Headers: headers,
|
||||||
Organization: config.Organization,
|
Organization: cfg.Organization,
|
||||||
Bucket: config.Bucket,
|
Bucket: cfg.Bucket,
|
||||||
BucketTag: config.BucketTag,
|
BucketTag: cfg.BucketTag,
|
||||||
ExcludeBucketTag: config.ExcludeBucketTag,
|
ExcludeBucketTag: cfg.ExcludeBucketTag,
|
||||||
log: config.Log,
|
log: cfg.Log,
|
||||||
}
|
}
|
||||||
return client, nil
|
return client, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ type Client interface {
|
||||||
|
|
||||||
type InfluxDB struct {
|
type InfluxDB struct {
|
||||||
URLs []string `toml:"urls"`
|
URLs []string `toml:"urls"`
|
||||||
Token string `toml:"token"`
|
Token config.Secret `toml:"token"`
|
||||||
Organization string `toml:"organization"`
|
Organization string `toml:"organization"`
|
||||||
Bucket string `toml:"bucket"`
|
Bucket string `toml:"bucket"`
|
||||||
BucketTag string `toml:"bucket_tag"`
|
BucketTag string `toml:"bucket_tag"`
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ var (
|
||||||
|
|
||||||
type Instrumental struct {
|
type Instrumental struct {
|
||||||
Host string `toml:"host"`
|
Host string `toml:"host"`
|
||||||
APIToken string `toml:"api_token"`
|
APIToken config.Secret `toml:"api_token"`
|
||||||
Prefix string `toml:"prefix"`
|
Prefix string `toml:"prefix"`
|
||||||
DataFormat string `toml:"data_format"`
|
DataFormat string `toml:"data_format"`
|
||||||
Template string `toml:"template"`
|
Template string `toml:"template"`
|
||||||
|
|
@ -164,8 +164,13 @@ func (i *Instrumental) Write(metrics []telegraf.Metric) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Instrumental) authenticate(conn net.Conn) error {
|
func (i *Instrumental) authenticate(conn net.Conn) error {
|
||||||
_, err := fmt.Fprintf(conn, HandshakeFormat, i.APIToken)
|
token, err := i.APIToken.Get()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
return fmt.Errorf("getting token failed: %w", err)
|
||||||
|
}
|
||||||
|
defer config.ReleaseSecret(token)
|
||||||
|
|
||||||
|
if _, err := fmt.Fprintf(conn, HandshakeFormat, string(token)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/influxdata/telegraf"
|
"github.com/influxdata/telegraf"
|
||||||
|
"github.com/influxdata/telegraf/config"
|
||||||
"github.com/influxdata/telegraf/metric"
|
"github.com/influxdata/telegraf/metric"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -21,7 +22,7 @@ func TestWrite(t *testing.T) {
|
||||||
|
|
||||||
i := Instrumental{
|
i := Instrumental{
|
||||||
Host: "127.0.0.1",
|
Host: "127.0.0.1",
|
||||||
APIToken: "abc123token",
|
APIToken: config.NewSecret([]byte("abc123token")),
|
||||||
Prefix: "my.prefix",
|
Prefix: "my.prefix",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,8 @@ var sampleConfig string
|
||||||
type IoTDB struct {
|
type IoTDB struct {
|
||||||
Host string `toml:"host"`
|
Host string `toml:"host"`
|
||||||
Port string `toml:"port"`
|
Port string `toml:"port"`
|
||||||
User string `toml:"user"`
|
User config.Secret `toml:"user"`
|
||||||
Password string `toml:"password"`
|
Password config.Secret `toml:"password"`
|
||||||
Timeout config.Duration `toml:"timeout"`
|
Timeout config.Duration `toml:"timeout"`
|
||||||
ConvertUint64To string `toml:"uint64_conversion"`
|
ConvertUint64To string `toml:"uint64_conversion"`
|
||||||
TimeStampUnit string `toml:"timestamp_precision"`
|
TimeStampUnit string `toml:"timestamp_precision"`
|
||||||
|
|
@ -64,16 +64,36 @@ func (s *IoTDB) Init() error {
|
||||||
if !choice.Contains(s.TreatTagsAs, []string{"fields", "device_id"}) {
|
if !choice.Contains(s.TreatTagsAs, []string{"fields", "device_id"}) {
|
||||||
return fmt.Errorf("unknown 'convert_tags_to' method %q", s.TreatTagsAs)
|
return fmt.Errorf("unknown 'convert_tags_to' method %q", s.TreatTagsAs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if s.User.Empty() {
|
||||||
|
s.User.Destroy()
|
||||||
|
s.User = config.NewSecret([]byte("root"))
|
||||||
|
}
|
||||||
|
if s.Password.Empty() {
|
||||||
|
s.Password.Destroy()
|
||||||
|
s.Password = config.NewSecret([]byte("root"))
|
||||||
|
}
|
||||||
|
|
||||||
s.Log.Info("Initialization completed.")
|
s.Log.Info("Initialization completed.")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *IoTDB) Connect() error {
|
func (s *IoTDB) Connect() error {
|
||||||
|
username, err := s.User.Get()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("getting username failed: %w", err)
|
||||||
|
}
|
||||||
|
defer config.ReleaseSecret(username)
|
||||||
|
password, err := s.Password.Get()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("getting password failed: %w", err)
|
||||||
|
}
|
||||||
|
defer config.ReleaseSecret(password)
|
||||||
sessionConf := &client.Config{
|
sessionConf := &client.Config{
|
||||||
Host: s.Host,
|
Host: s.Host,
|
||||||
Port: s.Port,
|
Port: s.Port,
|
||||||
UserName: s.User,
|
UserName: string(username),
|
||||||
Password: s.Password,
|
Password: string(password),
|
||||||
}
|
}
|
||||||
var ss = client.NewSession(sessionConf)
|
var ss = client.NewSession(sessionConf)
|
||||||
s.session = &ss
|
s.session = &ss
|
||||||
|
|
@ -265,8 +285,6 @@ func newIoTDB() *IoTDB {
|
||||||
return &IoTDB{
|
return &IoTDB{
|
||||||
Host: "localhost",
|
Host: "localhost",
|
||||||
Port: "6667",
|
Port: "6667",
|
||||||
User: "root",
|
|
||||||
Password: "root",
|
|
||||||
Timeout: config.Duration(time.Second * 5),
|
Timeout: config.Duration(time.Second * 5),
|
||||||
ConvertUint64To: "int64_clip",
|
ConvertUint64To: "int64_clip",
|
||||||
TimeStampUnit: "nanosecond",
|
TimeStampUnit: "nanosecond",
|
||||||
|
|
|
||||||
|
|
@ -511,8 +511,8 @@ func TestIntegrationInserts(t *testing.T) {
|
||||||
testClient := &IoTDB{
|
testClient := &IoTDB{
|
||||||
Host: container.Address,
|
Host: container.Address,
|
||||||
Port: container.Ports[iotdbPort],
|
Port: container.Ports[iotdbPort],
|
||||||
User: "root",
|
User: config.NewSecret([]byte("root")),
|
||||||
Password: "root",
|
Password: config.NewSecret([]byte("root")),
|
||||||
Timeout: config.Duration(time.Second * 5),
|
Timeout: config.Duration(time.Second * 5),
|
||||||
ConvertUint64To: "int64_clip",
|
ConvertUint64To: "int64_clip",
|
||||||
TimeStampUnit: "nanosecond",
|
TimeStampUnit: "nanosecond",
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
_ "embed"
|
_ "embed"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
@ -22,8 +23,8 @@ var sampleConfig string
|
||||||
|
|
||||||
// Librato structure for configuration and client
|
// Librato structure for configuration and client
|
||||||
type Librato struct {
|
type Librato struct {
|
||||||
APIUser string `toml:"api_user"`
|
APIUser config.Secret `toml:"api_user"`
|
||||||
APIToken string `toml:"api_token"`
|
APIToken config.Secret `toml:"api_token"`
|
||||||
Debug bool `toml:"debug"`
|
Debug bool `toml:"debug"`
|
||||||
SourceTag string `toml:"source_tag" deprecated:"1.0.0;use 'template' instead"`
|
SourceTag string `toml:"source_tag" deprecated:"1.0.0;use 'template' instead"`
|
||||||
Timeout config.Duration `toml:"timeout"`
|
Timeout config.Duration `toml:"timeout"`
|
||||||
|
|
@ -67,9 +68,8 @@ func (*Librato) SampleConfig() string {
|
||||||
// Connect is the default output plugin connection function who make sure it
|
// Connect is the default output plugin connection function who make sure it
|
||||||
// can connect to the endpoint
|
// can connect to the endpoint
|
||||||
func (l *Librato) Connect() error {
|
func (l *Librato) Connect() error {
|
||||||
if l.APIUser == "" || l.APIToken == "" {
|
if l.APIUser.Empty() || l.APIToken.Empty() {
|
||||||
return fmt.Errorf(
|
return errors.New("api_user and api_token required")
|
||||||
"api_user and api_token are required fields for librato output")
|
|
||||||
}
|
}
|
||||||
l.client = &http.Client{
|
l.client = &http.Client{
|
||||||
Transport: &http.Transport{
|
Transport: &http.Transport{
|
||||||
|
|
@ -142,7 +142,19 @@ func (l *Librato) writeBatch(start int, sizeBatch int, metricCounter int, tempGa
|
||||||
return fmt.Errorf("unable to create http.Request, %s", err.Error())
|
return fmt.Errorf("unable to create http.Request, %s", err.Error())
|
||||||
}
|
}
|
||||||
req.Header.Add("Content-Type", "application/json")
|
req.Header.Add("Content-Type", "application/json")
|
||||||
req.SetBasicAuth(l.APIUser, l.APIToken)
|
|
||||||
|
user, err := l.APIUser.Get()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("getting user failed: %w", err)
|
||||||
|
}
|
||||||
|
token, err := l.APIToken.Get()
|
||||||
|
if err != nil {
|
||||||
|
config.ReleaseSecret(user)
|
||||||
|
return fmt.Errorf("getting token failed: %w", err)
|
||||||
|
}
|
||||||
|
req.SetBasicAuth(string(user), string(token))
|
||||||
|
config.ReleaseSecret(user)
|
||||||
|
config.ReleaseSecret(token)
|
||||||
|
|
||||||
resp, err := l.client.Do(req)
|
resp, err := l.client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/influxdata/telegraf"
|
"github.com/influxdata/telegraf"
|
||||||
|
"github.com/influxdata/telegraf/config"
|
||||||
"github.com/influxdata/telegraf/metric"
|
"github.com/influxdata/telegraf/metric"
|
||||||
"github.com/influxdata/telegraf/testutil"
|
"github.com/influxdata/telegraf/testutil"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
@ -33,12 +34,10 @@ func TestUriOverride(t *testing.T) {
|
||||||
defer ts.Close()
|
defer ts.Close()
|
||||||
|
|
||||||
l := newTestLibrato(ts.URL)
|
l := newTestLibrato(ts.URL)
|
||||||
l.APIUser = "telegraf@influxdb.com"
|
l.APIUser = config.NewSecret([]byte("telegraf@influxdb.com"))
|
||||||
l.APIToken = "123456"
|
l.APIToken = config.NewSecret([]byte("123456"))
|
||||||
err := l.Connect()
|
require.NoError(t, l.Connect())
|
||||||
require.NoError(t, err)
|
require.NoError(t, l.Write([]telegraf.Metric{newHostMetric(int32(0), "name", "host")}))
|
||||||
err = l.Write([]telegraf.Metric{newHostMetric(int32(0), "name", "host")})
|
|
||||||
require.NoError(t, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBadStatusCode(t *testing.T) {
|
func TestBadStatusCode(t *testing.T) {
|
||||||
|
|
@ -49,18 +48,11 @@ func TestBadStatusCode(t *testing.T) {
|
||||||
defer ts.Close()
|
defer ts.Close()
|
||||||
|
|
||||||
l := newTestLibrato(ts.URL)
|
l := newTestLibrato(ts.URL)
|
||||||
l.APIUser = "telegraf@influxdb.com"
|
l.APIUser = config.NewSecret([]byte("telegraf@influxdb.com"))
|
||||||
l.APIToken = "123456"
|
l.APIToken = config.NewSecret([]byte("123456"))
|
||||||
err := l.Connect()
|
require.NoError(t, l.Connect())
|
||||||
require.NoError(t, err)
|
err := l.Write([]telegraf.Metric{newHostMetric(int32(0), "name", "host")})
|
||||||
err = l.Write([]telegraf.Metric{newHostMetric(int32(0), "name", "host")})
|
require.ErrorContains(t, err, "received bad status code, 503")
|
||||||
if err == nil {
|
|
||||||
t.Errorf("error expected but none returned")
|
|
||||||
} else {
|
|
||||||
require.EqualError(
|
|
||||||
t,
|
|
||||||
fmt.Errorf("received bad status code, 503\n "), err.Error())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBuildGauge(t *testing.T) {
|
func TestBuildGauge(t *testing.T) {
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,10 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Logzio struct {
|
type Logzio struct {
|
||||||
Log telegraf.Logger `toml:"-"`
|
|
||||||
Timeout config.Duration `toml:"timeout"`
|
|
||||||
Token string `toml:"token"`
|
|
||||||
URL string `toml:"url"`
|
URL string `toml:"url"`
|
||||||
|
Token config.Secret `toml:"token"`
|
||||||
|
Timeout config.Duration `toml:"timeout"`
|
||||||
|
Log telegraf.Logger `toml:"-"`
|
||||||
|
|
||||||
tls.ClientConfig
|
tls.ClientConfig
|
||||||
client *http.Client
|
client *http.Client
|
||||||
|
|
@ -53,9 +53,14 @@ func (*Logzio) SampleConfig() string {
|
||||||
func (l *Logzio) Connect() error {
|
func (l *Logzio) Connect() error {
|
||||||
l.Log.Debug("Connecting to logz.io output...")
|
l.Log.Debug("Connecting to logz.io output...")
|
||||||
|
|
||||||
if l.Token == "" || l.Token == "your logz.io token" {
|
if l.Token.Empty() {
|
||||||
return fmt.Errorf("token is required")
|
return fmt.Errorf("token is required")
|
||||||
}
|
}
|
||||||
|
if equal, err := l.Token.EqualTo([]byte("your logz.io token")); err != nil {
|
||||||
|
return err
|
||||||
|
} else if equal {
|
||||||
|
return fmt.Errorf("please replace 'token' with your actual token")
|
||||||
|
}
|
||||||
|
|
||||||
tlsCfg, err := l.ClientConfig.TLSConfig()
|
tlsCfg, err := l.ClientConfig.TLSConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -110,7 +115,12 @@ func (l *Logzio) Write(metrics []telegraf.Metric) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Logzio) send(metrics []byte) error {
|
func (l *Logzio) send(metrics []byte) error {
|
||||||
req, err := http.NewRequest("POST", l.authURL(), bytes.NewBuffer(metrics))
|
url, err := l.authURL()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequest("POST", url, bytes.NewBuffer(metrics))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to create http.Request, %s", err.Error())
|
return fmt.Errorf("unable to create http.Request, %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
@ -130,8 +140,14 @@ func (l *Logzio) send(metrics []byte) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Logzio) authURL() string {
|
func (l *Logzio) authURL() (string, error) {
|
||||||
return fmt.Sprintf("%s/?token=%s", l.URL, l.Token)
|
token, err := l.Token.Get()
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("getting token failed: %w", err)
|
||||||
|
}
|
||||||
|
defer config.ReleaseSecret(token)
|
||||||
|
|
||||||
|
return fmt.Sprintf("%s/?token=%s", l.URL, string(token)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Logzio) parseMetric(metric telegraf.Metric) *Metric {
|
func (l *Logzio) parseMetric(metric telegraf.Metric) *Metric {
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,15 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/influxdata/telegraf"
|
|
||||||
"github.com/influxdata/telegraf/testutil"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/influxdata/telegraf"
|
||||||
|
"github.com/influxdata/telegraf/config"
|
||||||
|
"github.com/influxdata/telegraf/testutil"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -18,13 +20,23 @@ const (
|
||||||
testURL = "https://logzio.com"
|
testURL = "https://logzio.com"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestConnetWithoutToken(t *testing.T) {
|
func TestConnectWithoutToken(t *testing.T) {
|
||||||
l := &Logzio{
|
l := &Logzio{
|
||||||
URL: testURL,
|
URL: testURL,
|
||||||
Log: testutil.Logger{},
|
Log: testutil.Logger{},
|
||||||
}
|
}
|
||||||
err := l.Connect()
|
err := l.Connect()
|
||||||
require.Error(t, err)
|
require.ErrorContains(t, err, "token is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConnectWithDefaultToken(t *testing.T) {
|
||||||
|
l := &Logzio{
|
||||||
|
URL: testURL,
|
||||||
|
Token: config.NewSecret([]byte("your logz.io token")),
|
||||||
|
Log: testutil.Logger{},
|
||||||
|
}
|
||||||
|
err := l.Connect()
|
||||||
|
require.ErrorContains(t, err, "please replace 'token'")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseMetric(t *testing.T) {
|
func TestParseMetric(t *testing.T) {
|
||||||
|
|
@ -45,16 +57,12 @@ func TestBadStatusCode(t *testing.T) {
|
||||||
defer ts.Close()
|
defer ts.Close()
|
||||||
|
|
||||||
l := &Logzio{
|
l := &Logzio{
|
||||||
Token: testToken,
|
Token: config.NewSecret([]byte(testToken)),
|
||||||
URL: ts.URL,
|
URL: ts.URL,
|
||||||
Log: testutil.Logger{},
|
Log: testutil.Logger{},
|
||||||
}
|
}
|
||||||
|
require.NoError(t, l.Connect())
|
||||||
err := l.Connect()
|
require.Error(t, l.Write(testutil.MockMetrics()))
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
err = l.Write(testutil.MockMetrics())
|
|
||||||
require.Error(t, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWrite(t *testing.T) {
|
func TestWrite(t *testing.T) {
|
||||||
|
|
@ -81,14 +89,10 @@ func TestWrite(t *testing.T) {
|
||||||
defer ts.Close()
|
defer ts.Close()
|
||||||
|
|
||||||
l := &Logzio{
|
l := &Logzio{
|
||||||
Token: testToken,
|
Token: config.NewSecret([]byte(testToken)),
|
||||||
URL: ts.URL,
|
URL: ts.URL,
|
||||||
Log: testutil.Logger{},
|
Log: testutil.Logger{},
|
||||||
}
|
}
|
||||||
|
require.NoError(t, l.Connect())
|
||||||
err := l.Connect()
|
require.NoError(t, l.Write([]telegraf.Metric{tm}))
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
err = l.Write([]telegraf.Metric{tm})
|
|
||||||
require.NoError(t, err)
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,8 @@ type Loki struct {
|
||||||
Domain string `toml:"domain"`
|
Domain string `toml:"domain"`
|
||||||
Endpoint string `toml:"endpoint"`
|
Endpoint string `toml:"endpoint"`
|
||||||
Timeout config.Duration `toml:"timeout"`
|
Timeout config.Duration `toml:"timeout"`
|
||||||
Username string `toml:"username"`
|
Username config.Secret `toml:"username"`
|
||||||
Password string `toml:"password"`
|
Password config.Secret `toml:"password"`
|
||||||
Headers map[string]string `toml:"http_headers"`
|
Headers map[string]string `toml:"http_headers"`
|
||||||
ClientID string `toml:"client_id"`
|
ClientID string `toml:"client_id"`
|
||||||
ClientSecret string `toml:"client_secret"`
|
ClientSecret string `toml:"client_secret"`
|
||||||
|
|
@ -156,8 +156,19 @@ func (l *Loki) writeMetrics(s Streams) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if l.Username != "" {
|
if !l.Username.Empty() {
|
||||||
req.SetBasicAuth(l.Username, l.Password)
|
username, err := l.Username.Get()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("getting username failed: %w", err)
|
||||||
|
}
|
||||||
|
defer config.ReleaseSecret(username)
|
||||||
|
password, err := l.Password.Get()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("getting password failed: %w", err)
|
||||||
|
}
|
||||||
|
defer config.ReleaseSecret(password)
|
||||||
|
|
||||||
|
req.SetBasicAuth(string(username), string(password))
|
||||||
}
|
}
|
||||||
|
|
||||||
for k, v := range l.Headers {
|
for k, v := range l.Headers {
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/influxdata/telegraf"
|
"github.com/influxdata/telegraf"
|
||||||
|
"github.com/influxdata/telegraf/config"
|
||||||
"github.com/influxdata/telegraf/internal"
|
"github.com/influxdata/telegraf/internal"
|
||||||
"github.com/influxdata/telegraf/testutil"
|
"github.com/influxdata/telegraf/testutil"
|
||||||
)
|
)
|
||||||
|
|
@ -250,22 +251,17 @@ func TestBasicAuth(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
plugin *Loki
|
username string
|
||||||
|
password string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "default",
|
name: "default",
|
||||||
plugin: &Loki{
|
|
||||||
Domain: u.String(),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "username and password",
|
name: "username and password",
|
||||||
plugin: &Loki{
|
username: "username",
|
||||||
Domain: u.String(),
|
password: "pa$$word",
|
||||||
Username: "username",
|
|
||||||
Password: "pa$$word",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -273,16 +269,19 @@ func TestBasicAuth(t *testing.T) {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
ts.Config.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
ts.Config.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
username, password, _ := r.BasicAuth()
|
username, password, _ := r.BasicAuth()
|
||||||
require.Equal(t, tt.plugin.Username, username)
|
require.Equal(t, tt.username, username)
|
||||||
require.Equal(t, tt.plugin.Password, password)
|
require.Equal(t, tt.password, password)
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
})
|
})
|
||||||
|
|
||||||
err = tt.plugin.Connect()
|
plugin := &Loki{
|
||||||
require.NoError(t, err)
|
Domain: u.String(),
|
||||||
|
Username: config.NewSecret([]byte(tt.username)),
|
||||||
|
Password: config.NewSecret([]byte(tt.password)),
|
||||||
|
}
|
||||||
|
require.NoError(t, plugin.Connect())
|
||||||
|
|
||||||
err = tt.plugin.Write([]telegraf.Metric{getMetric()})
|
require.NoError(t, plugin.Write([]telegraf.Metric{getMetric()}))
|
||||||
require.NoError(t, err)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,8 +55,8 @@ type MongoDB struct {
|
||||||
AuthenticationType string `toml:"authentication"`
|
AuthenticationType string `toml:"authentication"`
|
||||||
MetricDatabase string `toml:"database"`
|
MetricDatabase string `toml:"database"`
|
||||||
MetricGranularity string `toml:"granularity"`
|
MetricGranularity string `toml:"granularity"`
|
||||||
Username string `toml:"username"`
|
Username config.Secret `toml:"username"`
|
||||||
Password string `toml:"password"`
|
Password config.Secret `toml:"password"`
|
||||||
ServerSelectTimeout config.Duration `toml:"timeout"`
|
ServerSelectTimeout config.Duration `toml:"timeout"`
|
||||||
TTL config.Duration `toml:"ttl"`
|
TTL config.Duration `toml:"ttl"`
|
||||||
Log telegraf.Logger `toml:"-"`
|
Log telegraf.Logger `toml:"-"`
|
||||||
|
|
@ -95,17 +95,28 @@ func (s *MongoDB) Init() error {
|
||||||
|
|
||||||
switch s.AuthenticationType {
|
switch s.AuthenticationType {
|
||||||
case "SCRAM":
|
case "SCRAM":
|
||||||
if s.Username == "" {
|
if s.Username.Empty() {
|
||||||
return fmt.Errorf("SCRAM authentication must specify a username")
|
return fmt.Errorf("SCRAM authentication must specify a username")
|
||||||
}
|
}
|
||||||
if s.Password == "" {
|
if s.Password.Empty() {
|
||||||
return fmt.Errorf("SCRAM authentication must specify a password")
|
return fmt.Errorf("SCRAM authentication must specify a password")
|
||||||
}
|
}
|
||||||
|
username, err := s.Username.Get()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("getting username failed: %w", err)
|
||||||
|
}
|
||||||
|
password, err := s.Password.Get()
|
||||||
|
if err != nil {
|
||||||
|
config.ReleaseSecret(username)
|
||||||
|
return fmt.Errorf("getting password failed: %w", err)
|
||||||
|
}
|
||||||
credential := options.Credential{
|
credential := options.Credential{
|
||||||
AuthMechanism: "SCRAM-SHA-256",
|
AuthMechanism: "SCRAM-SHA-256",
|
||||||
Username: s.Username,
|
Username: string(username),
|
||||||
Password: s.Password,
|
Password: string(password),
|
||||||
}
|
}
|
||||||
|
config.ReleaseSecret(username)
|
||||||
|
config.ReleaseSecret(password)
|
||||||
s.clientOptions.SetAuth(credential)
|
s.clientOptions.SetAuth(credential)
|
||||||
case "X509":
|
case "X509":
|
||||||
//format connection string to include tls/x509 options
|
//format connection string to include tls/x509 options
|
||||||
|
|
|
||||||
|
|
@ -86,8 +86,8 @@ func TestConnectAndWriteIntegrationSCRAMAuth(t *testing.T) {
|
||||||
Dsn: fmt.Sprintf("mongodb://%s:%s/admin",
|
Dsn: fmt.Sprintf("mongodb://%s:%s/admin",
|
||||||
container.Address, container.Ports[servicePort]),
|
container.Address, container.Ports[servicePort]),
|
||||||
AuthenticationType: "SCRAM",
|
AuthenticationType: "SCRAM",
|
||||||
Username: "root",
|
Username: config.NewSecret([]byte("root")),
|
||||||
Password: "changeme",
|
Password: config.NewSecret([]byte("changeme")),
|
||||||
MetricDatabase: "telegraf_test",
|
MetricDatabase: "telegraf_test",
|
||||||
MetricGranularity: "seconds",
|
MetricGranularity: "seconds",
|
||||||
},
|
},
|
||||||
|
|
@ -101,8 +101,8 @@ func TestConnectAndWriteIntegrationSCRAMAuth(t *testing.T) {
|
||||||
Dsn: fmt.Sprintf("mongodb://%s:%s/admin",
|
Dsn: fmt.Sprintf("mongodb://%s:%s/admin",
|
||||||
container.Address, container.Ports[servicePort]),
|
container.Address, container.Ports[servicePort]),
|
||||||
AuthenticationType: "SCRAM",
|
AuthenticationType: "SCRAM",
|
||||||
Username: "root",
|
Username: config.NewSecret([]byte("root")),
|
||||||
Password: "root",
|
Password: config.NewSecret([]byte("root")),
|
||||||
MetricDatabase: "telegraf_test",
|
MetricDatabase: "telegraf_test",
|
||||||
MetricGranularity: "seconds",
|
MetricGranularity: "seconds",
|
||||||
ServerSelectTimeout: config.Duration(time.Duration(5) * time.Second),
|
ServerSelectTimeout: config.Duration(time.Duration(5) * time.Second),
|
||||||
|
|
@ -380,7 +380,7 @@ func TestConfiguration(t *testing.T) {
|
||||||
plugin: &MongoDB{
|
plugin: &MongoDB{
|
||||||
Dsn: "mongodb://localhost:27017",
|
Dsn: "mongodb://localhost:27017",
|
||||||
AuthenticationType: "SCRAM",
|
AuthenticationType: "SCRAM",
|
||||||
Password: "somerandompasswordthatwontwork",
|
Password: config.NewSecret([]byte("somerandompasswordthatwontwork")),
|
||||||
MetricDatabase: "telegraf_test",
|
MetricDatabase: "telegraf_test",
|
||||||
MetricGranularity: "seconds",
|
MetricGranularity: "seconds",
|
||||||
},
|
},
|
||||||
|
|
@ -390,7 +390,7 @@ func TestConfiguration(t *testing.T) {
|
||||||
plugin: &MongoDB{
|
plugin: &MongoDB{
|
||||||
Dsn: "mongodb://localhost:27017",
|
Dsn: "mongodb://localhost:27017",
|
||||||
AuthenticationType: "SCRAM",
|
AuthenticationType: "SCRAM",
|
||||||
Username: "somerandomusernamethatwontwork",
|
Username: config.NewSecret([]byte("somerandomusernamethatwontwork")),
|
||||||
MetricDatabase: "telegraf_test",
|
MetricDatabase: "telegraf_test",
|
||||||
MetricGranularity: "seconds",
|
MetricGranularity: "seconds",
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -24,10 +24,10 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type MQTT struct {
|
type MQTT struct {
|
||||||
Servers []string `toml:"servers"`
|
Servers []string `toml:"servers"`
|
||||||
Protocol string `toml:"protocol"`
|
Protocol string `toml:"protocol"`
|
||||||
Username string `toml:"username"`
|
Username config.Secret `toml:"username"`
|
||||||
Password string `toml:"password"`
|
Password config.Secret `toml:"password"`
|
||||||
Database string
|
Database string
|
||||||
Timeout config.Duration `toml:"timeout"`
|
Timeout config.Duration `toml:"timeout"`
|
||||||
TopicPrefix string `toml:"topic_prefix" deprecated:"1.25.0;use 'topic' instead"`
|
TopicPrefix string `toml:"topic_prefix" deprecated:"1.25.0;use 'topic' instead"`
|
||||||
|
|
|
||||||
|
|
@ -40,13 +40,21 @@ func (m *mqttv311Client) Connect() error {
|
||||||
}
|
}
|
||||||
opts.SetTLSConfig(tlsCfg)
|
opts.SetTLSConfig(tlsCfg)
|
||||||
|
|
||||||
user := m.Username
|
if !m.Username.Empty() {
|
||||||
if user != "" {
|
user, err := m.Username.Get()
|
||||||
opts.SetUsername(user)
|
if err != nil {
|
||||||
|
return fmt.Errorf("getting username failed: %w", err)
|
||||||
|
}
|
||||||
|
opts.SetUsername(string(user))
|
||||||
|
config.ReleaseSecret(user)
|
||||||
}
|
}
|
||||||
password := m.Password
|
if !m.Password.Empty() {
|
||||||
if password != "" {
|
password, err := m.Password.Get()
|
||||||
opts.SetPassword(password)
|
if err != nil {
|
||||||
|
return fmt.Errorf("getting password failed: %w", err)
|
||||||
|
}
|
||||||
|
opts.SetPassword(string(password))
|
||||||
|
config.ReleaseSecret(password)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(m.Servers) == 0 {
|
if len(m.Servers) == 0 {
|
||||||
|
|
|
||||||
|
|
@ -29,9 +29,18 @@ func (m *mqttv5Client) Connect() error {
|
||||||
opts.ClientID = "Telegraf-Output-" + internal.RandomString(5)
|
opts.ClientID = "Telegraf-Output-" + internal.RandomString(5)
|
||||||
}
|
}
|
||||||
|
|
||||||
user := m.Username
|
user, err := m.Username.Get()
|
||||||
pass := m.Password
|
if err != nil {
|
||||||
opts.SetUsernamePassword(user, []byte(pass))
|
return fmt.Errorf("getting username failed: %w", err)
|
||||||
|
}
|
||||||
|
pass, err := m.Password.Get()
|
||||||
|
if err != nil {
|
||||||
|
config.ReleaseSecret(user)
|
||||||
|
return fmt.Errorf("getting password failed: %w", err)
|
||||||
|
}
|
||||||
|
opts.SetUsernamePassword(string(user), pass)
|
||||||
|
config.ReleaseSecret(user)
|
||||||
|
config.ReleaseSecret(pass)
|
||||||
|
|
||||||
tlsCfg, err := m.ClientConfig.TLSConfig()
|
tlsCfg, err := m.ClientConfig.TLSConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"github.com/nats-io/nats.go"
|
"github.com/nats-io/nats.go"
|
||||||
|
|
||||||
"github.com/influxdata/telegraf"
|
"github.com/influxdata/telegraf"
|
||||||
|
"github.com/influxdata/telegraf/config"
|
||||||
"github.com/influxdata/telegraf/plugins/common/tls"
|
"github.com/influxdata/telegraf/plugins/common/tls"
|
||||||
"github.com/influxdata/telegraf/plugins/outputs"
|
"github.com/influxdata/telegraf/plugins/outputs"
|
||||||
"github.com/influxdata/telegraf/plugins/serializers"
|
"github.com/influxdata/telegraf/plugins/serializers"
|
||||||
|
|
@ -18,13 +19,13 @@ import (
|
||||||
var sampleConfig string
|
var sampleConfig string
|
||||||
|
|
||||||
type NATS struct {
|
type NATS struct {
|
||||||
Servers []string `toml:"servers"`
|
Servers []string `toml:"servers"`
|
||||||
Secure bool `toml:"secure"`
|
Secure bool `toml:"secure"`
|
||||||
Name string `toml:"name"`
|
Name string `toml:"name"`
|
||||||
Username string `toml:"username"`
|
Username config.Secret `toml:"username"`
|
||||||
Password string `toml:"password"`
|
Password config.Secret `toml:"password"`
|
||||||
Credentials string `toml:"credentials"`
|
Credentials config.Secret `toml:"credentials"`
|
||||||
Subject string `toml:"subject"`
|
Subject string `toml:"subject"`
|
||||||
|
|
||||||
tls.ClientConfig
|
tls.ClientConfig
|
||||||
|
|
||||||
|
|
@ -50,12 +51,28 @@ func (n *NATS) Connect() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// override authentication, if any was specified
|
// override authentication, if any was specified
|
||||||
if n.Username != "" && n.Password != "" {
|
if !n.Username.Empty() && !n.Password.Empty() {
|
||||||
opts = append(opts, nats.UserInfo(n.Username, n.Password))
|
username, err := n.Username.Get()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("getting username failed: %w", err)
|
||||||
|
}
|
||||||
|
password, err := n.Password.Get()
|
||||||
|
if err != nil {
|
||||||
|
config.ReleaseSecret(username)
|
||||||
|
return fmt.Errorf("getting password failed: %w", err)
|
||||||
|
}
|
||||||
|
opts = append(opts, nats.UserInfo(string(username), string(password)))
|
||||||
|
config.ReleaseSecret(username)
|
||||||
|
config.ReleaseSecret(password)
|
||||||
}
|
}
|
||||||
|
|
||||||
if n.Credentials != "" {
|
if !n.Credentials.Empty() {
|
||||||
opts = append(opts, nats.UserCredentials(n.Credentials))
|
credentials, err := n.Credentials.Get()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("getting credentials failed: %w", err)
|
||||||
|
}
|
||||||
|
opts = append(opts, nats.UserCredentials(string(credentials)))
|
||||||
|
config.ReleaseSecret(credentials)
|
||||||
}
|
}
|
||||||
|
|
||||||
if n.Name != "" {
|
if n.Name != "" {
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import (
|
||||||
|
|
||||||
"github.com/go-redis/redis/v7"
|
"github.com/go-redis/redis/v7"
|
||||||
"github.com/influxdata/telegraf"
|
"github.com/influxdata/telegraf"
|
||||||
|
"github.com/influxdata/telegraf/config"
|
||||||
"github.com/influxdata/telegraf/plugins/common/tls"
|
"github.com/influxdata/telegraf/plugins/common/tls"
|
||||||
"github.com/influxdata/telegraf/plugins/outputs"
|
"github.com/influxdata/telegraf/plugins/outputs"
|
||||||
)
|
)
|
||||||
|
|
@ -17,8 +18,8 @@ var sampleConfig string
|
||||||
|
|
||||||
type RedisTimeSeries struct {
|
type RedisTimeSeries struct {
|
||||||
Address string `toml:"address"`
|
Address string `toml:"address"`
|
||||||
Username string `toml:"username"`
|
Username config.Secret `toml:"username"`
|
||||||
Password string `toml:"password"`
|
Password config.Secret `toml:"password"`
|
||||||
Database int `toml:"database"`
|
Database int `toml:"database"`
|
||||||
Log telegraf.Logger `toml:"-"`
|
Log telegraf.Logger `toml:"-"`
|
||||||
tls.ClientConfig
|
tls.ClientConfig
|
||||||
|
|
@ -29,10 +30,23 @@ func (r *RedisTimeSeries) Connect() error {
|
||||||
if r.Address == "" {
|
if r.Address == "" {
|
||||||
return errors.New("redis address must be specified")
|
return errors.New("redis address must be specified")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
username, err := r.Username.Get()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("getting username failed: %w", err)
|
||||||
|
}
|
||||||
|
defer config.ReleaseSecret(username)
|
||||||
|
|
||||||
|
password, err := r.Password.Get()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("getting password failed: %w", err)
|
||||||
|
}
|
||||||
|
defer config.ReleaseSecret(password)
|
||||||
|
|
||||||
r.client = redis.NewClient(&redis.Options{
|
r.client = redis.NewClient(&redis.Options{
|
||||||
Addr: r.Address,
|
Addr: r.Address,
|
||||||
Password: r.Password,
|
Username: string(username),
|
||||||
Username: r.Username,
|
Password: string(password),
|
||||||
DB: r.Database,
|
DB: r.Database,
|
||||||
})
|
})
|
||||||
return r.client.Ping().Err()
|
return r.client.Ping().Err()
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"github.com/signalfx/golib/v3/sfxclient"
|
"github.com/signalfx/golib/v3/sfxclient"
|
||||||
|
|
||||||
"github.com/influxdata/telegraf"
|
"github.com/influxdata/telegraf"
|
||||||
|
"github.com/influxdata/telegraf/config"
|
||||||
"github.com/influxdata/telegraf/plugins/outputs"
|
"github.com/influxdata/telegraf/plugins/outputs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -29,10 +30,10 @@ func init() {
|
||||||
|
|
||||||
// SignalFx plugin context
|
// SignalFx plugin context
|
||||||
type SignalFx struct {
|
type SignalFx struct {
|
||||||
AccessToken string `toml:"access_token"`
|
AccessToken config.Secret `toml:"access_token"`
|
||||||
SignalFxRealm string `toml:"signalfx_realm"`
|
SignalFxRealm string `toml:"signalfx_realm"`
|
||||||
IngestURL string `toml:"ingest_url"`
|
IngestURL string `toml:"ingest_url"`
|
||||||
IncludedEventNames []string `toml:"included_event_names"`
|
IncludedEventNames []string `toml:"included_event_names"`
|
||||||
|
|
||||||
Log telegraf.Logger `toml:"-"`
|
Log telegraf.Logger `toml:"-"`
|
||||||
|
|
||||||
|
|
@ -66,9 +67,6 @@ func GetMetricType(mtype telegraf.ValueType) (metricType datapoint.MetricType) {
|
||||||
func NewSignalFx() *SignalFx {
|
func NewSignalFx() *SignalFx {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
return &SignalFx{
|
return &SignalFx{
|
||||||
AccessToken: "",
|
|
||||||
SignalFxRealm: "",
|
|
||||||
IngestURL: "",
|
|
||||||
IncludedEventNames: []string{""},
|
IncludedEventNames: []string{""},
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
cancel: cancel,
|
cancel: cancel,
|
||||||
|
|
@ -83,7 +81,13 @@ func (*SignalFx) SampleConfig() string {
|
||||||
// Connect establishes a connection to SignalFx
|
// Connect establishes a connection to SignalFx
|
||||||
func (s *SignalFx) Connect() error {
|
func (s *SignalFx) Connect() error {
|
||||||
client := s.client.(*sfxclient.HTTPSink)
|
client := s.client.(*sfxclient.HTTPSink)
|
||||||
client.AuthToken = s.AccessToken
|
|
||||||
|
token, err := s.AccessToken.Get()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("getting token failed: %w", err)
|
||||||
|
}
|
||||||
|
client.AuthToken = string(token)
|
||||||
|
config.ReleaseSecret(token)
|
||||||
|
|
||||||
if s.IngestURL != "" {
|
if s.IngestURL != "" {
|
||||||
client.DatapointEndpoint = datapointEndpointForIngestURL(s.IngestURL)
|
client.DatapointEndpoint = datapointEndpointForIngestURL(s.IngestURL)
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,8 @@ var sampleConfig string
|
||||||
|
|
||||||
type STOMP struct {
|
type STOMP struct {
|
||||||
Host string `toml:"host"`
|
Host string `toml:"host"`
|
||||||
Username string `toml:"username"`
|
Username config.Secret `toml:"username"`
|
||||||
Password string `toml:"password"`
|
Password config.Secret `toml:"password"`
|
||||||
QueueName string `toml:"queueName"`
|
QueueName string `toml:"queueName"`
|
||||||
Log telegraf.Logger `toml:"-"`
|
Log telegraf.Logger `toml:"-"`
|
||||||
|
|
||||||
|
|
@ -55,11 +55,15 @@ func (q *STOMP) Connect() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
q.stomp, err = stomp.Connect(
|
authOption, err := q.getAuthOption()
|
||||||
q.conn,
|
if err != nil {
|
||||||
stomp.ConnOpt.HeartBeat(time.Duration(q.HeartBeatSend), time.Duration(q.HeartBeatRec)),
|
return err
|
||||||
stomp.ConnOpt.Login(q.Username, q.Password),
|
}
|
||||||
|
heartbeatOption := stomp.ConnOpt.HeartBeat(
|
||||||
|
time.Duration(q.HeartBeatSend),
|
||||||
|
time.Duration(q.HeartBeatRec),
|
||||||
)
|
)
|
||||||
|
q.stomp, err = stomp.Connect(q.conn, heartbeatOption, authOption)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -92,6 +96,20 @@ func (q *STOMP) Close() error {
|
||||||
return q.stomp.Disconnect()
|
return q.stomp.Disconnect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (q *STOMP) getAuthOption() (func(*stomp.Conn) error, error) {
|
||||||
|
username, err := q.Username.Get()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("getting username failed: %w", err)
|
||||||
|
}
|
||||||
|
defer config.ReleaseSecret(username)
|
||||||
|
password, err := q.Password.Get()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("getting password failed: %w", err)
|
||||||
|
}
|
||||||
|
defer config.ReleaseSecret(password)
|
||||||
|
return stomp.ConnOpt.Login(string(username), string(password)), nil
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
outputs.Add("stomp", func() telegraf.Output {
|
outputs.Add("stomp", func() telegraf.Output {
|
||||||
return &STOMP{
|
return &STOMP{
|
||||||
|
|
|
||||||
|
|
@ -39,11 +39,10 @@ func TestConnectAndWrite(t *testing.T) {
|
||||||
QueueName: "test_queue",
|
QueueName: "test_queue",
|
||||||
HeartBeatSend: 0,
|
HeartBeatSend: 0,
|
||||||
HeartBeatRec: 0,
|
HeartBeatRec: 0,
|
||||||
|
Log: testutil.Logger{},
|
||||||
serialize: s,
|
serialize: s,
|
||||||
}
|
}
|
||||||
err = st.Connect()
|
require.NoError(t, st.Connect())
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
err = st.Write(testutil.MockMetrics())
|
require.NoError(t, st.Write(testutil.MockMetrics()))
|
||||||
require.NoError(t, err)
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ const (
|
||||||
type Warp10 struct {
|
type Warp10 struct {
|
||||||
Prefix string `toml:"prefix"`
|
Prefix string `toml:"prefix"`
|
||||||
WarpURL string `toml:"warp_url"`
|
WarpURL string `toml:"warp_url"`
|
||||||
Token string `toml:"token"`
|
Token config.Secret `toml:"token"`
|
||||||
Timeout config.Duration `toml:"timeout"`
|
Timeout config.Duration `toml:"timeout"`
|
||||||
PrintErrorBody bool `toml:"print_error_body"`
|
PrintErrorBody bool `toml:"print_error_body"`
|
||||||
MaxStringErrorSize int `toml:"max_string_error_size"`
|
MaxStringErrorSize int `toml:"max_string_error_size"`
|
||||||
|
|
@ -125,8 +125,13 @@ func (w *Warp10) Write(metrics []telegraf.Metric) error {
|
||||||
return fmt.Errorf("unable to create new request '%s': %s", addr, err)
|
return fmt.Errorf("unable to create new request '%s': %s", addr, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
req.Header.Set("X-Warp10-Token", w.Token)
|
|
||||||
req.Header.Set("Content-Type", "text/plain")
|
req.Header.Set("Content-Type", "text/plain")
|
||||||
|
token, err := w.Token.Get()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("getting token failed: %w", err)
|
||||||
|
}
|
||||||
|
req.Header.Set("X-Warp10-Token", string(token))
|
||||||
|
config.ReleaseSecret(token)
|
||||||
|
|
||||||
resp, err := w.client.Do(req)
|
resp, err := w.client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package warp10
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/influxdata/telegraf/config"
|
||||||
"github.com/influxdata/telegraf/testutil"
|
"github.com/influxdata/telegraf/testutil"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
@ -16,7 +17,7 @@ func TestWriteWarp10(t *testing.T) {
|
||||||
w := Warp10{
|
w := Warp10{
|
||||||
Prefix: "unit.test",
|
Prefix: "unit.test",
|
||||||
WarpURL: "http://localhost:8090",
|
WarpURL: "http://localhost:8090",
|
||||||
Token: "WRITE",
|
Token: config.NewSecret([]byte("WRITE")),
|
||||||
}
|
}
|
||||||
|
|
||||||
payload := w.GenWarp10Payload(testutil.MockMetrics())
|
payload := w.GenWarp10Payload(testutil.MockMetrics())
|
||||||
|
|
@ -27,7 +28,7 @@ func TestWriteWarp10EncodedTags(t *testing.T) {
|
||||||
w := Warp10{
|
w := Warp10{
|
||||||
Prefix: "unit.test",
|
Prefix: "unit.test",
|
||||||
WarpURL: "http://localhost:8090",
|
WarpURL: "http://localhost:8090",
|
||||||
Token: "WRITE",
|
Token: config.NewSecret([]byte("WRITE")),
|
||||||
}
|
}
|
||||||
|
|
||||||
metrics := testutil.MockMetrics()
|
metrics := testutil.MockMetrics()
|
||||||
|
|
@ -43,7 +44,7 @@ func TestHandleWarp10Error(t *testing.T) {
|
||||||
w := Warp10{
|
w := Warp10{
|
||||||
Prefix: "unit.test",
|
Prefix: "unit.test",
|
||||||
WarpURL: "http://localhost:8090",
|
WarpURL: "http://localhost:8090",
|
||||||
Token: "WRITE",
|
Token: config.NewSecret([]byte("WRITE")),
|
||||||
}
|
}
|
||||||
tests := [...]*ErrorTest{
|
tests := [...]*ErrorTest{
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import (
|
||||||
wavefront "github.com/wavefronthq/wavefront-sdk-go/senders"
|
wavefront "github.com/wavefronthq/wavefront-sdk-go/senders"
|
||||||
|
|
||||||
"github.com/influxdata/telegraf"
|
"github.com/influxdata/telegraf"
|
||||||
|
"github.com/influxdata/telegraf/config"
|
||||||
"github.com/influxdata/telegraf/plugins/outputs"
|
"github.com/influxdata/telegraf/plugins/outputs"
|
||||||
serializer "github.com/influxdata/telegraf/plugins/serializers/wavefront"
|
serializer "github.com/influxdata/telegraf/plugins/serializers/wavefront"
|
||||||
)
|
)
|
||||||
|
|
@ -22,7 +23,7 @@ const maxTagLength = 254
|
||||||
|
|
||||||
type Wavefront struct {
|
type Wavefront struct {
|
||||||
URL string `toml:"url"`
|
URL string `toml:"url"`
|
||||||
Token string `toml:"token"`
|
Token config.Secret `toml:"token"`
|
||||||
Host string `toml:"host" deprecated:"2.4.0;use url instead"`
|
Host string `toml:"host" deprecated:"2.4.0;use url instead"`
|
||||||
Port int `toml:"port" deprecated:"2.4.0;use url instead"`
|
Port int `toml:"port" deprecated:"2.4.0;use url instead"`
|
||||||
Prefix string `toml:"prefix"`
|
Prefix string `toml:"prefix"`
|
||||||
|
|
@ -53,10 +54,20 @@ func (*Wavefront) SampleConfig() string {
|
||||||
return sampleConfig
|
return sampleConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
func senderURLFromURLAndToken(rawURL, token string) (string, error) {
|
func (w *Wavefront) senderURLFromURLAndToken() (string, error) {
|
||||||
newURL, err := url.Parse(rawURL)
|
newURL, err := url.Parse(w.URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("could not parse the provided Url: %s", rawURL)
|
return "", fmt.Errorf("could not parse the provided URL: %s", w.URL)
|
||||||
|
}
|
||||||
|
|
||||||
|
token := "DUMMY_TOKEN"
|
||||||
|
if !w.Token.Empty() {
|
||||||
|
b, err := w.Token.Get()
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("getting token failed: %w", err)
|
||||||
|
}
|
||||||
|
token = string(b)
|
||||||
|
config.ReleaseSecret(b)
|
||||||
}
|
}
|
||||||
newURL.User = url.User(token)
|
newURL.User = url.User(token)
|
||||||
|
|
||||||
|
|
@ -75,7 +86,7 @@ func (w *Wavefront) Connect() error {
|
||||||
var connectionURL string
|
var connectionURL string
|
||||||
if w.URL != "" {
|
if w.URL != "" {
|
||||||
w.Log.Debug("connecting over http/https using Url: %s", w.URL)
|
w.Log.Debug("connecting over http/https using Url: %s", w.URL)
|
||||||
connectionURLWithToken, err := senderURLFromURLAndToken(w.URL, w.Token)
|
connectionURLWithToken, err := w.senderURLFromURLAndToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -287,7 +298,6 @@ func (w *Wavefront) Close() error {
|
||||||
func init() {
|
func init() {
|
||||||
outputs.Add("wavefront", func() telegraf.Output {
|
outputs.Add("wavefront", func() telegraf.Output {
|
||||||
return &Wavefront{
|
return &Wavefront{
|
||||||
Token: "DUMMY_TOKEN",
|
|
||||||
MetricSeparator: ".",
|
MetricSeparator: ".",
|
||||||
ConvertPaths: true,
|
ConvertPaths: true,
|
||||||
ConvertBool: true,
|
ConvertBool: true,
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/influxdata/telegraf"
|
"github.com/influxdata/telegraf"
|
||||||
|
"github.com/influxdata/telegraf/config"
|
||||||
"github.com/influxdata/telegraf/metric"
|
"github.com/influxdata/telegraf/metric"
|
||||||
"github.com/influxdata/telegraf/plugins/outputs"
|
"github.com/influxdata/telegraf/plugins/outputs"
|
||||||
serializer "github.com/influxdata/telegraf/plugins/serializers/wavefront"
|
serializer "github.com/influxdata/telegraf/plugins/serializers/wavefront"
|
||||||
|
|
@ -369,10 +370,14 @@ func TestSenderURLFromHostAndPort(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSenderURLFromURLAndToken(t *testing.T) {
|
func TestSenderURLFromURLAndToken(t *testing.T) {
|
||||||
url, err := senderURLFromURLAndToken("https://surf.wavefront.com", "11111111-2222-3333-4444-555555555555")
|
w := &Wavefront{
|
||||||
require.Nil(t, err)
|
URL: "https://surf.wavefront.com",
|
||||||
require.Equal(t, "https://11111111-2222-3333-4444-555555555555@surf.wavefront.com",
|
Token: config.NewSecret([]byte("11111111-2222-3333-4444-555555555555")),
|
||||||
url)
|
}
|
||||||
|
|
||||||
|
url, err := w.senderURLFromURLAndToken()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, "https://11111111-2222-3333-4444-555555555555@surf.wavefront.com", url)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDefaults(t *testing.T) {
|
func TestDefaults(t *testing.T) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue