mirror of https://github.com/hashicorp/boundary
test(e2e): Add a docker test runner (#3499)
* test(e2e): Add a docker test runner * !fixup: Self-review * !fixup: Make vault address compatible with local runs * !fixup: Remove unnecessary modification * !fixup: Remove arm64 requirement * !fixup: extend timeoutpull/3519/head
parent
0dcdee4758
commit
ef3954c561
@ -0,0 +1,226 @@
|
||||
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
terraform {
|
||||
required_providers {
|
||||
docker = {
|
||||
source = "kreuzwerker/docker"
|
||||
version = "3.0.1"
|
||||
}
|
||||
|
||||
enos = {
|
||||
source = "app.terraform.io/hashicorp-qti/enos"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
variable "docker_mirror" {
|
||||
description = "URL to the docker repository"
|
||||
type = string
|
||||
}
|
||||
variable "network_name" {
|
||||
description = "Name of Docker Network"
|
||||
type = string
|
||||
}
|
||||
variable "container_name" {
|
||||
description = "Name of Docker Container"
|
||||
type = string
|
||||
default = "test_runner"
|
||||
}
|
||||
variable "go_version" {
|
||||
description = "Version of Golang used by the application under test"
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
variable "debug_no_run" {
|
||||
description = "If set, this module will not execute the tests so that you can still access environment variables"
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
variable "test_package" {
|
||||
description = "Name of Go test package to run"
|
||||
type = string
|
||||
}
|
||||
variable "alb_boundary_api_addr" {
|
||||
description = "URL of the Boundary instance"
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
variable "auth_method_id" {
|
||||
description = "Id of Auth Method used to login to Boundary instance"
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
variable "auth_login_name" {
|
||||
description = "Name of admin user"
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
variable "auth_password" {
|
||||
description = "Password of admin user"
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
variable "local_boundary_dir" {
|
||||
description = "Local Path to boundary executable"
|
||||
type = string
|
||||
}
|
||||
variable "local_boundary_src_dir" {
|
||||
description = "Local Path to boundary src code directory"
|
||||
type = string
|
||||
}
|
||||
variable "target_user" {
|
||||
description = "SSH username for target"
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
variable "aws_ssh_private_key_path" {
|
||||
description = "Local Path to key used to SSH onto created hosts"
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
variable "target_ip" {
|
||||
description = "IP address of target"
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
variable "target_port" {
|
||||
description = "Port of target"
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
variable "vault_addr" {
|
||||
description = "External network address of Vault. Will be converted to a URL below"
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
variable "vault_addr_internal" {
|
||||
description = "Internal network address of Vault (i.e. within a docker network). Will be converted to a URL below"
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
variable "vault_root_token" {
|
||||
description = "Root token for vault instance"
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
variable "vault_port" {
|
||||
description = "External Port that vault instance is attached to (outside of docker network)"
|
||||
type = string
|
||||
default = "8200"
|
||||
}
|
||||
variable "aws_access_key_id" {
|
||||
description = "Access Key Id for AWS IAM user used in dynamic host catalogs"
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
variable "aws_secret_access_key" {
|
||||
description = "Secret Access Key for AWS IAM user used in dynamic host catalogs"
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
variable "aws_host_set_filter1" {
|
||||
description = "Filter tag for host set used in dynamic host catalogs"
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
variable "aws_host_set_count1" {
|
||||
description = "Number of hosts in aws_host_set_filter1"
|
||||
type = number
|
||||
default = 0
|
||||
}
|
||||
variable "aws_host_set_ips1" {
|
||||
description = "List of IP addresses in aws_host_set_filter1"
|
||||
type = list(string)
|
||||
default = [""]
|
||||
}
|
||||
variable "aws_host_set_filter2" {
|
||||
description = "Filter tag for host set used in dynamic host catalogs"
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
variable "aws_host_set_ips2" {
|
||||
description = "List of IP addresses in aws_host_set_filter2"
|
||||
type = list(string)
|
||||
default = [""]
|
||||
}
|
||||
variable "aws_region" {
|
||||
description = "AWS region where the resources will be created"
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
variable "aws_bucket_name" {
|
||||
description = "AWS S3 bucket name"
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
variable "worker_tags" {
|
||||
type = list(string)
|
||||
default = [""]
|
||||
}
|
||||
variable "test_timeout" {
|
||||
type = string
|
||||
default = "15m"
|
||||
}
|
||||
|
||||
resource "enos_local_exec" "get_go_version" {
|
||||
count = var.go_version == "" ? 1 : 0
|
||||
inline = ["cat $(echo $(git rev-parse --show-toplevel))/.go-version | xargs"]
|
||||
}
|
||||
|
||||
locals {
|
||||
go_version = var.go_version == "" ? enos_local_exec.get_go_version[0].stdout : var.go_version
|
||||
image_name = trimspace("${var.docker_mirror}/library/golang:${local.go_version}")
|
||||
|
||||
aws_ssh_private_key_path = abspath(var.aws_ssh_private_key_path)
|
||||
vault_addr = var.vault_addr != "" ? "http://${var.vault_addr}:${var.vault_port}" : ""
|
||||
vault_addr_internal = var.vault_addr_internal != "" ? "http://${var.vault_addr_internal}:8200" : local.vault_addr
|
||||
aws_host_set_ips1 = jsonencode(var.aws_host_set_ips1)
|
||||
aws_host_set_ips2 = jsonencode(var.aws_host_set_ips2)
|
||||
package_name = reverse(split("/", var.test_package))[0]
|
||||
}
|
||||
|
||||
resource "docker_image" "go" {
|
||||
name = local.image_name
|
||||
keep_locally = true
|
||||
}
|
||||
|
||||
resource "enos_local_exec" "run_e2e_test" {
|
||||
depends_on = [docker_image.go]
|
||||
environment = {
|
||||
TEST_PACKAGE = var.test_package,
|
||||
TEST_TIMEOUT = var.test_timeout,
|
||||
TEST_RUNNER_IMAGE = docker_image.go.image_id,
|
||||
TEST_NETWORK_NAME = var.network_name,
|
||||
E2E_TESTS = "true",
|
||||
BOUNDARY_ADDR = var.alb_boundary_api_addr,
|
||||
E2E_PASSWORD_AUTH_METHOD_ID = var.auth_method_id,
|
||||
E2E_PASSWORD_ADMIN_LOGIN_NAME = var.auth_login_name,
|
||||
E2E_PASSWORD_ADMIN_PASSWORD = var.auth_password,
|
||||
E2E_TARGET_IP = var.target_ip,
|
||||
E2E_SSH_USER = var.target_user,
|
||||
E2E_SSH_PORT = var.target_port,
|
||||
E2E_SSH_KEY_PATH = local.aws_ssh_private_key_path,
|
||||
VAULT_ADDR = local.vault_addr,
|
||||
VAULT_ADDR_INTERNAL = local.vault_addr_internal,
|
||||
VAULT_TOKEN = var.vault_root_token,
|
||||
E2E_VAULT_ADDR = local.vault_addr_internal,
|
||||
E2E_AWS_ACCESS_KEY_ID = var.aws_access_key_id,
|
||||
E2E_AWS_SECRET_ACCESS_KEY = var.aws_secret_access_key,
|
||||
E2E_AWS_HOST_SET_FILTER = var.aws_host_set_filter1,
|
||||
E2E_AWS_HOST_SET_IPS = local.aws_host_set_ips1,
|
||||
E2E_AWS_HOST_SET_FILTER2 = var.aws_host_set_filter2,
|
||||
E2E_AWS_HOST_SET_IPS2 = local.aws_host_set_ips2,
|
||||
E2E_AWS_REGION = var.aws_region,
|
||||
E2E_AWS_BUCKET_NAME = var.aws_bucket_name,
|
||||
E2E_WORKER_TAG = jsonencode(var.worker_tags),
|
||||
BOUNDARY_DIR = abspath(var.local_boundary_src_dir),
|
||||
BOUNDARY_CLI_DIR = abspath(var.local_boundary_dir),
|
||||
MODULE_DIR = abspath(path.module)
|
||||
}
|
||||
|
||||
inline = var.debug_no_run ? [""] : [
|
||||
"bash ./${path.module}/test_runner.sh"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
# This script is used for setting up and executing boundary e2e tests. It sets
|
||||
# up `pass` as a password store (linux) so that boundary can use it to store
|
||||
# auth tokens and installs the latest vault cli before executing the desired tests.
|
||||
|
||||
set -eux -o pipefail
|
||||
|
||||
# Install dependencies
|
||||
apt update
|
||||
# unzip is used to unzip boundary.zip
|
||||
# pass is used to store the auth token from `boundary authenticate``
|
||||
# lsb-release is used for adding the hashicorp apt source
|
||||
apt install unzip pass lsb-release -y
|
||||
|
||||
# Create a GPG key
|
||||
export KEY_PW=boundary
|
||||
gpg --generate-key --batch <<eoGpgConf
|
||||
%echo Started!
|
||||
Key-Type: default
|
||||
Key-Length: default
|
||||
Subkey-Type: default
|
||||
Name-Real: boundary
|
||||
Name-Comment: default
|
||||
Name-Email: default
|
||||
Expire-Date: 0
|
||||
Passphrase: $KEY_PW
|
||||
%commit
|
||||
%echo Done.
|
||||
eoGpgConf
|
||||
|
||||
# Enable gpg-preset-passphrase so that key passwords can be saved
|
||||
echo "allow-preset-passphrase" >> ~/.gnupg/gpg-agent.conf
|
||||
gpg-connect-agent reloadagent /bye &>/dev/null
|
||||
|
||||
# Get information about the created keys
|
||||
export lines=$(gpg --list-secret-keys --with-colons --with-keygrip)
|
||||
export KEY_ID=""
|
||||
while read -r line
|
||||
do
|
||||
# Save the first key id to be used later
|
||||
if [[ $line =~ "fpr"* ]]; then
|
||||
if [[ $KEY_ID == "" ]]; then
|
||||
KEY_ID="$(echo "$line" | sed -r 's/fpr|://g')"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Cache the passphrases for the keys so passwords do not need to be entered
|
||||
if [[ $line =~ "grp"* ]]; then
|
||||
export KEYGRIP_ID="$(echo "$line" | sed -r 's/grp|://g')"
|
||||
/usr/lib/gnupg/gpg-preset-passphrase --preset -P $KEY_PW $KEYGRIP_ID
|
||||
fi
|
||||
done <<< $lines
|
||||
|
||||
# Trust the key
|
||||
touch /tmp/test.txt
|
||||
gpg -a --encrypt -r $KEY_ID --trust-model always --batch --yes /tmp/test.txt
|
||||
echo "trusted-key $KEY_ID" >> ~/.gnupg/gpg.conf
|
||||
|
||||
# Initialize the password store
|
||||
pass init $KEY_ID &>/dev/null
|
||||
|
||||
# Install the vault cli
|
||||
wget -O- https://apt.releases.hashicorp.com/gpg | gpg --batch --yes --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
|
||||
export lines=$(gpg --no-default-keyring --keyring /usr/share/keyrings/hashicorp-archive-keyring.gpg --fingerprint --with-colons)
|
||||
while read -r line
|
||||
do
|
||||
if [[ $line =~ "fpr"* ]]; then
|
||||
if [[ "$(echo $line | sed -r 's/fpr|://g')" != "798AEC654E5C15428C8E42EEAA16FCBCA621E701" ]]; then
|
||||
echo "HashiCorp key fingerprint does not match expected"
|
||||
exit 1
|
||||
else
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done <<< $lines
|
||||
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/hashicorp.list
|
||||
apt update
|
||||
apt install vault
|
||||
|
||||
# Run Tests
|
||||
unzip /boundary.zip -d /usr/local/bin/
|
||||
cd /src/boundary
|
||||
go test -v -count=1 $TEST_PACKAGE -timeout $TEST_TIMEOUT | tee /testlogs/test-e2e-${TEST_PACKAGE##*/}.log
|
||||
@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
# This script sets up a docker container to serve as a test runner for boundary
|
||||
# e2e tests
|
||||
|
||||
set -eux -o pipefail
|
||||
|
||||
docker run \
|
||||
--rm \
|
||||
--name test-runner \
|
||||
-e "TEST_PACKAGE=$TEST_PACKAGE" \
|
||||
-e "TEST_TIMEOUT=$TEST_TIMEOUT" \
|
||||
-e "E2E_TESTS=$E2E_TESTS" \
|
||||
-e "BOUNDARY_ADDR=$BOUNDARY_ADDR" \
|
||||
-e "E2E_PASSWORD_AUTH_METHOD_ID=$E2E_PASSWORD_AUTH_METHOD_ID" \
|
||||
-e "E2E_PASSWORD_ADMIN_LOGIN_NAME=$E2E_PASSWORD_ADMIN_LOGIN_NAME" \
|
||||
-e "E2E_PASSWORD_ADMIN_PASSWORD=$E2E_PASSWORD_ADMIN_PASSWORD" \
|
||||
-e "E2E_TARGET_IP=$E2E_TARGET_IP" \
|
||||
-e "E2E_SSH_USER=$E2E_SSH_USER" \
|
||||
-e "E2E_SSH_PORT=$E2E_SSH_PORT" \
|
||||
-e "E2E_SSH_KEY_PATH=/keys/target.pem" \
|
||||
-e "VAULT_ADDR=$VAULT_ADDR_INTERNAL" \
|
||||
-e "VAULT_TOKEN=$VAULT_TOKEN" \
|
||||
-e "E2E_VAULT_ADDR=$E2E_VAULT_ADDR" \
|
||||
-e "E2E_AWS_ACCESS_KEY_ID=$E2E_AWS_ACCESS_KEY_ID" \
|
||||
-e "E2E_AWS_SECRET_ACCESS_KEY=$E2E_AWS_SECRET_ACCESS_KEY" \
|
||||
-e "E2E_AWS_HOST_SET_FILTER=$E2E_AWS_HOST_SET_FILTER" \
|
||||
-e "E2E_AWS_HOST_SET_IPS=$E2E_AWS_HOST_SET_IPS" \
|
||||
-e "E2E_AWS_HOST_SET_FILTER2=$E2E_AWS_HOST_SET_FILTER2" \
|
||||
-e "E2E_AWS_HOST_SET_IPS2=$E2E_AWS_HOST_SET_IPS2" \
|
||||
-e "E2E_AWS_REGION=$E2E_AWS_REGION" \
|
||||
-e "E2E_AWS_BUCKET_NAME=$E2E_AWS_BUCKET_NAME" \
|
||||
-e "E2E_WORKER_TAG=$E2E_WORKER_TAG" \
|
||||
--mount type=bind,src=$BOUNDARY_DIR,dst=/src/boundary/ \
|
||||
--mount type=bind,src=$MODULE_DIR/../..,dst=/testlogs \
|
||||
--mount type=bind,src=$(go env GOCACHE),dst=/root/.cache/go-build \
|
||||
--mount type=bind,src=$(go env GOMODCACHE),dst=/go/pkg/mod \
|
||||
-v "$MODULE_DIR/test.sh:/scripts/test.sh" \
|
||||
-v "$E2E_SSH_KEY_PATH:/keys/target.pem" \
|
||||
-v "$BOUNDARY_CLI_DIR:/boundary.zip" \
|
||||
--network $TEST_NETWORK_NAME \
|
||||
--cap-add=CAP_IPC_LOCK \
|
||||
$TEST_RUNNER_IMAGE \
|
||||
/bin/sh -c /scripts/test.sh
|
||||
Loading…
Reference in new issue