Files
teleport/lib/services/database_test.go
T

1547 lines
47 KiB
Go

/*
Copyright 2021 Gravitational, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package services
import (
"bufio"
"fmt"
"strings"
"testing"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/mysql/armmysql"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/redis/armredis/v2"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/redisenterprise/armredisenterprise"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/elasticache"
"github.com/aws/aws-sdk-go/service/memorydb"
"github.com/aws/aws-sdk-go/service/rds"
"github.com/aws/aws-sdk-go/service/redshift"
"github.com/google/uuid"
"github.com/stretchr/testify/require"
"github.com/gravitational/teleport/api/types"
awsutils "github.com/gravitational/teleport/api/utils/aws"
azureutils "github.com/gravitational/teleport/api/utils/azure"
"github.com/gravitational/teleport/lib/cloud/azure"
"github.com/gravitational/teleport/lib/defaults"
"github.com/gravitational/teleport/lib/fixtures"
"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/trace"
)
// TestDatabaseUnmarshal verifies a database resource can be unmarshaled.
func TestDatabaseUnmarshal(t *testing.T) {
expected, err := types.NewDatabaseV3(types.Metadata{
Name: "test-database",
Description: "Test description",
Labels: map[string]string{"env": "dev"},
}, types.DatabaseSpecV3{
Protocol: defaults.ProtocolPostgres,
URI: "localhost:5432",
CACert: fixtures.TLSCACertPEM,
})
require.NoError(t, err)
data, err := utils.ToJSON([]byte(fmt.Sprintf(databaseYAML, indent(fixtures.TLSCACertPEM, 4))))
require.NoError(t, err)
actual, err := UnmarshalDatabase(data)
require.NoError(t, err)
require.Equal(t, expected, actual)
}
// TestDatabaseMarshal verifies a marshaled database resource can be unmarshaled back.
func TestDatabaseMarshal(t *testing.T) {
expected, err := types.NewDatabaseV3(types.Metadata{
Name: "test-database",
Description: "Test description",
Labels: map[string]string{"env": "dev"},
}, types.DatabaseSpecV3{
Protocol: defaults.ProtocolPostgres,
URI: "localhost:5432",
CACert: fixtures.TLSCACertPEM,
})
require.NoError(t, err)
data, err := MarshalDatabase(expected)
require.NoError(t, err)
actual, err := UnmarshalDatabase(data)
require.NoError(t, err)
require.Equal(t, expected, actual)
}
// indent returns the string where each line is indented by the specified
// number of spaces.
func indent(s string, spaces int) string {
var lines []string
scanner := bufio.NewScanner(strings.NewReader(s))
for scanner.Scan() {
lines = append(lines, fmt.Sprintf("%v%v", strings.Repeat(" ", spaces), scanner.Text()))
}
return strings.Join(lines, "\n")
}
var databaseYAML = `kind: db
version: v3
metadata:
name: test-database
description: "Test description"
labels:
env: dev
spec:
protocol: "postgres"
uri: "localhost:5432"
ca_cert: |
%v`
// TestDatabaseFromAzureDBServer tests converting an Azure DB Server to a database resource.
func TestDatabaseFromAzureDBServer(t *testing.T) {
subscription := "sub1"
resourceGroup := "defaultRG"
resourceType := "Microsoft.DBforMySQL/servers"
name := "testdb"
id := fmt.Sprintf("/subscriptions/%v/resourceGroups/%v/providers/%v/%v",
subscription,
resourceGroup,
resourceType,
name,
)
server := azure.DBServer{
ID: id,
Location: "eastus",
Name: name,
Port: "3306",
Properties: azure.ServerProperties{
FullyQualifiedDomainName: name + ".mysql" + azureutils.DatabaseEndpointSuffix,
UserVisibleState: string(armmysql.ServerStateReady),
Version: string(armmysql.ServerVersionFive7),
},
Protocol: defaults.ProtocolMySQL,
Tags: map[string]string{
"foo": "bar",
},
}
expected, err := types.NewDatabaseV3(types.Metadata{
Name: "testdb",
Description: "Azure MySQL server in eastus",
Labels: map[string]string{
types.OriginLabel: types.OriginCloud,
labelRegion: "eastus",
labelEngine: "Microsoft.DBforMySQL/servers",
labelEngineVersion: "5.7",
labelResourceGroup: "defaultRG",
labelSubscriptionID: "sub1",
"foo": "bar",
},
}, types.DatabaseSpecV3{
Protocol: defaults.ProtocolMySQL,
URI: "testdb.mysql.database.azure.com:3306",
Azure: types.Azure{
Name: "testdb",
ResourceID: id,
},
})
require.NoError(t, err)
actual, err := NewDatabaseFromAzureServer(&server)
require.NoError(t, err)
require.Equal(t, expected, actual)
}
func TestDatabaseFromAzureRedis(t *testing.T) {
subscription := "test-sub"
name := "test-azure-redis"
group := "test-group"
region := "eastus"
id := fmt.Sprintf("/subscriptions/%v/resourceGroups/%v/providers/Microsoft.Cache/Redis/%v", subscription, group, name)
resourceInfo := &armredis.ResourceInfo{
Name: to.Ptr(name),
ID: to.Ptr(id),
Location: to.Ptr(region),
Tags: map[string]*string{
"foo": to.Ptr("bar"),
},
Properties: &armredis.Properties{
HostName: to.Ptr(fmt.Sprintf("%v.redis.cache.windows.net", name)),
SSLPort: to.Ptr(int32(6380)),
ProvisioningState: to.Ptr(armredis.ProvisioningStateSucceeded),
RedisVersion: to.Ptr("6.0"),
},
}
expected, err := types.NewDatabaseV3(types.Metadata{
Name: name,
Description: "Azure Redis server in eastus",
Labels: map[string]string{
types.OriginLabel: types.OriginCloud,
labelRegion: region,
labelEngine: "Microsoft.Cache/Redis",
labelEngineVersion: "6.0",
labelResourceGroup: group,
labelSubscriptionID: subscription,
"foo": "bar",
},
}, types.DatabaseSpecV3{
Protocol: defaults.ProtocolRedis,
URI: "test-azure-redis.redis.cache.windows.net:6380",
Azure: types.Azure{
Name: "test-azure-redis",
ResourceID: id,
},
})
require.NoError(t, err)
actual, err := NewDatabaseFromAzureRedis(resourceInfo)
require.NoError(t, err)
require.Equal(t, expected, actual)
}
func TestDatabaseFromAzureRedisEnterprise(t *testing.T) {
subscription := "test-sub"
name := "test-azure-redis"
group := "test-group"
region := "eastus"
clusterID := fmt.Sprintf("/subscriptions/%v/resourceGroups/%v/providers/Microsoft.Cache/redisEnterprise/%v", subscription, group, name)
databaseID := fmt.Sprintf("%v/databases/default", clusterID)
armCluster := &armredisenterprise.Cluster{
Name: to.Ptr(name),
ID: to.Ptr(clusterID),
Location: to.Ptr(region),
Tags: map[string]*string{
"foo": to.Ptr("bar"),
},
Properties: &armredisenterprise.ClusterProperties{
HostName: to.Ptr(fmt.Sprintf("%v.%v.redisenterprise.cache.azure.net", name, region)),
RedisVersion: to.Ptr("6.0"),
},
}
armDatabase := &armredisenterprise.Database{
Name: to.Ptr("default"),
ID: to.Ptr(databaseID),
Properties: &armredisenterprise.DatabaseProperties{
ProvisioningState: to.Ptr(armredisenterprise.ProvisioningStateSucceeded),
Port: to.Ptr(int32(10000)),
ClusteringPolicy: to.Ptr(armredisenterprise.ClusteringPolicyOSSCluster),
ClientProtocol: to.Ptr(armredisenterprise.ProtocolEncrypted),
},
}
expected, err := types.NewDatabaseV3(types.Metadata{
Name: name,
Description: "Azure Redis Enterprise server in eastus",
Labels: map[string]string{
types.OriginLabel: types.OriginCloud,
labelRegion: region,
labelEngine: "Microsoft.Cache/redisEnterprise",
labelEngineVersion: "6.0",
labelResourceGroup: group,
labelSubscriptionID: subscription,
labelEndpointType: "OSSCluster",
"foo": "bar",
},
}, types.DatabaseSpecV3{
Protocol: defaults.ProtocolRedis,
URI: "test-azure-redis.eastus.redisenterprise.cache.azure.net:10000",
Azure: types.Azure{
Name: "test-azure-redis",
ResourceID: databaseID,
Redis: types.AzureRedis{
ClusteringPolicy: "OSSCluster",
},
},
})
require.NoError(t, err)
actual, err := NewDatabaseFromAzureRedisEnterprise(armCluster, armDatabase)
require.NoError(t, err)
require.Equal(t, expected, actual)
}
// TestDatabaseFromRDSInstance tests converting an RDS instance to a database resource.
func TestDatabaseFromRDSInstance(t *testing.T) {
instance := &rds.DBInstance{
DBInstanceArn: aws.String("arn:aws:rds:us-west-1:1234567890:db:instance-1"),
DBInstanceIdentifier: aws.String("instance-1"),
DBClusterIdentifier: aws.String("cluster-1"),
DbiResourceId: aws.String("resource-1"),
IAMDatabaseAuthenticationEnabled: aws.Bool(true),
Engine: aws.String(RDSEnginePostgres),
EngineVersion: aws.String("13.0"),
Endpoint: &rds.Endpoint{
Address: aws.String("localhost"),
Port: aws.Int64(5432),
},
TagList: []*rds.Tag{{
Key: aws.String("key"),
Value: aws.String("val"),
}},
}
expected, err := types.NewDatabaseV3(types.Metadata{
Name: "instance-1",
Description: "RDS instance in us-west-1",
Labels: map[string]string{
types.OriginLabel: types.OriginCloud,
labelAccountID: "1234567890",
labelRegion: "us-west-1",
labelEngine: RDSEnginePostgres,
labelEngineVersion: "13.0",
labelEndpointType: "instance",
"key": "val",
},
}, types.DatabaseSpecV3{
Protocol: defaults.ProtocolPostgres,
URI: "localhost:5432",
AWS: types.AWS{
AccountID: "1234567890",
Region: "us-west-1",
RDS: types.RDS{
InstanceID: "instance-1",
ClusterID: "cluster-1",
ResourceID: "resource-1",
IAMAuth: true,
},
},
})
require.NoError(t, err)
actual, err := NewDatabaseFromRDSInstance(instance)
require.NoError(t, err)
require.Equal(t, expected, actual)
}
// TestDatabaseFromRDSInstance tests converting an RDS instance to a database resource.
func TestDatabaseFromRDSInstanceNameOverride(t *testing.T) {
instance := &rds.DBInstance{
DBInstanceArn: aws.String("arn:aws:rds:us-west-1:1234567890:db:instance-1"),
DBInstanceIdentifier: aws.String("instance-1"),
DBClusterIdentifier: aws.String("cluster-1"),
DbiResourceId: aws.String("resource-1"),
IAMDatabaseAuthenticationEnabled: aws.Bool(true),
Engine: aws.String(RDSEnginePostgres),
EngineVersion: aws.String("13.0"),
Endpoint: &rds.Endpoint{
Address: aws.String("localhost"),
Port: aws.Int64(5432),
},
TagList: []*rds.Tag{
{Key: aws.String("key"), Value: aws.String("val")},
{Key: aws.String(labelTeleportDBName), Value: aws.String("override-1")},
},
}
expected, err := types.NewDatabaseV3(types.Metadata{
Name: "override-1",
Description: "RDS instance in us-west-1",
Labels: map[string]string{
types.OriginLabel: types.OriginCloud,
labelAccountID: "1234567890",
labelRegion: "us-west-1",
labelEngine: RDSEnginePostgres,
labelEngineVersion: "13.0",
labelEndpointType: "instance",
labelTeleportDBName: "override-1",
"key": "val",
},
}, types.DatabaseSpecV3{
Protocol: defaults.ProtocolPostgres,
URI: "localhost:5432",
AWS: types.AWS{
AccountID: "1234567890",
Region: "us-west-1",
RDS: types.RDS{
InstanceID: "instance-1",
ClusterID: "cluster-1",
ResourceID: "resource-1",
IAMAuth: true,
},
},
})
require.NoError(t, err)
actual, err := NewDatabaseFromRDSInstance(instance)
require.NoError(t, err)
require.Equal(t, expected, actual)
}
// TestDatabaseFromRDSCluster tests converting an RDS cluster to a database resource.
func TestDatabaseFromRDSCluster(t *testing.T) {
cluster := &rds.DBCluster{
DBClusterArn: aws.String("arn:aws:rds:us-east-1:1234567890:cluster:cluster-1"),
DBClusterIdentifier: aws.String("cluster-1"),
DbClusterResourceId: aws.String("resource-1"),
IAMDatabaseAuthenticationEnabled: aws.Bool(true),
Engine: aws.String(RDSEngineAuroraMySQL),
EngineVersion: aws.String("8.0.0"),
Endpoint: aws.String("localhost"),
ReaderEndpoint: aws.String("reader.host"),
Port: aws.Int64(3306),
CustomEndpoints: []*string{
aws.String("myendpoint1.cluster-custom-example.us-east-1.rds.amazonaws.com"),
aws.String("myendpoint2.cluster-custom-example.us-east-1.rds.amazonaws.com"),
},
TagList: []*rds.Tag{{
Key: aws.String("key"),
Value: aws.String("val"),
}},
}
expectedAWS := types.AWS{
AccountID: "1234567890",
Region: "us-east-1",
RDS: types.RDS{
ClusterID: "cluster-1",
ResourceID: "resource-1",
IAMAuth: true,
},
}
t.Run("primary", func(t *testing.T) {
expected, err := types.NewDatabaseV3(types.Metadata{
Name: "cluster-1",
Description: "Aurora cluster in us-east-1",
Labels: map[string]string{
types.OriginLabel: types.OriginCloud,
labelAccountID: "1234567890",
labelRegion: "us-east-1",
labelEngine: RDSEngineAuroraMySQL,
labelEngineVersion: "8.0.0",
labelEndpointType: "primary",
"key": "val",
},
}, types.DatabaseSpecV3{
Protocol: defaults.ProtocolMySQL,
URI: "localhost:3306",
AWS: expectedAWS,
})
require.NoError(t, err)
actual, err := NewDatabaseFromRDSCluster(cluster)
require.NoError(t, err)
require.Equal(t, expected, actual)
})
t.Run("reader", func(t *testing.T) {
expected, err := types.NewDatabaseV3(types.Metadata{
Name: "cluster-1-reader",
Description: "Aurora cluster in us-east-1 (reader endpoint)",
Labels: map[string]string{
types.OriginLabel: types.OriginCloud,
labelAccountID: "1234567890",
labelRegion: "us-east-1",
labelEngine: RDSEngineAuroraMySQL,
labelEngineVersion: "8.0.0",
labelEndpointType: "reader",
"key": "val",
},
}, types.DatabaseSpecV3{
Protocol: defaults.ProtocolMySQL,
URI: "reader.host:3306",
AWS: expectedAWS,
})
require.NoError(t, err)
actual, err := NewDatabaseFromRDSClusterReaderEndpoint(cluster)
require.NoError(t, err)
require.Equal(t, expected, actual)
})
t.Run("custom endpoints", func(t *testing.T) {
expectedLabels := map[string]string{
types.OriginLabel: types.OriginCloud,
labelAccountID: "1234567890",
labelRegion: "us-east-1",
labelEngine: RDSEngineAuroraMySQL,
labelEngineVersion: "8.0.0",
labelEndpointType: "custom",
"key": "val",
}
expectedMyEndpoint1, err := types.NewDatabaseV3(types.Metadata{
Name: "cluster-1-custom-myendpoint1",
Description: "Aurora cluster in us-east-1 (custom endpoint)",
Labels: expectedLabels,
}, types.DatabaseSpecV3{
Protocol: defaults.ProtocolMySQL,
URI: "myendpoint1.cluster-custom-example.us-east-1.rds.amazonaws.com:3306",
AWS: expectedAWS,
TLS: types.DatabaseTLS{
ServerName: "localhost",
},
})
require.NoError(t, err)
expectedMyEndpoint2, err := types.NewDatabaseV3(types.Metadata{
Name: "cluster-1-custom-myendpoint2",
Description: "Aurora cluster in us-east-1 (custom endpoint)",
Labels: expectedLabels,
}, types.DatabaseSpecV3{
Protocol: defaults.ProtocolMySQL,
URI: "myendpoint2.cluster-custom-example.us-east-1.rds.amazonaws.com:3306",
AWS: expectedAWS,
TLS: types.DatabaseTLS{
ServerName: "localhost",
},
})
require.NoError(t, err)
databases, err := NewDatabasesFromRDSClusterCustomEndpoints(cluster)
require.NoError(t, err)
require.Equal(t, types.Databases{expectedMyEndpoint1, expectedMyEndpoint2}, databases)
})
t.Run("bad custom endpoints ", func(t *testing.T) {
badCluster := *cluster
badCluster.CustomEndpoints = []*string{
aws.String("badendpoint1"),
aws.String("badendpoint2"),
}
_, err := NewDatabasesFromRDSClusterCustomEndpoints(&badCluster)
require.Error(t, err)
})
}
// TestDatabaseFromRDSClusterNameOverride tests converting an RDS cluster to a database resource with overridden name.
func TestDatabaseFromRDSClusterNameOverride(t *testing.T) {
cluster := &rds.DBCluster{
DBClusterArn: aws.String("arn:aws:rds:us-east-1:1234567890:cluster:cluster-1"),
DBClusterIdentifier: aws.String("cluster-1"),
DbClusterResourceId: aws.String("resource-1"),
IAMDatabaseAuthenticationEnabled: aws.Bool(true),
Engine: aws.String(RDSEngineAuroraMySQL),
EngineVersion: aws.String("8.0.0"),
Endpoint: aws.String("localhost"),
ReaderEndpoint: aws.String("reader.host"),
Port: aws.Int64(3306),
CustomEndpoints: []*string{
aws.String("myendpoint1.cluster-custom-example.us-east-1.rds.amazonaws.com"),
aws.String("myendpoint2.cluster-custom-example.us-east-1.rds.amazonaws.com"),
},
TagList: []*rds.Tag{
{Key: aws.String("key"), Value: aws.String("val")},
{Key: aws.String(labelTeleportDBName), Value: aws.String("mycluster-2")},
},
}
expectedAWS := types.AWS{
AccountID: "1234567890",
Region: "us-east-1",
RDS: types.RDS{
ClusterID: "cluster-1",
ResourceID: "resource-1",
IAMAuth: true,
},
}
t.Run("primary", func(t *testing.T) {
expected, err := types.NewDatabaseV3(types.Metadata{
Name: "mycluster-2",
Description: "Aurora cluster in us-east-1",
Labels: map[string]string{
types.OriginLabel: types.OriginCloud,
labelAccountID: "1234567890",
labelRegion: "us-east-1",
labelEngine: RDSEngineAuroraMySQL,
labelEngineVersion: "8.0.0",
labelEndpointType: "primary",
labelTeleportDBName: "mycluster-2",
"key": "val",
},
}, types.DatabaseSpecV3{
Protocol: defaults.ProtocolMySQL,
URI: "localhost:3306",
AWS: expectedAWS,
})
require.NoError(t, err)
actual, err := NewDatabaseFromRDSCluster(cluster)
require.NoError(t, err)
require.Equal(t, expected, actual)
})
t.Run("reader", func(t *testing.T) {
expected, err := types.NewDatabaseV3(types.Metadata{
Name: "mycluster-2-reader",
Description: "Aurora cluster in us-east-1 (reader endpoint)",
Labels: map[string]string{
types.OriginLabel: types.OriginCloud,
labelAccountID: "1234567890",
labelRegion: "us-east-1",
labelEngine: RDSEngineAuroraMySQL,
labelEngineVersion: "8.0.0",
labelEndpointType: "reader",
labelTeleportDBName: "mycluster-2",
"key": "val",
},
}, types.DatabaseSpecV3{
Protocol: defaults.ProtocolMySQL,
URI: "reader.host:3306",
AWS: expectedAWS,
})
require.NoError(t, err)
actual, err := NewDatabaseFromRDSClusterReaderEndpoint(cluster)
require.NoError(t, err)
require.Equal(t, expected, actual)
})
t.Run("custom endpoints", func(t *testing.T) {
expectedLabels := map[string]string{
types.OriginLabel: types.OriginCloud,
labelAccountID: "1234567890",
labelRegion: "us-east-1",
labelEngine: RDSEngineAuroraMySQL,
labelEngineVersion: "8.0.0",
labelEndpointType: "custom",
labelTeleportDBName: "mycluster-2",
"key": "val",
}
expectedMyEndpoint1, err := types.NewDatabaseV3(types.Metadata{
Name: "mycluster-2-custom-myendpoint1",
Description: "Aurora cluster in us-east-1 (custom endpoint)",
Labels: expectedLabels,
}, types.DatabaseSpecV3{
Protocol: defaults.ProtocolMySQL,
URI: "myendpoint1.cluster-custom-example.us-east-1.rds.amazonaws.com:3306",
AWS: expectedAWS,
TLS: types.DatabaseTLS{
ServerName: "localhost",
},
})
require.NoError(t, err)
expectedMyEndpoint2, err := types.NewDatabaseV3(types.Metadata{
Name: "mycluster-2-custom-myendpoint2",
Description: "Aurora cluster in us-east-1 (custom endpoint)",
Labels: expectedLabels,
}, types.DatabaseSpecV3{
Protocol: defaults.ProtocolMySQL,
URI: "myendpoint2.cluster-custom-example.us-east-1.rds.amazonaws.com:3306",
AWS: expectedAWS,
TLS: types.DatabaseTLS{
ServerName: "localhost",
},
})
require.NoError(t, err)
databases, err := NewDatabasesFromRDSClusterCustomEndpoints(cluster)
require.NoError(t, err)
require.Equal(t, types.Databases{expectedMyEndpoint1, expectedMyEndpoint2}, databases)
})
t.Run("bad custom endpoints ", func(t *testing.T) {
badCluster := *cluster
badCluster.CustomEndpoints = []*string{
aws.String("badendpoint1"),
aws.String("badendpoint2"),
}
_, err := NewDatabasesFromRDSClusterCustomEndpoints(&badCluster)
require.Error(t, err)
})
}
func TestAuroraMySQLVersion(t *testing.T) {
tests := []struct {
engineVersion string
expectedMySQLVersion string
}{
{
engineVersion: "5.6.10a",
expectedMySQLVersion: "5.6.10a",
},
{
engineVersion: "5.6.mysql_aurora.1.22.1",
expectedMySQLVersion: "1.22.1",
},
{
engineVersion: "5.6.mysql_aurora.1.22.1.3",
expectedMySQLVersion: "1.22.1.3",
},
}
for _, test := range tests {
t.Run(test.engineVersion, func(t *testing.T) {
require.Equal(t, test.expectedMySQLVersion, auroraMySQLVersion(&rds.DBCluster{EngineVersion: aws.String(test.engineVersion)}))
})
}
}
func TestIsRDSClusterSupported(t *testing.T) {
tests := []struct {
name string
engineMode string
engineVersion string
isSupported bool
}{
{
name: "provisioned",
engineMode: RDSEngineModeProvisioned,
engineVersion: "5.6.mysql_aurora.1.22.0",
isSupported: true,
},
{
name: "serverless",
engineMode: RDSEngineModeServerless,
engineVersion: "5.6.mysql_aurora.1.22.0",
isSupported: false,
},
{
name: "parallel query supported",
engineMode: RDSEngineModeParallelQuery,
engineVersion: "5.6.mysql_aurora.1.22.0",
isSupported: true,
},
{
name: "parallel query unsupported",
engineMode: RDSEngineModeParallelQuery,
engineVersion: "5.6.mysql_aurora.1.19.6",
isSupported: false,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
cluster := &rds.DBCluster{
DBClusterArn: aws.String("arn:aws:rds:us-east-1:1234567890:cluster:test"),
DBClusterIdentifier: aws.String(test.name),
DbClusterResourceId: aws.String(uuid.New().String()),
Engine: aws.String(RDSEngineAuroraMySQL),
EngineMode: aws.String(test.engineMode),
EngineVersion: aws.String(test.engineVersion),
}
got, want := IsRDSClusterSupported(cluster), test.isSupported
require.Equal(t, want, got, "IsRDSClusterSupported = %v, want = %v", got, want)
})
}
}
func TestIsRDSInstanceSupported(t *testing.T) {
tests := []struct {
name string
engine string
engineVersion string
isSupported bool
}{
{
name: "non-MariaDB engine",
engine: RDSEnginePostgres,
engineVersion: "13.3",
isSupported: true,
},
{
name: "unsupported MariaDB",
engine: RDSEngineMariaDB,
engineVersion: "10.3.28",
isSupported: false,
},
{
name: "min supported version",
engine: RDSEngineMariaDB,
engineVersion: "10.6.2",
isSupported: true,
},
{
name: "supported version",
engine: RDSEngineMariaDB,
engineVersion: "10.8.0",
isSupported: true,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
cluster := &rds.DBInstance{
DBInstanceArn: aws.String("arn:aws:rds:us-east-1:1234567890:instance:test"),
DBClusterIdentifier: aws.String(test.name),
DbiResourceId: aws.String(uuid.New().String()),
Engine: aws.String(test.engine),
EngineVersion: aws.String(test.engineVersion),
}
got, want := IsRDSInstanceSupported(cluster), test.isSupported
require.Equal(t, want, got, "IsRDSInstanceSupported = %v, want = %v", got, want)
})
}
}
func TestAzureTagsToLabels(t *testing.T) {
azureTags := map[string]string{
"Env": "dev",
"foo:bar": "some-id",
"Name": "test",
}
labels := azureTagsToLabels(azureTags)
require.Equal(t, map[string]string{"Name": "test", "Env": "dev",
"foo:bar": "some-id"}, labels)
}
func TestRDSTagsToLabels(t *testing.T) {
rdsTags := []*rds.Tag{
{
Key: aws.String("Env"),
Value: aws.String("dev"),
},
{
Key: aws.String("aws:cloudformation:stack-id"),
Value: aws.String("some-id"),
},
{
Key: aws.String("Name"),
Value: aws.String("test"),
},
}
labels := rdsTagsToLabels(rdsTags)
require.Equal(t, map[string]string{"Name": "test", "Env": "dev",
"aws:cloudformation:stack-id": "some-id"}, labels)
}
// TestDatabaseFromRedshiftCluster tests converting an Redshift cluster to a database resource.
func TestDatabaseFromRedshiftCluster(t *testing.T) {
t.Run("success", func(t *testing.T) {
cluster := &redshift.Cluster{
ClusterIdentifier: aws.String("mycluster"),
ClusterNamespaceArn: aws.String("arn:aws:redshift:us-east-1:1234567890:namespace:u-u-i-d"),
Endpoint: &redshift.Endpoint{
Address: aws.String("localhost"),
Port: aws.Int64(5439),
},
Tags: []*redshift.Tag{
{
Key: aws.String("key"),
Value: aws.String("val"),
},
{
Key: aws.String("elasticbeanstalk:environment-id"),
Value: aws.String("id"),
},
},
}
expected, err := types.NewDatabaseV3(types.Metadata{
Name: "mycluster",
Description: "Redshift cluster in us-east-1",
Labels: map[string]string{
types.OriginLabel: types.OriginCloud,
labelAccountID: "1234567890",
labelRegion: "us-east-1",
"key": "val",
"elasticbeanstalk:environment-id": "id",
},
}, types.DatabaseSpecV3{
Protocol: defaults.ProtocolPostgres,
URI: "localhost:5439",
AWS: types.AWS{
AccountID: "1234567890",
Region: "us-east-1",
Redshift: types.Redshift{
ClusterID: "mycluster",
},
},
})
require.NoError(t, err)
actual, err := NewDatabaseFromRedshiftCluster(cluster)
require.NoError(t, err)
require.Equal(t, expected, actual)
})
t.Run("success with name override", func(t *testing.T) {
cluster := &redshift.Cluster{
ClusterIdentifier: aws.String("mycluster"),
ClusterNamespaceArn: aws.String("arn:aws:redshift:us-east-1:1234567890:namespace:u-u-i-d"),
Endpoint: &redshift.Endpoint{
Address: aws.String("localhost"),
Port: aws.Int64(5439),
},
Tags: []*redshift.Tag{
{
Key: aws.String("key"),
Value: aws.String("val"),
},
{
Key: aws.String("elasticbeanstalk:environment-id"),
Value: aws.String("id"),
},
{
Key: aws.String(labelTeleportDBName),
Value: aws.String("mycluster-override-2"),
},
},
}
expected, err := types.NewDatabaseV3(types.Metadata{
Name: "mycluster-override-2",
Description: "Redshift cluster in us-east-1",
Labels: map[string]string{
types.OriginLabel: types.OriginCloud,
labelAccountID: "1234567890",
labelRegion: "us-east-1",
labelTeleportDBName: "mycluster-override-2",
"key": "val",
"elasticbeanstalk:environment-id": "id",
},
}, types.DatabaseSpecV3{
Protocol: defaults.ProtocolPostgres,
URI: "localhost:5439",
AWS: types.AWS{
AccountID: "1234567890",
Region: "us-east-1",
Redshift: types.Redshift{
ClusterID: "mycluster",
},
},
})
require.NoError(t, err)
actual, err := NewDatabaseFromRedshiftCluster(cluster)
require.NoError(t, err)
require.Equal(t, expected, actual)
})
t.Run("missing endpoint", func(t *testing.T) {
_, err := NewDatabaseFromRedshiftCluster(&redshift.Cluster{
ClusterIdentifier: aws.String("still-creating"),
})
require.Error(t, err)
require.True(t, trace.IsBadParameter(err), "Expected trace.BadParameter, got %v", err)
})
}
func TestDatabaseFromElastiCacheConfigurationEndpoint(t *testing.T) {
cluster := &elasticache.ReplicationGroup{
ARN: aws.String("arn:aws:elasticache:us-east-1:1234567890:replicationgroup:my-cluster"),
ReplicationGroupId: aws.String("my-cluster"),
Status: aws.String("available"),
TransitEncryptionEnabled: aws.Bool(true),
ClusterEnabled: aws.Bool(true),
ConfigurationEndpoint: &elasticache.Endpoint{
Address: aws.String("configuration.localhost"),
Port: aws.Int64(6379),
},
UserGroupIds: []*string{aws.String("my-user-group")},
NodeGroups: []*elasticache.NodeGroup{
{
NodeGroupId: aws.String("0001"),
NodeGroupMembers: []*elasticache.NodeGroupMember{
{
CacheClusterId: aws.String("my-cluster-0001-001"),
},
{
CacheClusterId: aws.String("my-cluster-0001-002"),
},
},
},
{
NodeGroupId: aws.String("0002"),
NodeGroupMembers: []*elasticache.NodeGroupMember{
{
CacheClusterId: aws.String("my-cluster-0002-001"),
},
{
CacheClusterId: aws.String("my-cluster-0002-002"),
},
},
},
},
}
extraLabels := map[string]string{"key": "value"}
expected, err := types.NewDatabaseV3(types.Metadata{
Name: "my-cluster",
Description: "ElastiCache cluster in us-east-1 (configuration endpoint)",
Labels: map[string]string{
types.OriginLabel: types.OriginCloud,
labelAccountID: "1234567890",
labelRegion: "us-east-1",
labelEndpointType: "configuration",
"key": "value",
},
}, types.DatabaseSpecV3{
Protocol: defaults.ProtocolRedis,
URI: "configuration.localhost:6379",
AWS: types.AWS{
AccountID: "1234567890",
Region: "us-east-1",
ElastiCache: types.ElastiCache{
ReplicationGroupID: "my-cluster",
UserGroupIDs: []string{"my-user-group"},
TransitEncryptionEnabled: true,
EndpointType: awsutils.ElastiCacheConfigurationEndpoint,
},
},
})
require.NoError(t, err)
actual, err := NewDatabaseFromElastiCacheConfigurationEndpoint(cluster, extraLabels)
require.NoError(t, err)
require.Equal(t, expected, actual)
}
func TestDatabaseFromElastiCacheConfigurationEndpointNameOverride(t *testing.T) {
cluster := &elasticache.ReplicationGroup{
ARN: aws.String("arn:aws:elasticache:us-east-1:1234567890:replicationgroup:my-cluster"),
ReplicationGroupId: aws.String("my-cluster"),
Status: aws.String("available"),
TransitEncryptionEnabled: aws.Bool(true),
ClusterEnabled: aws.Bool(true),
ConfigurationEndpoint: &elasticache.Endpoint{
Address: aws.String("configuration.localhost"),
Port: aws.Int64(6379),
},
UserGroupIds: []*string{aws.String("my-user-group")},
NodeGroups: []*elasticache.NodeGroup{
{
NodeGroupId: aws.String("0001"),
NodeGroupMembers: []*elasticache.NodeGroupMember{
{
CacheClusterId: aws.String("my-cluster-0001-001"),
},
{
CacheClusterId: aws.String("my-cluster-0001-002"),
},
},
},
{
NodeGroupId: aws.String("0002"),
NodeGroupMembers: []*elasticache.NodeGroupMember{
{
CacheClusterId: aws.String("my-cluster-0002-001"),
},
{
CacheClusterId: aws.String("my-cluster-0002-002"),
},
},
},
},
}
extraLabels := map[string]string{
labelTeleportDBName: "my-override-cluster-2",
"key": "value",
}
expected, err := types.NewDatabaseV3(types.Metadata{
Name: "my-override-cluster-2",
Description: "ElastiCache cluster in us-east-1 (configuration endpoint)",
Labels: map[string]string{
types.OriginLabel: types.OriginCloud,
labelAccountID: "1234567890",
labelRegion: "us-east-1",
labelEndpointType: "configuration",
labelTeleportDBName: "my-override-cluster-2",
"key": "value",
},
}, types.DatabaseSpecV3{
Protocol: defaults.ProtocolRedis,
URI: "configuration.localhost:6379",
AWS: types.AWS{
AccountID: "1234567890",
Region: "us-east-1",
ElastiCache: types.ElastiCache{
ReplicationGroupID: "my-cluster",
UserGroupIDs: []string{"my-user-group"},
TransitEncryptionEnabled: true,
EndpointType: awsutils.ElastiCacheConfigurationEndpoint,
},
},
})
require.NoError(t, err)
actual, err := NewDatabaseFromElastiCacheConfigurationEndpoint(cluster, extraLabels)
require.NoError(t, err)
require.Equal(t, expected, actual)
}
func TestDatabaseFromElastiCacheNodeGroups(t *testing.T) {
cluster := &elasticache.ReplicationGroup{
ARN: aws.String("arn:aws:elasticache:us-east-1:1234567890:replicationgroup:my-cluster"),
ReplicationGroupId: aws.String("my-cluster"),
Status: aws.String("available"),
TransitEncryptionEnabled: aws.Bool(true),
ClusterEnabled: aws.Bool(false),
UserGroupIds: []*string{aws.String("my-user-group")},
NodeGroups: []*elasticache.NodeGroup{
{
NodeGroupId: aws.String("0001"),
PrimaryEndpoint: &elasticache.Endpoint{
Address: aws.String("primary.localhost"),
Port: aws.Int64(6379),
},
ReaderEndpoint: &elasticache.Endpoint{
Address: aws.String("reader.localhost"),
Port: aws.Int64(6379),
},
},
},
}
extraLabels := map[string]string{"key": "value"}
expectedPrimary, err := types.NewDatabaseV3(types.Metadata{
Name: "my-cluster",
Description: "ElastiCache cluster in us-east-1 (primary endpoint)",
Labels: map[string]string{
types.OriginLabel: types.OriginCloud,
labelAccountID: "1234567890",
labelRegion: "us-east-1",
labelEndpointType: "primary",
"key": "value",
},
}, types.DatabaseSpecV3{
Protocol: defaults.ProtocolRedis,
URI: "primary.localhost:6379",
AWS: types.AWS{
AccountID: "1234567890",
Region: "us-east-1",
ElastiCache: types.ElastiCache{
ReplicationGroupID: "my-cluster",
UserGroupIDs: []string{"my-user-group"},
TransitEncryptionEnabled: true,
EndpointType: awsutils.ElastiCachePrimaryEndpoint,
},
},
})
require.NoError(t, err)
expectedReader, err := types.NewDatabaseV3(types.Metadata{
Name: "my-cluster-reader",
Description: "ElastiCache cluster in us-east-1 (reader endpoint)",
Labels: map[string]string{
types.OriginLabel: types.OriginCloud,
labelAccountID: "1234567890",
labelRegion: "us-east-1",
labelEndpointType: "reader",
"key": "value",
},
}, types.DatabaseSpecV3{
Protocol: defaults.ProtocolRedis,
URI: "reader.localhost:6379",
AWS: types.AWS{
AccountID: "1234567890",
Region: "us-east-1",
ElastiCache: types.ElastiCache{
ReplicationGroupID: "my-cluster",
UserGroupIDs: []string{"my-user-group"},
TransitEncryptionEnabled: true,
EndpointType: awsutils.ElastiCacheReaderEndpoint,
},
},
})
require.NoError(t, err)
actual, err := NewDatabasesFromElastiCacheNodeGroups(cluster, extraLabels)
require.NoError(t, err)
require.Equal(t, types.Databases{expectedPrimary, expectedReader}, actual)
}
func TestDatabaseFromElastiCacheNodeGroupsNameOverride(t *testing.T) {
cluster := &elasticache.ReplicationGroup{
ARN: aws.String("arn:aws:elasticache:us-east-1:1234567890:replicationgroup:my-cluster"),
ReplicationGroupId: aws.String("my-cluster"),
Status: aws.String("available"),
TransitEncryptionEnabled: aws.Bool(true),
ClusterEnabled: aws.Bool(false),
UserGroupIds: []*string{aws.String("my-user-group")},
NodeGroups: []*elasticache.NodeGroup{
{
NodeGroupId: aws.String("0001"),
PrimaryEndpoint: &elasticache.Endpoint{
Address: aws.String("primary.localhost"),
Port: aws.Int64(6379),
},
ReaderEndpoint: &elasticache.Endpoint{
Address: aws.String("reader.localhost"),
Port: aws.Int64(6379),
},
},
},
}
extraLabels := map[string]string{
labelTeleportDBName: "my-override-cluster-2",
"key": "value",
}
expectedPrimary, err := types.NewDatabaseV3(types.Metadata{
Name: "my-override-cluster-2",
Description: "ElastiCache cluster in us-east-1 (primary endpoint)",
Labels: map[string]string{
types.OriginLabel: types.OriginCloud,
labelAccountID: "1234567890",
labelRegion: "us-east-1",
labelEndpointType: "primary",
labelTeleportDBName: "my-override-cluster-2",
"key": "value",
},
}, types.DatabaseSpecV3{
Protocol: defaults.ProtocolRedis,
URI: "primary.localhost:6379",
AWS: types.AWS{
AccountID: "1234567890",
Region: "us-east-1",
ElastiCache: types.ElastiCache{
ReplicationGroupID: "my-cluster",
UserGroupIDs: []string{"my-user-group"},
TransitEncryptionEnabled: true,
EndpointType: awsutils.ElastiCachePrimaryEndpoint,
},
},
})
require.NoError(t, err)
expectedReader, err := types.NewDatabaseV3(types.Metadata{
Name: "my-override-cluster-2-reader",
Description: "ElastiCache cluster in us-east-1 (reader endpoint)",
Labels: map[string]string{
types.OriginLabel: types.OriginCloud,
labelAccountID: "1234567890",
labelRegion: "us-east-1",
labelEndpointType: "reader",
labelTeleportDBName: "my-override-cluster-2",
"key": "value",
},
}, types.DatabaseSpecV3{
Protocol: defaults.ProtocolRedis,
URI: "reader.localhost:6379",
AWS: types.AWS{
AccountID: "1234567890",
Region: "us-east-1",
ElastiCache: types.ElastiCache{
ReplicationGroupID: "my-cluster",
UserGroupIDs: []string{"my-user-group"},
TransitEncryptionEnabled: true,
EndpointType: awsutils.ElastiCacheReaderEndpoint,
},
},
})
require.NoError(t, err)
actual, err := NewDatabasesFromElastiCacheNodeGroups(cluster, extraLabels)
require.NoError(t, err)
require.Equal(t, types.Databases{expectedPrimary, expectedReader}, actual)
}
func TestDatabaseFromMemoryDBCluster(t *testing.T) {
cluster := &memorydb.Cluster{
ARN: aws.String("arn:aws:memorydb:us-east-1:1234567890:cluster:my-cluster"),
Name: aws.String("my-cluster"),
Status: aws.String("available"),
TLSEnabled: aws.Bool(true),
ACLName: aws.String("my-user-group"),
ClusterEndpoint: &memorydb.Endpoint{
Address: aws.String("memorydb.localhost"),
Port: aws.Int64(6379),
},
}
extraLabels := map[string]string{"key": "value"}
expected, err := types.NewDatabaseV3(types.Metadata{
Name: "my-cluster",
Description: "MemoryDB cluster in us-east-1",
Labels: map[string]string{
types.OriginLabel: types.OriginCloud,
labelAccountID: "1234567890",
labelRegion: "us-east-1",
labelEndpointType: "cluster",
"key": "value",
},
}, types.DatabaseSpecV3{
Protocol: defaults.ProtocolRedis,
URI: "memorydb.localhost:6379",
AWS: types.AWS{
AccountID: "1234567890",
Region: "us-east-1",
MemoryDB: types.MemoryDB{
ClusterName: "my-cluster",
ACLName: "my-user-group",
TLSEnabled: true,
EndpointType: awsutils.MemoryDBClusterEndpoint,
},
},
})
require.NoError(t, err)
actual, err := NewDatabaseFromMemoryDBCluster(cluster, extraLabels)
require.NoError(t, err)
require.Equal(t, expected, actual)
}
func TestDatabaseFromMemoryDBClusterNameOverride(t *testing.T) {
cluster := &memorydb.Cluster{
ARN: aws.String("arn:aws:memorydb:us-east-1:1234567890:cluster:my-cluster"),
Name: aws.String("my-cluster"),
Status: aws.String("available"),
TLSEnabled: aws.Bool(true),
ACLName: aws.String("my-user-group"),
ClusterEndpoint: &memorydb.Endpoint{
Address: aws.String("memorydb.localhost"),
Port: aws.Int64(6379),
},
}
extraLabels := map[string]string{
labelTeleportDBName: "override-1",
"key": "value",
}
expected, err := types.NewDatabaseV3(types.Metadata{
Name: "override-1",
Description: "MemoryDB cluster in us-east-1",
Labels: map[string]string{
types.OriginLabel: types.OriginCloud,
labelAccountID: "1234567890",
labelRegion: "us-east-1",
labelEndpointType: "cluster",
labelTeleportDBName: "override-1",
"key": "value",
},
}, types.DatabaseSpecV3{
Protocol: defaults.ProtocolRedis,
URI: "memorydb.localhost:6379",
AWS: types.AWS{
AccountID: "1234567890",
Region: "us-east-1",
MemoryDB: types.MemoryDB{
ClusterName: "my-cluster",
ACLName: "my-user-group",
TLSEnabled: true,
EndpointType: awsutils.MemoryDBClusterEndpoint,
},
},
})
require.NoError(t, err)
actual, err := NewDatabaseFromMemoryDBCluster(cluster, extraLabels)
require.NoError(t, err)
require.Equal(t, expected, actual)
}
func TestExtraElastiCacheLabels(t *testing.T) {
cluster := &elasticache.ReplicationGroup{
ReplicationGroupId: aws.String("my-redis"),
}
tags := []*elasticache.Tag{
{Key: aws.String("key1"), Value: aws.String("value1")},
{Key: aws.String("key2"), Value: aws.String("value2")},
}
nodes := []*elasticache.CacheCluster{
{
ReplicationGroupId: aws.String("some-other-redis"),
EngineVersion: aws.String("8.8.8"),
CacheSubnetGroupName: aws.String("some-other-subnet-group"),
},
{
ReplicationGroupId: aws.String("my-redis"),
EngineVersion: aws.String("6.6.6"),
CacheSubnetGroupName: aws.String("my-subnet-group"),
},
}
subnetGroups := []*elasticache.CacheSubnetGroup{
{
CacheSubnetGroupName: aws.String("some-other-subnet-group"),
VpcId: aws.String("some-other-vpc"),
},
{
CacheSubnetGroupName: aws.String("my-subnet-group"),
VpcId: aws.String("my-vpc"),
},
}
tests := []struct {
name string
inputTags []*elasticache.Tag
inputNodes []*elasticache.CacheCluster
inputSubnetGroups []*elasticache.CacheSubnetGroup
expectLabels map[string]string
}{
{
name: "all tags",
inputTags: tags,
inputNodes: nodes,
inputSubnetGroups: subnetGroups,
expectLabels: map[string]string{
"key1": "value1",
"key2": "value2",
"engine-version": "6.6.6",
"vpc-id": "my-vpc",
},
},
{
name: "no resource tags",
inputTags: nil,
inputNodes: nodes,
inputSubnetGroups: subnetGroups,
expectLabels: map[string]string{
"engine-version": "6.6.6",
"vpc-id": "my-vpc",
},
},
{
name: "no nodes",
inputTags: tags,
inputNodes: nil,
inputSubnetGroups: subnetGroups,
// Without subnet group name from nodes, VPC ID cannot be found.
expectLabels: map[string]string{
"key1": "value1",
"key2": "value2",
},
},
{
name: "no subnet groups",
inputTags: tags,
inputNodes: nodes,
inputSubnetGroups: nil,
expectLabels: map[string]string{
"key1": "value1",
"key2": "value2",
"engine-version": "6.6.6",
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
actualLabels := ExtraElastiCacheLabels(cluster, test.inputTags, test.inputNodes, test.inputSubnetGroups)
require.Equal(t, test.expectLabels, actualLabels)
})
}
}
func TestExtraMemoryDBLabels(t *testing.T) {
cluster := &memorydb.Cluster{
Name: aws.String("my-cluster"),
SubnetGroupName: aws.String("my-subnet-group"),
EngineVersion: aws.String("6.6.6"),
}
allSubnetGroups := []*memorydb.SubnetGroup{
{
Name: aws.String("other-subnet-group"),
VpcId: aws.String("other-vpc-id"),
},
{
Name: aws.String("my-subnet-group"),
VpcId: aws.String("my-vpc-id"),
},
}
resourceTags := []*memorydb.Tag{
{Key: aws.String("key1"), Value: aws.String("value1")},
{Key: aws.String("key2"), Value: aws.String("value2")},
}
expected := map[string]string{
"key1": "value1",
"key2": "value2",
"engine-version": "6.6.6",
"vpc-id": "my-vpc-id",
}
actual := ExtraMemoryDBLabels(cluster, resourceTags, allSubnetGroups)
require.Equal(t, expected, actual)
}
func TestGetLabelEngineVersion(t *testing.T) {
t.Parallel()
tests := []struct {
name string
labels map[string]string
want string
}{
{
name: "mysql-8.0.0",
labels: map[string]string{
labelEngine: RDSEngineMySQL,
labelEngineVersion: "8.0.0",
},
want: "8.0.0",
},
{
name: "mariadb returns nothing",
labels: map[string]string{
labelEngine: RDSEngineMariaDB,
labelEngineVersion: "10.6.7",
},
want: "",
},
{
name: "missing labels",
labels: map[string]string{},
want: "",
},
{
name: "azure-mysql-8.0.0",
labels: map[string]string{
labelEngine: AzureEngineMySQL,
labelEngineVersion: "8.0.0",
},
want: "8.0.0",
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
if got := GetMySQLEngineVersion(tt.labels); got != tt.want {
t.Errorf("GetMySQLEngineVersion() = %v, want %v", got, tt.want)
}
})
}
}
func Test_setDBName(t *testing.T) {
tests := []struct {
name string
meta types.Metadata
firstNamePart string
extraNameParts []string
want types.Metadata
}{
{
name: "no override, one part name",
meta: types.Metadata{},
firstNamePart: "foo",
extraNameParts: nil,
want: types.Metadata{Name: "foo"},
},
{
name: "no override, multi part name",
meta: types.Metadata{},
firstNamePart: "foo",
extraNameParts: []string{"bar", "baz"},
want: types.Metadata{Name: "foo-bar-baz"},
},
{
name: "override, one part name",
meta: types.Metadata{Labels: map[string]string{labelTeleportDBName: "gizmo"}},
firstNamePart: "foo",
extraNameParts: nil,
want: types.Metadata{Name: "gizmo", Labels: map[string]string{labelTeleportDBName: "gizmo"}},
},
{
name: "override, multi part name",
meta: types.Metadata{Labels: map[string]string{labelTeleportDBName: "gizmo"}},
firstNamePart: "foo",
extraNameParts: []string{"bar", "baz"},
want: types.Metadata{Name: "gizmo-bar-baz", Labels: map[string]string{labelTeleportDBName: "gizmo"}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := setDBName(tt.meta, tt.firstNamePart, tt.extraNameParts...)
require.Equal(t, tt.want, result)
})
}
}