1
0
Fork 0
telegraf/plugins/outputs/mongodb/mongodb_test.go

438 lines
12 KiB
Go
Raw Permalink Normal View History

package mongodb
import (
"fmt"
"path/filepath"
"testing"
"time"
"github.com/docker/go-connections/nat"
"github.com/stretchr/testify/require"
"github.com/testcontainers/testcontainers-go/wait"
"github.com/influxdata/telegraf/config"
"github.com/influxdata/telegraf/plugins/common/tls"
"github.com/influxdata/telegraf/testutil"
)
func TestConnectAndWriteIntegrationNoAuth(t *testing.T) {
if testing.Short() {
t.Skip("Skipping integration test in short mode")
}
servicePort := "27017"
container := testutil.Container{
Image: "mongo",
ExposedPorts: []string{servicePort},
WaitingFor: wait.ForAll(
wait.NewHTTPStrategy("/").WithPort(nat.Port(servicePort)),
wait.ForLog("Waiting for connections"),
),
}
err := container.Start()
require.NoError(t, err, "failed to start container")
defer container.Terminate()
// Run test
plugin := &MongoDB{
Dsn: fmt.Sprintf("mongodb://%s:%s",
container.Address,
container.Ports[servicePort],
),
AuthenticationType: "NONE",
MetricDatabase: "telegraf_test",
MetricGranularity: "seconds",
}
// validate config
require.NoError(t, plugin.Init())
require.NoError(t, plugin.Connect())
require.NoError(t, plugin.Write(testutil.MockMetrics()))
require.NoError(t, plugin.Close())
}
func TestConnectAndWriteIntegrationSCRAMAuth(t *testing.T) {
if testing.Short() {
t.Skip("Skipping integration test in short mode")
}
initdb, err := filepath.Abs("testdata/auth_scram/setup.js")
require.NoError(t, err)
servicePort := "27017"
container := testutil.Container{
Image: "mongo",
ExposedPorts: []string{servicePort},
Files: map[string]string{
"/docker-entrypoint-initdb.d/setup.js": initdb,
},
WaitingFor: wait.ForAll(
wait.NewHTTPStrategy("/").WithPort(nat.Port(servicePort)),
wait.ForLog("Waiting for connections").WithOccurrence(2),
),
}
err = container.Start()
require.NoError(t, err, "failed to start container")
defer container.Terminate()
tests := []struct {
name string
plugin *MongoDB
connErrFunc func(t *testing.T, err error)
}{
{
name: "success with scram authentication",
plugin: &MongoDB{
Dsn: fmt.Sprintf("mongodb://%s:%s/admin",
container.Address, container.Ports[servicePort]),
AuthenticationType: "SCRAM",
Username: config.NewSecret([]byte("root")),
Password: config.NewSecret([]byte("changeme")),
MetricDatabase: "telegraf_test",
MetricGranularity: "seconds",
},
connErrFunc: func(t *testing.T, err error) {
require.NoError(t, err)
},
},
{
name: "fail with scram authentication bad password",
plugin: &MongoDB{
Dsn: fmt.Sprintf("mongodb://%s:%s/admin",
container.Address, container.Ports[servicePort]),
AuthenticationType: "SCRAM",
Username: config.NewSecret([]byte("root")),
Password: config.NewSecret([]byte("root")),
MetricDatabase: "telegraf_test",
MetricGranularity: "seconds",
ServerSelectTimeout: config.Duration(time.Duration(5) * time.Second),
},
connErrFunc: func(t *testing.T, err error) {
require.Error(t, err)
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// validate config
err := tt.plugin.Init()
require.NoError(t, err)
if err == nil {
// connect
err = tt.plugin.Connect()
tt.connErrFunc(t, err)
if err == nil {
// insert mock metrics
err = tt.plugin.Write(testutil.MockMetrics())
require.NoError(t, err)
// cleanup
err = tt.plugin.Close()
require.NoError(t, err)
}
}
})
}
}
func TestConnectAndWriteIntegrationX509Auth(t *testing.T) {
if testing.Short() {
t.Skip("Skipping integration test in short mode")
}
pki := testutil.NewPKI("../../../testutil/pki")
// bind mount files
initdb, err := filepath.Abs("testdata/auth_x509/setup.js")
require.NoError(t, err)
cacert, err := filepath.Abs(pki.CACertPath())
require.NoError(t, err)
serverpem, err := filepath.Abs(pki.ServerCertAndKeyPath())
require.NoError(t, err)
servicePort := "27017"
container := testutil.Container{
Image: "mongo",
ExposedPorts: []string{servicePort},
Files: map[string]string{
"/docker-entrypoint-initdb.d/setup.js": initdb,
"/cacert.pem": cacert,
"/server.pem": serverpem,
},
Entrypoint: []string{
"docker-entrypoint.sh",
"--auth", "--setParameter", "authenticationMechanisms=MONGODB-X509",
"--tlsMode", "preferTLS",
"--tlsCAFile", "/cacert.pem",
"--tlsCertificateKeyFile", "/server.pem",
},
WaitingFor: wait.ForAll(
wait.NewHTTPStrategy("/").WithPort(nat.Port(servicePort)),
wait.ForLog("Waiting for connections").WithOccurrence(2),
),
}
err = container.Start()
require.NoError(t, err, "failed to start container")
defer container.Terminate()
tests := []struct {
name string
plugin *MongoDB
connErrFunc func(t *testing.T, err error)
}{
{
name: "success with x509 authentication",
plugin: &MongoDB{
Dsn: fmt.Sprintf("mongodb://%s:%s",
container.Address, container.Ports[servicePort]),
AuthenticationType: "X509",
MetricDatabase: "telegraf_test",
MetricGranularity: "seconds",
ServerSelectTimeout: config.Duration(time.Duration(5) * time.Second),
TTL: config.Duration(time.Duration(5) * time.Minute),
ClientConfig: tls.ClientConfig{
TLSCA: pki.CACertPath(),
TLSKey: pki.ClientCertAndKeyPath(),
InsecureSkipVerify: false,
},
},
connErrFunc: func(t *testing.T, err error) {
require.NoError(t, err)
},
},
{
name: "success with x509 authentication using encrypted key file",
plugin: &MongoDB{
Dsn: fmt.Sprintf("mongodb://%s:%s",
container.Address, container.Ports[servicePort]),
AuthenticationType: "X509",
MetricDatabase: "telegraf_test",
MetricGranularity: "seconds",
ServerSelectTimeout: config.Duration(time.Duration(5) * time.Second),
TTL: config.Duration(time.Duration(5) * time.Minute),
ClientConfig: tls.ClientConfig{
TLSCA: pki.CACertPath(),
TLSKey: pki.ClientCertAndEncKeyPath(),
TLSKeyPwd: "changeme",
InsecureSkipVerify: false,
},
},
connErrFunc: func(t *testing.T, err error) {
require.NoError(t, err)
},
},
{
name: "success with x509 authentication missing ca and using insceure tls",
plugin: &MongoDB{
Dsn: fmt.Sprintf("mongodb://%s:%s",
container.Address, container.Ports[servicePort]),
AuthenticationType: "X509",
MetricDatabase: "telegraf_test",
MetricGranularity: "seconds",
ServerSelectTimeout: config.Duration(time.Duration(5) * time.Second),
TTL: config.Duration(time.Duration(5) * time.Minute),
ClientConfig: tls.ClientConfig{
TLSKey: pki.ClientCertAndKeyPath(),
InsecureSkipVerify: true,
},
},
connErrFunc: func(t *testing.T, err error) {
require.NoError(t, err)
},
},
{
name: "fail with x509 authentication missing ca",
plugin: &MongoDB{
Dsn: fmt.Sprintf("mongodb://%s:%s",
container.Address, container.Ports[servicePort]),
AuthenticationType: "X509",
MetricDatabase: "telegraf_test",
MetricGranularity: "seconds",
ServerSelectTimeout: config.Duration(time.Duration(5) * time.Second),
TTL: config.Duration(time.Duration(5) * time.Minute),
ClientConfig: tls.ClientConfig{
TLSKey: pki.ClientCertAndKeyPath(),
InsecureSkipVerify: false,
},
},
connErrFunc: func(t *testing.T, err error) {
require.Error(t, err)
},
},
{
name: "fail with x509 authentication using encrypted key file",
plugin: &MongoDB{
Dsn: fmt.Sprintf("mongodb://%s:%s",
container.Address, container.Ports[servicePort]),
AuthenticationType: "X509",
MetricDatabase: "telegraf_test",
MetricGranularity: "seconds",
ServerSelectTimeout: config.Duration(time.Duration(5) * time.Second),
TTL: config.Duration(time.Duration(5) * time.Minute),
ClientConfig: tls.ClientConfig{
TLSCA: pki.CACertPath(),
TLSKey: pki.ClientCertAndEncKeyPath(),
TLSKeyPwd: "badpassword",
InsecureSkipVerify: false,
},
},
connErrFunc: func(t *testing.T, err error) {
require.Error(t, err)
},
},
{
name: "fail with x509 authentication using invalid ca",
plugin: &MongoDB{
Dsn: fmt.Sprintf("mongodb://%s:%s",
container.Address, container.Ports[servicePort]),
AuthenticationType: "X509",
MetricDatabase: "telegraf_test",
MetricGranularity: "seconds",
ServerSelectTimeout: config.Duration(time.Duration(5) * time.Second),
TTL: config.Duration(time.Duration(5) * time.Minute),
ClientConfig: tls.ClientConfig{
TLSCA: pki.ClientCertAndKeyPath(),
TLSKey: pki.ClientCertAndKeyPath(),
InsecureSkipVerify: false,
},
},
connErrFunc: func(t *testing.T, err error) {
require.Error(t, err)
},
},
{
name: "fail with x509 authentication using invalid key",
plugin: &MongoDB{
Dsn: fmt.Sprintf("mongodb://%s:%s",
container.Address, container.Ports[servicePort]),
AuthenticationType: "X509",
MetricDatabase: "telegraf_test",
MetricGranularity: "seconds",
ServerSelectTimeout: config.Duration(time.Duration(5) * time.Second),
TTL: config.Duration(time.Duration(5) * time.Minute),
ClientConfig: tls.ClientConfig{
TLSCA: pki.CACertPath(),
TLSKey: pki.CACertPath(),
InsecureSkipVerify: false,
},
},
connErrFunc: func(t *testing.T, err error) {
require.Error(t, err)
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// validate config
err := tt.plugin.Init()
require.NoError(t, err)
if err == nil {
// connect
err = tt.plugin.Connect()
tt.connErrFunc(t, err)
if err == nil {
// insert mock metrics
err = tt.plugin.Write(testutil.MockMetrics())
require.NoError(t, err)
// cleanup
err = tt.plugin.Close()
require.NoError(t, err)
}
}
})
}
}
func TestConfiguration(t *testing.T) {
tests := []struct {
name string
plugin *MongoDB
errFunc func(t *testing.T, err error)
}{
{
name: "fail with invalid connection string",
plugin: &MongoDB{
Dsn: "asdf1234",
AuthenticationType: "NONE",
MetricDatabase: "telegraf_test",
MetricGranularity: "seconds",
TTL: config.Duration(time.Duration(5) * time.Minute),
},
},
{
name: "fail with invalid metric granularity",
plugin: &MongoDB{
Dsn: "mongodb://localhost:27017",
AuthenticationType: "NONE",
MetricDatabase: "telegraf_test",
MetricGranularity: "somerandomgranularitythatdoesntwork",
},
},
{
name: "fail with scram authentication missing username field",
plugin: &MongoDB{
Dsn: "mongodb://localhost:27017",
AuthenticationType: "SCRAM",
Password: config.NewSecret([]byte("somerandompasswordthatwontwork")),
MetricDatabase: "telegraf_test",
MetricGranularity: "seconds",
},
},
{
name: "fail with scram authentication missing password field",
plugin: &MongoDB{
Dsn: "mongodb://localhost:27017",
AuthenticationType: "SCRAM",
Username: config.NewSecret([]byte("somerandomusernamethatwontwork")),
MetricDatabase: "telegraf_test",
MetricGranularity: "seconds",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// validate config
err := tt.plugin.Init()
require.Error(t, err)
})
}
tests = []struct {
name string
plugin *MongoDB
errFunc func(t *testing.T, err error)
}{
{
name: "success init with missing metric database",
plugin: &MongoDB{
Dsn: "mongodb://localhost:27017",
AuthenticationType: "NONE",
MetricGranularity: "seconds",
},
},
{
name: "success init missing metric granularity",
plugin: &MongoDB{
Dsn: "mongodb://localhost:27017",
AuthenticationType: "NONE",
MetricDatabase: "telegraf_test",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// validate config
err := tt.plugin.Init()
require.NoError(t, err)
})
}
}