Files
threshold/testing/internal/e2e/tests/aws/dynamichostcatalog_test.go
T
Michael LiandJohan Brandhorst-Satzkorn 45171a3f56 refact(e2e): Changes to support an automated migration test (#2676)
* refact(e2e): Move cleanup steps into each test

The migration test needed to create some resources, but doesn't care about cleaning up because the test would take care of spinning down the docker container that it's using. To maintain flexibility going forward, we'll establish that tests are responsible for cleaning up (rather than the methods they use)

* refact(e2e): Use new env var for skip check

Currently, the e2e tests use the E2E_PASSWORD_AUTH_METHOD_ID environment variable to determine if the test should be skipped. However, the new migration test does not require a pre-existing boundary cluster and would not have this environment variable. As a result, we needed an alternative way to check if an e2e test should be skipped when running tests in ci.

* refact(e2e): Create more common boundary methods

* fix(e2e): Set to string value

Co-authored-by: Johan Brandhorst-Satzkorn <johan.brandhorst@gmail.com>
2022-12-06 15:59:17 -05:00

268 lines
9.5 KiB
Go

package aws_test
import (
"context"
"encoding/json"
"errors"
"fmt"
"strings"
"testing"
"time"
"github.com/cenkalti/backoff/v4"
"github.com/hashicorp/boundary/api/hostcatalogs"
"github.com/hashicorp/boundary/api/hosts"
"github.com/hashicorp/boundary/api/hostsets"
"github.com/hashicorp/boundary/api/scopes"
"github.com/hashicorp/boundary/testing/internal/e2e"
"github.com/hashicorp/boundary/testing/internal/e2e/boundary"
"github.com/kelseyhightower/envconfig"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
type config struct {
AwsAccessKeyId string `envconfig:"E2E_AWS_ACCESS_KEY_ID" required:"true"`
AwsSecretAccessKey string `envconfig:"E2E_AWS_SECRET_ACCESS_KEY" required:"true"`
AwsHostSetFilter1 string `envconfig:"E2E_AWS_HOST_SET_FILTER1" required:"true"` // e.g. "tag:testtag=true"
AwsHostSetIps1 string `envconfig:"E2E_AWS_HOST_SET_IPS1" required:"true"` // e.g. "[\"1.2.3.4\", \"2.3.4.5\"]"
AwsHostSetFilter2 string `envconfig:"E2E_AWS_HOST_SET_FILTER2" required:"true"` // e.g. "tag:testtagtwo=test"
AwsHostSetIps2 string `envconfig:"E2E_AWS_HOST_SET_IPS2" required:"true"` // e.g. "[\"1.2.3.4\"]"
TargetSshKeyPath string `envconfig:"E2E_SSH_KEY_PATH" required:"true"` // e.g. "/Users/username/key.pem"
TargetSshUser string `envconfig:"E2E_SSH_USER" required:"true"` // e.g. "ubuntu"
TargetPort string `envconfig:"E2E_SSH_PORT" default:"22"`
}
func loadConfig() (*config, error) {
var c config
err := envconfig.Process("", &c)
if err != nil {
return nil, err
}
return &c, err
}
// TestCliCreateAwsDynamicHostCatalog uses the boundary cli to create a host catalog with the AWS
// plugin. The test sets up an AWS dynamic host catalog, creates some host sets, sets up a target to
// one of the host sets, and attempts to connect to the target.
func TestCliCreateAwsDynamicHostCatalog(t *testing.T) {
e2e.MaybeSkipTest(t)
c, err := loadConfig()
require.NoError(t, err)
ctx := context.Background()
boundary.AuthenticateAdminCli(t, ctx)
newOrgId := boundary.CreateNewOrgCli(t, ctx)
t.Cleanup(func() {
ctx := context.Background()
boundary.AuthenticateAdminCli(t, ctx)
output := e2e.RunCommand(ctx, "boundary", e2e.WithArgs("scopes", "delete", "-id", newOrgId))
require.NoError(t, output.Err, string(output.Stderr))
})
newProjectId := boundary.CreateNewProjectCli(t, ctx, newOrgId)
newHostCatalogId := boundary.CreateNewAwsHostCatalogCli(t, ctx, newProjectId, c.AwsAccessKeyId, c.AwsSecretAccessKey)
// Set up a host set
newHostSetId1 := boundary.CreateNewAwsHostSetCli(t, ctx, newHostCatalogId, c.AwsHostSetFilter1)
actualHostSetCount1 := boundary.WaitForHostsInHostSetCli(t, ctx, newHostSetId1)
var targetIps1 []string
err = json.Unmarshal([]byte(c.AwsHostSetIps1), &targetIps1)
expectedHostSetCount1 := len(targetIps1)
require.NoError(t, err)
assert.Equal(t, expectedHostSetCount1, actualHostSetCount1, "Numbers of hosts in host set did not match expected amount")
// Set up another host set
newHostSetId2 := boundary.CreateNewAwsHostSetCli(t, ctx, newHostCatalogId, c.AwsHostSetFilter2)
actualHostSetCount2 := boundary.WaitForHostsInHostSetCli(t, ctx, newHostSetId2)
var targetIps2 []string
err = json.Unmarshal([]byte(c.AwsHostSetIps2), &targetIps2)
expectedHostSetCount2 := len(targetIps2)
require.NoError(t, err)
assert.Equal(t, expectedHostSetCount2, actualHostSetCount2, "Numbers of hosts in host set did not match expected amount")
// Get list of all hosts from host catalog
t.Logf("Looking for items in the host catalog...")
var actualHostCatalogCount int
err = backoff.RetryNotify(
func() error {
output := e2e.RunCommand(ctx, "boundary",
e2e.WithArgs("hosts", "list", "-host-catalog-id", newHostCatalogId, "-format", "json"),
)
if output.Err != nil {
return backoff.Permanent(errors.New(string(output.Stderr)))
}
var hostCatalogListResult hostcatalogs.HostCatalogListResult
err := json.Unmarshal(output.Stdout, &hostCatalogListResult)
if err != nil {
return backoff.Permanent(err)
}
actualHostCatalogCount = len(hostCatalogListResult.Items)
if actualHostCatalogCount == 0 {
return errors.New("No items are appearing in the host catalog")
}
t.Logf("Found %d host(s)", actualHostCatalogCount)
return nil
},
backoff.WithMaxRetries(backoff.NewConstantBackOff(3*time.Second), 5),
func(err error, td time.Duration) {
t.Logf("%s. Retrying...", err.Error())
},
)
require.NoError(t, err)
expectedHostCatalogCount := expectedHostSetCount1 + expectedHostSetCount2
require.NoError(t, err)
assert.Equal(t, expectedHostCatalogCount, actualHostCatalogCount, "Numbers of hosts in host catalog did not match expected amount")
// Create target
newTargetId := boundary.CreateNewTargetCli(t, ctx, newProjectId, c.TargetPort)
boundary.AddHostSourceToTargetCli(t, ctx, newTargetId, newHostSetId1)
// Connect to target
output := e2e.RunCommand(ctx, "boundary",
e2e.WithArgs(
"connect",
"-target-id", newTargetId,
"-exec", "/usr/bin/ssh", "--",
"-l", c.TargetSshUser,
"-i", c.TargetSshKeyPath,
"-o", "UserKnownHostsFile=/dev/null",
"-o", "StrictHostKeyChecking=no",
"-o", "IdentitiesOnly=yes", // forces the use of the provided key
"-p", "{{boundary.port}}", // this is provided by boundary
"{{boundary.ip}}",
"hostname", "-i",
),
)
require.NoError(t, output.Err, string(output.Stderr))
parts := strings.Fields(string(output.Stdout))
hostIp := parts[len(parts)-1]
t.Log("Successfully connected to the target")
// Check if connected host exists in the host set
hostIpInList := false
for _, v := range targetIps1 {
if v == hostIp {
hostIpInList = true
}
}
require.True(t, hostIpInList, fmt.Sprintf("Connected host (%s) is not in expected list (%s)", hostIp, targetIps1))
}
// TestApiCreateAwsDynamicHostCatalog uses the Go api to create a host catalog with the AWS plugin.
// The test sets up an AWS dynamic host catalog, creates a host set, and sets up a target to the
// host set.
func TestApiCreateAwsDynamicHostCatalog(t *testing.T) {
e2e.MaybeSkipTest(t)
c, err := loadConfig()
require.NoError(t, err)
client, err := boundary.NewApiClient()
require.NoError(t, err)
ctx := context.Background()
newOrgId := boundary.CreateNewOrgApi(t, ctx, client)
t.Cleanup(func() {
scopeClient := scopes.NewClient(client)
_, err := scopeClient.Delete(ctx, newOrgId)
require.NoError(t, err)
})
newProjectId := boundary.CreateNewProjectApi(t, ctx, client, newOrgId)
// Create a dynamic host catalog
hcClient := hostcatalogs.NewClient(client)
newHostCatalogResult, err := hcClient.Create(ctx, "plugin", newProjectId,
hostcatalogs.WithName("e2e Automated Test Host Catalog"),
hostcatalogs.WithPluginName("aws"),
hostcatalogs.WithAttributes(map[string]any{
"disable_credential_rotation": true,
"region": "us-east-1",
}),
hostcatalogs.WithSecrets(map[string]any{
"access_key_id": c.AwsAccessKeyId,
"secret_access_key": c.AwsSecretAccessKey,
}),
)
require.NoError(t, err)
newHostCatalogId := newHostCatalogResult.Item.Id
t.Logf("Created Host Catalog: %s", newHostCatalogId)
// Create a host set and add to catalog
hsClient := hostsets.NewClient(client)
newHostSetResult, err := hsClient.Create(ctx, newHostCatalogId,
hostsets.WithAttributes(map[string]any{
"filters": c.AwsHostSetFilter1,
}),
hostsets.WithName("e2e Automated Test Host Set"),
)
require.NoError(t, err)
newHostSetId := newHostSetResult.Item.Id
t.Logf("Created Host Set: %s", newHostSetId)
// Get list of hosts in host set
// Retry is needed here since it can take a few tries before hosts start appearing
t.Logf("Looking for items in the host set...")
var actualHostSetCount int
err = backoff.RetryNotify(
func() error {
hostSetReadResult, err := hsClient.Read(ctx, newHostSetId)
if err != nil {
return backoff.Permanent(err)
}
actualHostSetCount = len(hostSetReadResult.Item.HostIds)
if actualHostSetCount == 0 {
return errors.New("No items are appearing in the host set")
}
t.Logf("Found %d hosts", actualHostSetCount)
return nil
},
backoff.WithMaxRetries(backoff.NewConstantBackOff(3*time.Second), 5),
func(err error, td time.Duration) {
t.Logf("%s. Retrying...", err.Error())
},
)
require.NoError(t, err)
t.Log("Successfully found items in the host set")
var targetIps []string
err = json.Unmarshal([]byte(c.AwsHostSetIps1), &targetIps)
expectedHostSetCount := len(targetIps)
require.NoError(t, err)
assert.Equal(t, expectedHostSetCount, actualHostSetCount, "Numbers of hosts in host set did not match expected amount")
// Get list of all hosts from host catalog
// Retry is needed here since it can take a few tries before hosts start appearing
t.Logf("Looking for items in the host catalog...")
var actualHostCatalogCount int
hClient := hosts.NewClient(client)
err = backoff.RetryNotify(
func() error {
hostListResult, err := hClient.List(ctx, newHostCatalogId)
if err != nil {
return backoff.Permanent(err)
}
actualHostCatalogCount = len(hostListResult.Items)
if actualHostCatalogCount == 0 {
return errors.New("No items are appearing in the host catalog")
}
t.Logf("Found %d hosts", actualHostCatalogCount)
return nil
},
backoff.WithMaxRetries(backoff.NewConstantBackOff(3*time.Second), 5),
func(err error, td time.Duration) {
t.Logf("%s. Retrying...", err.Error())
},
)
require.NoError(t, err)
t.Log("Successfully found items in the host catalog")
require.NoError(t, err)
assert.Equal(t, actualHostCatalogCount, expectedHostSetCount, "Numbers of hosts in host catalog did not match expected amount")
}