#!/usr/bin/env bash

set -e

check_command() {
  if ! [ -x "$(command -v "$1")" ]; then
    echo "$1 is required to run this script"
    exit
  fi
}

check_command base64
check_command aws

if [ -x "$(command -v jq)" ]; then
  image_extract=(jq -r '.MetricWidgetImage')
else
  echo "jq is reccomended to run this script. Will fall back to parsing JSON with sed"
  image_extract=(sed -En 's/\{? *"MetricWidgetImage" *: *"([^"]+) *,? *\}?"/\1/p')
fi

case "$(uname -a)" in
  Linux*)
    open_cmd=xdg-open
    ;;
  Darwin*)
    open_cmd=open
    ;;
  *)
    echo "This command only works on Linux or MacOS"
    exit 1
    ;;
esac

if [ -z "$AWS_ACCOUNT_ID" ]; then
    echo "AWS_ACCOUNT_ID environment variable is not set."
    exit 1
fi

if [ -z "$AWS_DEFAULT_REGION" ]; then
    echo "AWS_DEFAULT_REGION environment variable is not set."
    exit 1
fi

PROJECT_NAME="${PROJECT_NAME:-"howto-metrics-extension"}"

usage() {
  echo "usage: $(basename "$0") [-h]
  -m <metric name>            envoy.appmesh.RequestCountPerTarget
  [ -n <node name> ]          e.g. djapp
  [ -t <node type> ]          VirtualNode, VirtualGateway
  [ -q <search expression> ]  e.g. TargetVirtualNode=metal-v1
  [ -x <metric statistic> ]   Average, Sum, p50, etc. Default: Average
  [ -s <start time> ]         e.g. -PT3H, -P2D, etc. Default: -PT15M
  [ -p <period> ]             Period in seconds. Default: 60"
  exit 1
}

if [ -z "$1" ]; then
  usage
fi

statistic="Average"
start_time="-PT15M"
period="60"

while getopts ":m:x:s:t:n:q:p:h" options; do
  case "$options" in
    m)
      metric_name="$OPTARG"
      ;;
    x)
      statistic="$OPTARG"
      ;;
    s)
      start_time="$OPTARG"
      ;;
    t)
      node_type="$OPTARG"
      ;;
    n)
      node_name="$OPTARG"
      ;;
    q)
      query="$OPTARG"
      ;;
    p)
      period="$OPTARG"
      ;;
    h|:|*)
      usage
      ;;
  esac
done

if ! [ -z "$node_name" ]; then
  if [ -z "$node_type" ]; then
    echo "Node type must be specified with a node name"
    exit 1
  fi
fi

if ! [ -z "$node_type" ]; then
  if [ -z "$node_name" ]; then
    echo "Node name must be specified with a node type"
    exit 1
  fi
fi

if [ -z "$node_name" ]; then
  title="$metric_name $statistic"
  expression=$(cat <<EOF
{ "expression": "SEARCH('Namespace=\"$PROJECT_NAME\" MetricName=\"$metric_name\" $query', '$statistic', $period)" }
EOF
)
else
  title="$node_name - $metric_name $statistic"
  expression=$(cat <<EOF
{ "expression": "SEARCH('Namespace=\"$PROJECT_NAME\" Mesh=\"$PROJECT_NAME\" $node_type=\"$node_name\" MetricName=\"$metric_name\" $query', '$statistic', $period)" }
EOF
)
fi

widget=$(cat <<EOF
{
  "width": 1200,
  "height": 600,
  "period": $period,
  "start": "$start_time",
  "end": "PT0H",
  "title": "$title",
  "metrics": [
    [
      $expression
    ]
  ]
}
EOF
)

echo "Metric widget:"
echo "$widget"

file="$(mktemp -u).png"

echo "Saving metric snapshot to $file"

aws cloudwatch get-metric-widget-image --metric-widget "$widget" | "${image_extract[@]}" | base64 -d > "$file"

$open_cmd "$file"


#!/bin/bash

set -ex

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"

aws --region "${AWS_DEFAULT_REGION}" \
    cloudformation deploy \
    --stack-name "${ENVIRONMENT_NAME}-ecr-repositories" \
    --capabilities CAPABILITY_IAM \
    --template-file "${DIR}/ecr-repositories.yaml" \
    --parameter-overrides \
    TellerImageName="${TELLER_IMAGE_NAME}"


#!/bin/bash

set -ex

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"

aws --region "${AWS_DEFAULT_REGION}" \
    cloudformation deploy \
    --stack-name "${ENVIRONMENT_NAME}-ecs-cluster" \
    --capabilities CAPABILITY_IAM \
    --template-file "${DIR}/ecs-cluster.yaml"  \
    --parameter-overrides \
    EnvironmentName="${ENVIRONMENT_NAME}" \
    KeyName="${KEY_PAIR_NAME}" \
    ECSServicesDomain="${SERVICES_DOMAIN}"


#!/bin/bash

set -e

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"

aws --region "${AWS_DEFAULT_REGION}" \
    cloudformation deploy \
    --stack-name "${ENVIRONMENT_NAME}-ecs-service" \
    --capabilities CAPABILITY_IAM \
    --template-file "${DIR}/ecs-service.yaml"  \
    --parameter-overrides \
    EnvironmentName="${ENVIRONMENT_NAME}" \
    ECSServicesDomain="${SERVICES_DOMAIN}" \
    AppMeshMeshName="${MESH_NAME}" \
    EnvoyImage="${ENVOY_IMAGE}" \
    TellerImageName="${TELLER_IMAGE_NAME}"

print_bastion() {
    echo "Bastion endpoint:"
    ip=$(aws cloudformation describe-stacks \
        --stack-name="${ENVIRONMENT_NAME}-ecs-cluster" \
        --query="Stacks[0].Outputs[?OutputKey=='BastionIP'].OutputValue" \
        --output=text)
    echo "${ip}"
}

print_endpoint() {
    echo "ColorApp Endpoint:"
    prefix=$(aws cloudformation describe-stacks \
        --stack-name="${ENVIRONMENT_NAME}-ecs-service" \
        --query="Stacks[0].Outputs[?OutputKey=='TellerAppEndpoint'].OutputValue" \
        --output=text)
    echo "${prefix}"
}

print_bastion
print_endpoint


#!/bin/bash

set -ex

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"

aws --region "${AWS_DEFAULT_REGION}" \
    cloudformation deploy \
    --stack-name "${ENVIRONMENT_NAME}-vpc" \
    --capabilities CAPABILITY_IAM \
    --template-file "${DIR}/vpc.yaml" \
    --parameter-overrides \
    EnvironmentName="${ENVIRONMENT_NAME}"


#!/usr/bin/env bash
# vim:syn=sh:ts=4:sw=4:et:ai
shopt -s nullglob

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
TEST_MESH_DIR="${DIR}"

print() {
    printf "[$(date)] : %s\n" "$*"
}

err() {
    msg="Error: $1"
    print "${msg}"
    code=${2:-"1"}
    exit ${code}
}

sanity_check() {
    if [ -z "${MESH_NAME}" ]; then
        err "MESH_NAME is not set"
    fi
}

appmesh_cmd="aws appmesh"

create_mesh() {
    spec_file=$1
    cmd=( $appmesh_cmd create-mesh --mesh-name "${MESH_NAME}" \
                --cli-input-json "file:///${spec_file}" \
                --query mesh.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to create mesh" "$?"
    print "--> ${uid}"
}

delete_mesh() {
    cmd=( $appmesh_cmd delete-mesh --mesh-name "${MESH_NAME}" \
                ${PROFILE_OPT} \
                --query mesh.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to delete mesh" "$?"
    print "--> ${uid}"
}

create_vgateway() {
    spec_file=$1
    vgateway_name=$2
    cli_input=$( jq -n \
    -f "$spec_file" )
    cmd=( $appmesh_cmd create-virtual-gateway \
                --mesh-name "${MESH_NAME}" \
                --virtual-gateway-name "${vgateway_name}" \
                --cli-input-json "$cli_input" \
                --query virtualGateway.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to create virtual gateway" "$?"
    print "--> ${uid}"
}

update_vgateway() {
    spec_file=$1
    vgateway_name=$2
    cli_input=$( jq -n \
    -f "$spec_file" )
    cmd=( $appmesh_cmd update-virtual-gateway \
                --mesh-name "${MESH_NAME}" \
                --virtual-gateway-name "${vgateway_name}" \
                --cli-input-json "$cli_input" \
                --query virtualGateway.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to update virtual gateway" "$?"
    print "--> ${uid}"
}

delete_vgateway() {
    vgateway_name=$1
    cmd=( $appmesh_cmd delete-virtual-gateway \
                --mesh-name "${MESH_NAME}" \
                --virtual-gateway-name "${vgateway_name}" \
                --query virtualGateway.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to delete virtual gateway" "$?"
    print "--> ${uid}"
}

create_gateway_route() {
    spec_file=$1
    vgateway_name=$2
    gatewayroute_name=$3
    cli_input=$( jq -n \
        --arg VIRTUALSERVICE_NAME "$4" \
        -f "$spec_file" )
    cmd=( $appmesh_cmd create-gateway-route \
                --mesh-name "${MESH_NAME}" \
                --virtual-gateway-name "${vgateway_name}" \
                --gateway-route-name "${gatewayroute_name}" \
                --cli-input-json "$cli_input" \
                --query gatewayRoute.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to create gateway route" "$?"
    print "--> ${uid}"
}

delete_gateway_route() {
    vgateway_name=$1
    gatewayroute_name=$2
    cmd=( $appmesh_cmd delete-gateway-route \
                --mesh-name "${MESH_NAME}" \
                --virtual-gateway-name "${vgateway_name}" \
                --gateway-route-name "${gatewayroute_name}" \
                --query gatewayRoute.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to delete gateway route" "$?"
    print "--> ${uid}"
}

create_vnode() {
    spec_file=$1
    vnode_name=$2
    dns_hostname="$3.${SERVICES_DOMAIN}"
    cli_input=$( jq -n \
        --arg DNS_HOSTNAME "$3.${SERVICES_DOMAIN}" \
        -f "$spec_file" )
    cmd=( $appmesh_cmd create-virtual-node \
                --mesh-name "${MESH_NAME}" \
                --virtual-node-name "${vnode_name}" \
                --cli-input-json "$cli_input" \
                --query virtualNode.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to create virtual node" "$?"
    print "--> ${uid}"
}

update_vnode() {
    spec_file=$1
    vnode_name=$2
    dns_hostname="$3.${SERVICES_DOMAIN}"
    cli_input=$( jq -n \
        --arg DNS_HOSTNAME "$3.${SERVICES_DOMAIN}" \
        -f "$spec_file" )
    cmd=( $appmesh_cmd update-virtual-node \
                --mesh-name "${MESH_NAME}" \
                --virtual-node-name "${vnode_name}" \
                --cli-input-json "$cli_input" \
                --query virtualNode.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to update virtual node" "$?"
    print "--> ${uid}"
}

delete_vnode() {
    vnode_name=$1
    cmd=( $appmesh_cmd delete-virtual-node \
                --mesh-name "${MESH_NAME}" \
                --virtual-node-name "${vnode_name}" \
                --query virtualNode.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to delete virtual node" "$?"
    print "--> ${uid}"
}

create_vservice() {
    spec_file=$1
    vservice_name=$2
    cmd=( $appmesh_cmd create-virtual-service  \
                --mesh-name "${MESH_NAME}" \
                --virtual-service-name "${vservice_name}" \
                --cli-input-json "file:///${spec_file}" \
                --query virtualService.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to create virtual service" "$?"
    print "--> ${uid}"
}

delete_vservice() {
    vservice_name=$1
    cmd=( $appmesh_cmd delete-virtual-service \
                --mesh-name "${MESH_NAME}" \
                --virtual-service-name "${vservice_name}" \
                --query virtualService.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to delete virtual service" "$?"
    print "--> ${uid}"
}

create_vrouter() {
    spec_file=$1
    vrouter_name=$2
    cmd=( $appmesh_cmd create-virtual-router \
                --mesh-name "${MESH_NAME}" \
                --virtual-router-name "${vrouter_name}" \
                --cli-input-json "file:///${spec_file}" \
                --query virtualRouter.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to create virtual router" "$?"
    print "--> ${uid}"
}

delete_vrouter() {
    vrouter_name=$1
    cmd=( $appmesh_cmd delete-virtual-router \
                --mesh-name "${MESH_NAME}" \
                --virtual-router-name "${vrouter_name}" \
                --query virtualRouter.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to delete virtual router" "$?"
    print "--> ${uid}"
}

create_route() {
    spec_file=$1
    vrouter_name=$2
    route_name=$3
    cmd=( $appmesh_cmd create-route \
                --mesh-name "${MESH_NAME}" \
                --virtual-router-name "${vrouter_name}" \
                --route-name "${route_name}" \
                --cli-input-json "file:///${spec_file}" \
                --query route.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to create route" "$?"
    print "--> ${uid}"
}

delete_route() {
    vrouter_name=$1
    route_name=$2
    cmd=( $appmesh_cmd delete-route \
                --mesh-name "${MESH_NAME}" \
                --virtual-router-name "${vrouter_name}" \
                --route-name "${route_name}" \
                --query route.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to delete route" "$?"
    print "--> ${uid}"
}

main() {
    action="$1"
    if [ -z "$action" ]; then
        echo "Usage:"
        echo "mesh.sh [up|down]"
    fi
    sanity_check

    update_resource="$2"
    resource_name="$3"

    case "$action" in
    up)
        create_mesh "${TEST_MESH_DIR}/mesh.json"

        create_vnode "${TEST_MESH_DIR}/colorteller-vn.json" "colorteller-vn" "colorteller"
        create_vservice "${TEST_MESH_DIR}/colorteller-vs.json" "colorteller.${SERVICES_DOMAIN}"

        create_vnode "${TEST_MESH_DIR}/foodteller-vn.json" "foodteller-vn" "foodteller"
        create_vrouter "${TEST_MESH_DIR}/foodteller-vr.json" "foodteller-vr"
        create_vservice "${TEST_MESH_DIR}/foodteller-vs.json" "foodteller.${SERVICES_DOMAIN}"
        create_route "${TEST_MESH_DIR}/fruit-route.json" "foodteller-vr" "fruit-route"
        create_route "${TEST_MESH_DIR}/vegetable-route.json" "foodteller-vr" "vegetable-route"

        create_vgateway "${TEST_MESH_DIR}/tellergateway-vg.json" "tellergateway-vg"
        create_gateway_route "${TEST_MESH_DIR}/color-gateway-route.json" "tellergateway-vg" "color-gateway-route" "colorteller.${SERVICES_DOMAIN}"
        create_gateway_route "${TEST_MESH_DIR}/fruit-gateway-route.json" "tellergateway-vg" "fruit-gateway-route" "foodteller.${SERVICES_DOMAIN}"
        create_gateway_route "${TEST_MESH_DIR}/vegetable-gateway-route.json" "tellergateway-vg" "vegetable-gateway-route" "foodteller.${SERVICES_DOMAIN}"
        ;;

    down)
        delete_gateway_route "tellergateway-vg" "vegetable-gateway-route"
        delete_gateway_route "tellergateway-vg" "fruit-gateway-route"
        delete_gateway_route "tellergateway-vg" "color-gateway-route"
        delete_vgateway "tellergateway-vg"

        delete_route "foodteller-vr" "vegetable-route"
        delete_route "foodteller-vr" "fruit-route"
        delete_vservice "foodteller.${SERVICES_DOMAIN}"
        delete_vrouter "foodteller-vr"
        delete_vnode "foodteller-vn"

        delete_vservice "colorteller.${SERVICES_DOMAIN}"
        delete_vnode "colorteller-vn"

        delete_mesh
        ;;

    *)
        err "Invalid action specified: $action"
        ;;
    esac
}

main $@


#!/usr/bin/env bash
# vim:syn=sh:ts=4:sw=4:et:ai

set -ex

if [ -z $TELLER_IMAGE_NAME ]; then
    echo "TELLER_IMAGE_NAME environment variable is not set"
    exit 1
fi

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
ECR_URL="${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com"
IMAGE="${ECR_URL}/${TELLER_IMAGE_NAME}:latest"

# build
docker build -t $IMAGE $DIR --build-arg GO_PROXY=${GO_PROXY:-"https://proxy.golang.org"}

# login
AWS_CLI_VERSION=$(aws --version 2>&1 | cut -d/ -f2 | cut -d. -f1)
if [ $AWS_CLI_VERSION -gt 1 ]; then
    aws ecr get-login-password --region ${AWS_DEFAULT_REGION} | \
         docker login --username AWS --password-stdin ${ECR_URL}
else
    $(aws ecr get-login --no-include-email)
fi

# push
docker push $IMAGE


#!/bin/bash

set -ex

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"

aws --profile "${AWS_PROFILE}" --region "${AWS_DEFAULT_REGION}" \
    cloudformation deploy \
    --stack-name "${ENVIRONMENT_NAME}-ecr-repositories" \
    --capabilities CAPABILITY_IAM \
    --template-file "${DIR}/ecr-repositories.yaml" \
    --parameter-overrides \
    ColorTellerImageName="${COLOR_TELLER_IMAGE_NAME}" \
    ColorTellerEnvoyImageName="${ENVOY_IMAGE_NAME}"


#!/bin/bash

set -ex

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"

aws --profile "${AWS_PROFILE}" --region "${AWS_DEFAULT_REGION}" \
    cloudformation deploy \
    --stack-name "${ENVIRONMENT_NAME}-ecs-cluster" \
    --capabilities CAPABILITY_IAM \
    --template-file "${DIR}/ecs-cluster.yaml"  \
    --parameter-overrides \
    EnvironmentName="${ENVIRONMENT_NAME}" \
    KeyName="${KEY_PAIR_NAME}" \
    ECSServicesDomain="${SERVICES_DOMAIN}"


#!/bin/bash

set -ex

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"

aws --profile "${AWS_PROFILE}" --region "${AWS_DEFAULT_REGION}" \
    cloudformation deploy \
    --stack-name "${ENVIRONMENT_NAME}-ecs-service" \
    --capabilities CAPABILITY_IAM \
    --template-file "${DIR}/ecs-service.yaml"  \
    --parameter-overrides \
    EnvironmentName="${ENVIRONMENT_NAME}" \
    ECSServicesDomain="${SERVICES_DOMAIN}" \
    AppMeshMeshName="${MESH_NAME}" \
    EnvoyImageName="${ENVOY_IMAGE_NAME}" \
    ColorTellerImageName="${COLOR_TELLER_IMAGE_NAME}"


#!/bin/bash

set -ex

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"

aws --profile "${AWS_PROFILE}" --region "${AWS_DEFAULT_REGION}" \
    cloudformation deploy \
    --stack-name "${ENVIRONMENT_NAME}-vpc" \
    --capabilities CAPABILITY_IAM \
    --template-file "${DIR}/vpc.yaml" \
    --parameter-overrides \
    EnvironmentName="${ENVIRONMENT_NAME}"


#!/usr/bin/env bash
# vim:syn=sh:ts=4:sw=4:et:ai

shopt -s nullglob
set -eo pipefail

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
TEST_MESH_DIR="${DIR}"

print() {
    printf "[$(date)] : %s\n" "$*"
}

err() {
    msg="Error: $1"
    print "${msg}"
    code=${2:-"1"}
    exit ${code}
}

sanity_check() {
    if [ -z "${MESH_NAME}" ]; then
        err "MESH_NAME is not set"
    fi
}

appmesh_cmd="aws appmesh"

create_mesh() {
    spec_file=$1
    cmd=( $appmesh_cmd create-mesh --mesh-name "${MESH_NAME}" \
                ${PROFILE_OPT} \
                --cli-input-json "file:///${spec_file}" \
                --query mesh.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to create mesh" "$?"
    print "--> ${uid}"
}

delete_mesh() {
    cmd=( $appmesh_cmd delete-mesh --mesh-name "${MESH_NAME}" \
                ${PROFILE_OPT} \
                --query mesh.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to delete mesh" "$?"
    print "--> ${uid}"
}

create_vnode() {
    spec_file=$1
    vnode_name=$2
    cli_input=$( jq -n \
        --arg SERVICES_DOMAIN $SERVICES_DOMAIN \
        -f "$spec_file" )
    cmd=( $appmesh_cmd create-virtual-node --mesh-name "${MESH_NAME}" \
                --virtual-node-name "${vnode_name}" \
                ${PROFILE_OPT} \
                --cli-input-json "$cli_input" \
                --query virtualNode.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to create virtual node" "$?"
    print "--> ${uid}"
}

update_vnode() {
    spec_file=$1
    vnode_name=$2
    gateway_san=$3
    cli_input=$( jq -n \
        --arg SERVICES_DOMAIN $SERVICES_DOMAIN \
        --arg GATEWAY_SAN $gateway_san \
        -f "$spec_file" )
    cmd=( $appmesh_cmd update-virtual-node --mesh-name "${MESH_NAME}" \
                --virtual-node-name "${vnode_name}" \
                ${PROFILE_OPT} \
                --cli-input-json "$cli_input" \
                --query virtualNode.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to update virtual node" "$?"
    print "--> ${uid}"
}

delete_vnode() {
    vnode_name=$1
    cmd=( $appmesh_cmd delete-virtual-node --mesh-name "${MESH_NAME}" \
                --virtual-node-name "${vnode_name}" \
                ${PROFILE_OPT} \
                --query virtualNode.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to delete virtual node" "$?"
    print "--> ${uid}"
}

create_vgateway() {
    spec_file=$1
    gateway_name=$2
    cli_input=$( jq -n \
        -f "$spec_file" )
    cmd=( $appmesh_cmd create-virtual-gateway --mesh-name "${MESH_NAME}" \
                --virtual-gateway-name "${gateway_name}" \
                ${PROFILE_OPT} \
                --cli-input-json "$cli_input" \
                --query virtualGateway.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to create virtual gateway" "$?"
    print "--> ${uid}"
}

update_vgateway() {
    spec_file=$1
    gateway_name=$2
    backend_san=$3
    cli_input=$( jq -n \
        --arg COLOR_TELLER_SAN $backend_san \
        -f "$spec_file" )
    cmd=( $appmesh_cmd update-virtual-gateway --mesh-name "${MESH_NAME}" \
                --virtual-gateway-name "${gateway_name}" \
                ${PROFILE_OPT} \
                --cli-input-json "$cli_input" \
                --query virtualGateway.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to update virtual gateway" "$?"
    print "--> ${uid}"
}

delete_vgateway() {
    gateway_name=$1
    cmd=( $appmesh_cmd delete-virtual-gateway --mesh-name "${MESH_NAME}" \
                --virtual-gateway-name "${gateway_name}" \
                ${PROFILE_OPT} \
                --query virtualNode.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to delete virtual gateway" "$?"
    print "--> ${uid}"
}

create_gwroute() {
    spec_file=$1
    route_name=$2
    gateway_name=$3
    vservice_name=$4
    cli_input=$( jq -n \
        --arg VIRTUAL_SERVICE $vservice_name \
        -f "$spec_file" )
    cmd=( $appmesh_cmd create-gateway-route --mesh-name "${MESH_NAME}" \
                --gateway-route-name "${route_name}" \
                --virtual-gateway-name "${gateway_name}" \
                ${PROFILE_OPT} \
                --cli-input-json "$cli_input" \
                --query gatewayRoute.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to create virtual gateway" "$?"
    print "--> ${uid}"
}

update_gwroute() {
    spec_file=$1
    route_name=$2
    gateway_name=$3
    cli_input=$( jq -n \
        --arg VIRTUAL_SERVICE $service_name \
        -f "$spec_file" )
    cmd=( $appmesh_cmd update-gateway-route --mesh-name "${MESH_NAME}" \
                --gateway-route-name "${route_name}" \
                --virtual-gateway-name "${gateway_name}" \
                ${PROFILE_OPT} \
                --cli-input-json "$cli_input" \
                --query gatewayRoute.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to update virtual gateway" "$?"
    print "--> ${uid}"
}

delete_gwroute() {
    route_name=$1
    gateway_name=$2
    cmd=( $appmesh_cmd delete-gateway-route --mesh-name "${MESH_NAME}" \
                --virtual-gateway-name "${gateway_name}" \
                --gateway-route-name "${route_name}" \
                ${PROFILE_OPT} \
                --query gatewayRoute.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to delete virtual gateway" "$?"
    print "--> ${uid}"
}

create_vservice() {
    spec_file=$1
    vservice_name=$2
    cmd=( $appmesh_cmd create-virtual-service --mesh-name "${MESH_NAME}" \
                --virtual-service-name "${vservice_name}" \
                ${PROFILE_OPT} \
                --cli-input-json "file:///${spec_file}" \
                --query virtualService.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to create virtual service" "$?"
    print "--> ${uid}"
}

delete_vservice() {
    vservice_name=$1
    cmd=( $appmesh_cmd delete-virtual-service --mesh-name "${MESH_NAME}" \
                --virtual-service-name "${vservice_name}" \
                ${PROFILE_OPT} \
                --query virtualService.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to delete virtual service" "$?"
    print "--> ${uid}"
}

main() {
    action="$1"
    if [ -z "$action" ]; then
        echo "Usage:"
        echo "mesh.sh [up|down]"
    fi
    sanity_check

    case "$action" in
    up)
        create_mesh "${TEST_MESH_DIR}/mesh.json"
        create_vnode "${TEST_MESH_DIR}/colorteller-vn.json" "colorteller-vn"
        create_vservice "${TEST_MESH_DIR}/colorteller-vs.json" "colorteller.${SERVICES_DOMAIN}"
        create_vgateway "${TEST_MESH_DIR}/gateway-vgw.json" "gateway-vgw"
        create_gwroute "${TEST_MESH_DIR}/colorteller-gwroute.json" "colorteller-route" "gateway-vgw" "colorteller.${SERVICES_DOMAIN}"
        ;;
    down)
        delete_gwroute "colorteller-route" "gateway-vgw"
        delete_vgateway "gateway-vgw"
        delete_vservice "colorteller.${SERVICES_DOMAIN}"
        delete_vnode "colorteller-vn"
        delete_mesh
        ;;
    update_1_strict_tls)
        update_vnode "${TEST_MESH_DIR}/updates/colorteller-vn-strict-tls.json" "colorteller-vn" "gateway.$SERVICES_DOMAIN"
        ;;
    update_2_client_policy_bad_san)
        update_vgateway "${TEST_MESH_DIR}/updates/gateway-vgw-client-policy.json" "gateway-vgw" "bogus.$SERVICES_DOMAIN"
        ;;
    update_3_client_policy_good_san)
        update_vgateway "${TEST_MESH_DIR}/updates/gateway-vgw-client-policy.json" "gateway-vgw" "colorteller.$SERVICES_DOMAIN"
        ;;
    update_4_require_client_cert)
        update_vnode "${TEST_MESH_DIR}/updates/colorteller-vn-strict-validation.json" "colorteller-vn" "gateway.$SERVICES_DOMAIN"
        ;;
    update_5_client_cert)
        update_vgateway "${TEST_MESH_DIR}/updates/gateway-vgw-client-cert.json" "gateway-vgw" "colorteller.$SERVICES_DOMAIN"
        ;;
    *)
        err "Invalid action specified: $action"
        ;;
    esac
}

main $@


#!/usr/bin/env bash
# vim:syn=sh:ts=4:sw=4:et:ai

set -ex

if [ -z $AWS_ACCOUNT_ID ]; then
    echo "AWS_ACCOUNT_ID environment variable is not set."
    exit 1
fi

if [ -z $AWS_DEFAULT_REGION ]; then
    echo "AWS_DEFAULT_REGION environment variable is not set."
    exit 1
fi

if [ -z $COLOR_TELLER_IMAGE_NAME ]; then
    echo "COLOR_TELLER_IMAGE_NAME environment variable is not set"
    exit 1
fi

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
AWS_CLI_VERSION=$(aws --version 2>&1 | cut -d/ -f2 | cut -d. -f1)

ECR_URL="${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com"
IMAGE="${ECR_URL}/${COLOR_TELLER_IMAGE_NAME}:latest"

ecr_login() {
    if [ $AWS_CLI_VERSION -gt 1 ]; then
        aws ecr get-login-password --region ${AWS_DEFAULT_REGION} | \
            docker login --username AWS --password-stdin ${ECR_URL}
    else
        $(aws ecr get-login --no-include-email)
    fi
}

# build and push
docker build -t $IMAGE $DIR --build-arg GO_PROXY=${GO_PROXY:-"https://proxy.golang.org"}
ecr_login
docker push $IMAGE


#!/usr/bin/env bash
# vim:syn=sh:ts=4:sw=4:et:ai

set -ex

if [ -z $AWS_ACCOUNT_ID ]; then
    echo "AWS_ACCOUNT_ID environment variable is not set."
    exit 1
fi

if [ -z $AWS_DEFAULT_REGION ]; then
    echo "AWS_DEFAULT_REGION environment variable is not set."
    exit 1
fi

if [ -z $ENVOY_IMAGE_NAME ]; then
    echo "ENVOY_IMAGE_NAME environment variable is not set"
    exit 1
fi

if [ -z $ENVOY_IMAGE ]; then
    echo "ENVOY_IMAGE environment variable is not set"
    exit 1
fi

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
AWS_CLI_VERSION=$(aws --version 2>&1 | cut -d/ -f2 | cut -d. -f1)

ENVOY_REGISTRY_ID=840364872350
DEMO_ECR_URL="${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com"
IMAGE="${DEMO_ECR_URL}/${ENVOY_IMAGE_NAME}:latest"

ecr_login() {
    REGISTRY_ID=$1

    if [ $AWS_CLI_VERSION -gt 1 ]; then
	REGISTRY_URL="${REGISTRY_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com"
        aws ecr get-login-password --region ${AWS_DEFAULT_REGION} | \
            docker login --username AWS --password-stdin ${REGISTRY_URL}
    else
	$(aws ecr get-login --no-include-email --registry-id ${REGISTRY_ID})
    fi
}

# login to envoy registry for pull
ecr_login $ENVOY_REGISTRY_ID

# build and push
docker build -t $IMAGE $DIR \
    --build-arg ENVOY_IMAGE=$ENVOY_IMAGE \
    --build-arg AWS_DEFAULT_REGION=$AWS_DEFAULT_REGION
ecr_login $AWS_ACCOUNT_ID
docker push $IMAGE


#!/bin/bash

# $1=Secret Name
getSecret() {
    aws secretsmanager get-secret-value --secret-id $1 --region $AWS_DEFAULT_REGION | jq -r .SecretString > /keys/${1}.pem
    echo "Added $1 to container"
}

getCertificates() {
    if [[ $CERTIFICATE_NAME = "gateway" ]];
    then
        getSecret "ca_cert"
        getSecret "gateway_key"
        getSecret "gateway_cert_chain"
    fi
    if [[ $CERTIFICATE_NAME = "colorteller" ]];
    then
        getSecret "colorteller_key"
        getSecret "colorteller_cert_chain"
        getSecret "ca_cert"
    fi
}

# Get the appropriate certificates
getCertificates
# Start Envoy
/usr/bin/agent


#!/bin/bash

set -e

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"

# $1=<CA name>
generate_ca() {
  openssl genrsa -out $DIR/$1_key.pem 2048
  openssl req -new -key $DIR/$1_key.pem -out $DIR/$1_cert.csr -config $DIR/$1_cert.cfg -batch -sha256
  openssl x509 -req -days 3650 -in $DIR/$1_cert.csr -signkey $DIR/$1_key.pem -out $DIR/$1_cert.pem \
    -extensions v3_ca -extfile $DIR/$1_cert.cfg
}

# $1=<certificate name>
generate_rsa_key() {
  openssl genrsa -out $DIR/$1_key.pem 2048
}

# $1=<certificate_name>
generate_cert_config() {
  sed -e "s/\${services_domain}/${SERVICES_DOMAIN}/" $DIR/$1_cert.cfg > $DIR/$1_cert.cfg.generated
}

# $1=<certificate name> $2=<CA name>
generate_x509_cert() {
  generate_cert_config $1
  openssl req -new -key $DIR/$1_key.pem -out $DIR/$1_cert.csr -config $DIR/$1_cert.cfg.generated -batch -sha256
  openssl x509 -req -days 3650 -in $DIR/$1_cert.csr -sha256 -CA $DIR/$2_cert.pem -CAkey \
    $DIR/$2_key.pem -CAcreateserial -out $DIR/$1_cert.pem -extensions v3_req -extfile $DIR/$1_cert.cfg.generated
}

# $1=<certificate name> $2=<CA name>
generate_cert_chain() {
  cat $DIR/$1_cert.pem $DIR/$2_cert.pem > $DIR/$1_cert_chain.pem
}

echo "Generating CA certificate"
generate_ca ca

echo "Generating gateway certificate"
generate_rsa_key gateway ca
generate_x509_cert gateway ca
generate_cert_chain gateway ca

echo "Generating colorteller certificate"
generate_rsa_key colorteller ca
generate_x509_cert colorteller ca
generate_cert_chain colorteller ca

rm $DIR/*.csr
rm $DIR/*.srl


#!/bin/bash

set -ex

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"

# $1= Certificate Name
removeSecret() {
    aws secretsmanager delete-secret --secret-id $1 --force-delete-without-recovery
}

removeSecret "ca_cert"
removeSecret "gateway_cert"
removeSecret "gateway_key"
removeSecret "gateway_cert_chain"
removeSecret "colorteller_cert"
removeSecret "colorteller_key"
removeSecret "colorteller_cert_chain"
rm $DIR/*.pem
rm $DIR/*.generated


#!/bin/bash

set -e

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"

# $1= Certificate Name
deploySecret() {
    secret=`cat $DIR/$1.pem`
    aws secretsmanager create-secret --name $1 --secret-string "$secret"
}

main() {
    deploySecret "ca_cert"
    # deploySecret "gateway_cert"
    deploySecret "gateway_key"
    deploySecret "gateway_cert_chain"
    # deploySecret "colorteller_cert"
    deploySecret "colorteller_key"
    deploySecret "colorteller_cert_chain"
}

main $@


#!/bin/bash

set -ex

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"

aws --profile "${AWS_PROFILE}" --region "${AWS_DEFAULT_REGION}" \
    cloudformation deploy \
    --stack-name "${ENVIRONMENT_NAME}-acm" \
    --capabilities CAPABILITY_IAM \
    --parameter-overrides \
    DomainName="${SERVICES_DOMAIN}" \
    EnvironmentName="${ENVIRONMENT_NAME}" \
    --template-file "${DIR}/acmpca.yaml"


#!/bin/bash

set -ex

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"

aws --profile "${AWS_PROFILE}" --region "${AWS_DEFAULT_REGION}" \
    cloudformation deploy \
    --stack-name "${ENVIRONMENT_NAME}-deploy" \
    --capabilities CAPABILITY_IAM \
    --template-file "${DIR}/deploy.yaml" \
    --parameter-overrides \
    EnvironmentName="${ENVIRONMENT_NAME}"\
    DomainName="${SERVICES_DOMAIN}" \
    ECSServicesDomain="${SERVICES_DOMAIN}" \
    AppMeshMeshName="${MESH_NAME}" \
    TlsState=$1 \
    EnvoyImageName="${ENVOY_IMAGE_NAME}" \
    ColorTellerImageName="${COLOR_TELLER_IMAGE_NAME}"


#!/bin/bash

set -ex

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"

aws --profile "${AWS_PROFILE}" --region "${AWS_DEFAULT_REGION}" \
    cloudformation deploy \
    --stack-name "${ENVIRONMENT_NAME}-mesh" \
    --capabilities CAPABILITY_IAM \
    --parameter-overrides \
    ServiceDomain="${SERVICES_DOMAIN}" \
    EnvironmentName="${ENVIRONMENT_NAME}" \
    MeshName="${MESH_NAME}" \
    TlsState=$1 \
    --template-file "${DIR}/mesh.yaml"


#!/usr/bin/env bash
# vim:syn=sh:ts=4:sw=4:et:ai

set -ex

if [ -z $COLOR_TELLER_IMAGE_NAME ]; then
    echo "COLOR_TELLER_IMAGE_NAME environment variable is not set"
    exit 1
fi

if [ -z $AWS_ACCOUNT_ID ]; then
    echo "AWS_ACCOUNT_ID environment variable is not set."
    exit 1
fi

if [ -z $AWS_DEFAULT_REGION ]; then
    echo "AWS_DEFAULT_REGION environment variable is not set."
    exit 1
fi

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
AWS_CLI_VERSION=$(aws --version 2>&1 | cut -d/ -f2 | cut -d. -f1)

ECR_URL="${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com"
IMAGE="${ECR_URL}/${COLOR_TELLER_IMAGE_NAME}:latest"

ecr_login() {
    if [ $AWS_CLI_VERSION -gt 1 ]; then
        aws ecr get-login-password --region ${AWS_DEFAULT_REGION} | \
            docker login --username AWS --password-stdin ${ECR_URL}
    else
        $(aws ecr get-login --no-include-email)
    fi
}

# build and push
docker build -t $IMAGE $DIR --build-arg GO_PROXY=${GO_PROXY:-"https://proxy.golang.org"}
ecr_login
docker push $IMAGE


#!/bin/bash

set -xe

PASSPHRASE=`echo $CertSecret|jq -r '.Passphrase'`
PASSPHRASE_B64=`echo -n $PASSPHRASE | base64`

# -------- CollorGateway Cert ----------
echo $CertSecret|jq -r '.GatewayCertificate' > /keys/colorgateway_endpoint_cert.pem
echo $CertSecret|jq -r '.GatewayCertificateChain' > /keys/colorgateway_root_cert.pem
echo $CertSecret|jq -r '.GatewayPrivateKey' > /keys/colorgateway_endpoint_enc_pri_key.pem

cat /keys/colorgateway_endpoint_cert.pem /keys/colorgateway_root_cert.pem > /keys/colorgateway_endpoint_cert_chain.pem
openssl rsa -in /keys/colorgateway_endpoint_enc_pri_key.pem -out /keys/colorgateway_endpoint_dec_pri_key.pem -passin pass:$PASSPHRASE_B64
openssl rsa -in /keys/colorgateway_endpoint_dec_pri_key.pem -check

# Clear environment of secret values
unset CertSecret
unset PASSPHRASE
unset PASSPHRASE_B64

# Start Envoy
/usr/bin/agent


#!/usr/bin/env bash

set -e

if [ -z $AWS_ACCOUNT_ID ]; then
    echo "AWS_ACCOUNT_ID environment variable is not set."
    exit 1
fi

if [ -z $AWS_DEFAULT_REGION ]; then
    echo "AWS_DEFAULT_REGION environment variable is not set."
    exit 1
fi

if [ -z $ENVOY_IMAGE ]; then
    echo "ENVOY_IMAGE environment variable is not set to App Mesh Envoy, see https://docs.aws.amazon.com/app-mesh/latest/userguide/envoy.html"
    exit 1
fi

AWS_CLI_VERSION=$(aws --version 2>&1 | cut -d/ -f2 | cut -d. -f1)
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)"
PROJECT_NAME="howto-outlier-detection"
ECR_URL="${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com"
ECR_IMAGE_PREFIX=${ECR_URL}/${PROJECT_NAME}

ecr_login() {
    if [ $AWS_CLI_VERSION -gt 1 ]; then
        aws ecr get-login-password --region ${AWS_DEFAULT_REGION} | \
            docker login --username AWS --password-stdin ${ECR_URL}
    else
        $(aws ecr get-login --no-include-email)
    fi
}

deploy_images() {
    ecr_login
    for app in color-app frontend-app; do
        aws ecr describe-repositories --repository-name $PROJECT_NAME/$app >/dev/null 2>&1 || aws ecr create-repository --repository-name $PROJECT_NAME/$app >/dev/null
        docker build --build-arg GO_PROXY=${GO_PROXY:-"https://proxy.golang.org"} -t ${ECR_IMAGE_PREFIX}/${app} ${DIR}/src/${app}
        docker push ${ECR_IMAGE_PREFIX}/${app}
    done
}

deploy_infra() {
    stack_name="${PROJECT_NAME}-infra"
    aws cloudformation deploy \
        --no-fail-on-empty-changeset \
        --stack-name $stack_name\
        --template-file "${DIR}/infrastructure.yaml" \
        --capabilities CAPABILITY_IAM \
        --parameter-overrides "ProjectName=${PROJECT_NAME}"
}

deploy_app() {
    aws cloudformation deploy \
        --no-fail-on-empty-changeset \
        --stack-name "${PROJECT_NAME}-app" \
        --template-file "${DIR}/application.yaml" \
        --capabilities CAPABILITY_IAM \
        --parameter-overrides "ProjectName=${PROJECT_NAME}" "EnvoyImage=${ENVOY_IMAGE}" \
                              "ColorAppImage=${ECR_IMAGE_PREFIX}/color-app" "FrontAppImage=${ECR_IMAGE_PREFIX}/frontend-app" \
                              "ColorNodeName=mesh/${PROJECT_NAME}/virtualNode/color-node" "FrontNodeName=mesh/${PROJECT_NAME}/virtualNode/front-node" \
                              "BastionKeyName=${KEY_PAIR_NAME}"
}

delete_cfn_stack() {
    stack_name=$1
    aws cloudformation delete-stack --stack-name $stack_name
    echo 'Waiting for the stack to be deleted, this may take a few minutes...'
    aws cloudformation wait stack-delete-complete --stack-name $stack_name
    echo 'Done'
}

delete_images() {
    for app in color-app frontend-app; do
        echo "deleting repository..."
        aws ecr delete-repository \
           --repository-name $PROJECT_NAME/$app \
           --force >/dev/null
    done
}

confirm_service_linked_role() {
    aws iam get-role --role-name AWSServiceRoleForAppMesh >/dev/null
    [[ $? -eq 0 ]] ||
        (echo "Error: no service linked role for App Mesh" && exit 1)
}

print_alb_endpoint() {
    echo "Public ALB endpoint:"
    prefix=$(aws cloudformation describe-stacks \
        --stack-name="${PROJECT_NAME}-app" \
        --query="Stacks[0].Outputs[0].OutputValue" \
        --output=text)
    echo "${prefix}"
}

print_bastion_endpoint() {
    echo "Public bastion endpoint:"
    prefix=$(aws cloudformation describe-stacks \
        --stack-name="${PROJECT_NAME}-app" \
        --query="Stacks[0].Outputs[1].OutputValue" \
        --output=text)
    echo "${prefix}"
}

deploy_stacks() {

    echo "deploy images..."
    deploy_images

    echo "deploy infra..."
    deploy_infra

    echo "deploy app..."
    deploy_app

    #confirm_service_linked_role
    print_alb_endpoint
    print_bastion_endpoint
}

delete_stacks() {
    echo "delete app..."
    delete_cfn_stack "${PROJECT_NAME}-app"

    echo "delete infra..."
    delete_cfn_stack "${PROJECT_NAME}-infra"

    echo "delete images..."
    delete_images

    echo "all resources from this tutorial have been removed"
}

action=${1}
if [ "$action" == "delete" ]; then
    delete_stacks
    exit 0
fi

deploy_stacks


#!/usr/bin/env bash

shopt -s nullglob

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
MESH_DIR="${DIR}/mesh"
PROJECT_NAME="howto-outlier-detection"
MESH_NAME=$PROJECT_NAME
CLOUDMAP_NAMESPACE_NAME=${PROJECT_NAME}.local

print() {
    printf "[$(date)] : %s\n" "$*"
}

err() {
    msg="Error: $1"
    print "${msg}"
    code=${2:-"1"}
    exit ${code}
}

appmesh_cmd="aws appmesh"

create_mesh() {
    cmd=( $appmesh_cmd create-mesh --mesh-name "${MESH_NAME}" \
                --query mesh.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to create mesh" "$?"
    print "--> ${uid}"
}

delete_mesh() {
    cmd=( $appmesh_cmd delete-mesh --mesh-name "${MESH_NAME}" \
                --query mesh.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to delete mesh" "$?"
    print "--> ${uid}"
}

create_vnode() {
    spec_file=$1
    cli_input=$( jq -n \
        --arg NAMESPACE_NAME "${CLOUDMAP_NAMESPACE_NAME}" \
        --arg BACKEND_VS_NAME "color.${CLOUDMAP_NAMESPACE_NAME}" \
        -f "$spec_file" )
    cmd=( $appmesh_cmd create-virtual-node --mesh-name "${MESH_NAME}" \
                --cli-input-json "$cli_input" \
                --query virtualNode.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to create virtual node" "$?"
    print "--> ${uid}"
}

update_vnode() {
    spec_file=$1
    cli_input=$( jq -n \
        --arg NAMESPACE_NAME "${CLOUDMAP_NAMESPACE_NAME}" \
        -f "$spec_file" )
    cmd=( $appmesh_cmd update-virtual-node --mesh-name "${MESH_NAME}" \
                --cli-input-json "$cli_input" \
                --query virtualNode.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to create virtual node" "$?"
    print "--> ${uid}"
}

delete_vnode() {
    vnode_name=$1
    cmd=( $appmesh_cmd delete-virtual-node --mesh-name "${MESH_NAME}" \
                --virtual-node-name "${vnode_name}" \
                --query virtualNode.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to delete virtual node" "$?"
    print "--> ${uid}"
}

create_vservice() {
    spec_file=$1
    vservice_name=$2
    cli_input=$( jq -n \
    --arg VIRTUAL_SERVICE_NAME "${vservice_name}" \
    -f "$spec_file" )
    cmd=( $appmesh_cmd create-virtual-service --mesh-name "${MESH_NAME}" \
                --cli-input-json "$cli_input" \
                --query virtualService.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to create virtual service" "$?"
    print "--> ${uid}"
}

delete_vservice() {
    vservice_name=$1
    cmd=( $appmesh_cmd delete-virtual-service --mesh-name "${MESH_NAME}" \
                --virtual-service-name "${vservice_name}" \
                --query virtualService.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to delete virtual service" "$?"
    print "--> ${uid}"
}

main() {
    action="$1"
    if [ -z "$action" ]; then
        echo "Usage:"
        echo "mesh.sh [up|down|add-outlier-detection|remove-outlier-detection]"
    fi

    case "$action" in
    up)
        create_mesh
        create_vnode "${MESH_DIR}/front-vn.json"
        create_vnode "${MESH_DIR}/color-vn.json"
        create_vservice "${MESH_DIR}/color-vs.json" "color.${PROJECT_NAME}.local"
        ;;
    down)
        delete_vservice "color.${PROJECT_NAME}.local"
        delete_vnode "color-node"
        delete_vnode "front-node"
        delete_mesh
        ;;
    add-outlier-detection)
        update_vnode "${MESH_DIR}/color-vn-with-outlier-detection.json"
        ;;
    remove-outlier-detection)
        update_vnode "${MESH_DIR}/color-vn.json"
        ;;
    *)
        err "Invalid action specified: $action"
        ;;
    esac
}

main $@


#!/usr/bin/env bash

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
APP_DIR="${DIR}/../../examples/apps/colorapp"

${APP_DIR}/src/colorteller/deploy.sh
echo "Done deploying color/teller docker image"


#!/usr/bin/env bash

set -e

if [ -z $AWS_ACCOUNT_ID ]; then
    echo "AWS_ACCOUNT_ID environment variable is not set."
    exit 1
fi

if [ -z $AWS_DEFAULT_REGION ]; then
    echo "AWS_DEFAULT_REGION environment variable is not set."
    exit 1
fi

if [ -z $ENVOY_IMAGE ]; then
    echo "ENVOY_IMAGE environment variable is not set to App Mesh Envoy, see https://docs.aws.amazon.com/app-mesh/latest/userguide/envoy.html"
    exit 1
fi

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
APP_DIR="${DIR}/../../examples/apps/colorapp"
COLOR_TELLER_IMAGE=${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/colorteller

deploy_vpc() {
    aws cloudformation deploy \
        --no-fail-on-empty-changeset \
        --stack-name "${RESOURCE_PREFIX}-vpc" \
        --template-file "${DIR}/vpc.yaml" \
        --capabilities CAPABILITY_IAM
}

deploy_mesh() {
    aws cloudformation deploy \
        --no-fail-on-empty-changeset \
        --stack-name "${RESOURCE_PREFIX}-mesh" \
        --template-file "${DIR}/mesh.yaml" \
        --capabilities CAPABILITY_IAM
}

deploy_app() {
    aws cloudformation deploy \
        --no-fail-on-empty-changeset \
        --stack-name "${RESOURCE_PREFIX}" \
        --template-file "${DIR}/app.yaml" \
        --capabilities CAPABILITY_IAM \
        --parameter-overrides "EnvoyImage=${ENVOY_IMAGE}" "ColorTellerImage=${COLOR_TELLER_IMAGE}"
}

confirm_service_linked_role() {
    aws iam get-role --role-name AWSServiceRoleForAppMesh >/dev/null
    [[ $? -eq 0 ]] \
        || ( echo "Error: no service linked role for App Mesh" && exit 1 )
}

print_endpoint() {
    echo "Public endpoint:"
    prefix=$( aws cloudformation describe-stacks \
        --stack-name="${RESOURCE_PREFIX}" \
        --query="Stacks[0].Outputs[?OutputKey=='ColorGatewayEndpoint'].OutputValue" \
        --output=text )
    echo "${prefix}/color"
}

main() {
    echo "deploy vpc..."
    deploy_vpc

    echo "deploy mesh..."
    deploy_mesh

    echo "deploy app..."
    deploy_app

    confirm_service_linked_role
    print_endpoint
}

delete_cfn_stack() {
    stack_name=$1
    echo "Deleting Cloud Formation stack: \"${stack_name}\"..."
    aws cloudformation delete-stack --stack-name $stack_name
    echo "Waiting for the stack $stack_name to be deleted, this may take a few minutes..."
    aws cloudformation wait stack-delete-complete --stack-name $stack_name
    echo 'Done'
}

delete_stacks() {
    echo "delete stack ${RESOURCE_PREFIX}..."
    delete_cfn_stack ${RESOURCE_PREFIX}
    echo "delete stack ${RESOURCE_PREFIX}-mesh..."
    delete_cfn_stack ${RESOURCE_PREFIX}-mesh
    echo "delete stack ${RESOURCE_PREFIX}-vpc..."
    delete_cfn_stack ${RESOURCE_PREFIX}-vpc
}

action=${1:-"deploy"}
if [ "$action" == "delete" ]; then
    delete_stacks
    exit 0
fi

main $@


#!/bin/bash

set -ex

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"

aws --profile "${AWS_PROFILE}" --region "${AWS_DEFAULT_REGION}" \
    cloudformation deploy \
    --stack-name "${ENVIRONMENT_NAME}-ecr-repositories" \
    --capabilities CAPABILITY_IAM \
    --template-file "${DIR}/ecr-repositories.yaml" \
    --parameter-overrides \
    GatewayImageName="${COLOR_GATEWAY_IMAGE_NAME}" \
    ColorTellerImageName="${COLOR_TELLER_IMAGE_NAME}"


#!/bin/bash

set -ex

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"

aws --profile "${AWS_PROFILE}" --region "${AWS_DEFAULT_REGION}" \
    cloudformation deploy \
    --stack-name "${ENVIRONMENT_NAME}-ecs-cluster" \
    --capabilities CAPABILITY_IAM \
    --template-file "${DIR}/ecs-cluster.yaml"  \
    --parameter-overrides \
    EnvironmentName="${ENVIRONMENT_NAME}" \
    KeyName="${KEY_PAIR_NAME}" \
    ECSServicesDomain="${SERVICES_DOMAIN}"


#!/bin/bash

set -ex

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"

aws --profile "${AWS_PROFILE}" --region "${AWS_DEFAULT_REGION}" \
    cloudformation deploy \
    --stack-name "${ENVIRONMENT_NAME}-ecs-service" \
    --capabilities CAPABILITY_IAM \
    --template-file "${DIR}/ecs-service.yaml"  \
    --parameter-overrides \
    EnvironmentName="${ENVIRONMENT_NAME}" \
    ECSServicesDomain="${SERVICES_DOMAIN}" \
    AppMeshMeshName="${MESH_NAME}" \
    EnvoyImage="${ENVOY_IMAGE}" \
    ColorGatewayImageName="${COLOR_GATEWAY_IMAGE_NAME}" \
    ColorTellerImageName="${COLOR_TELLER_IMAGE_NAME}"


#!/bin/bash

set -ex

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"

aws --profile "${AWS_PROFILE}" --region "${AWS_DEFAULT_REGION}" \
    cloudformation deploy \
    --stack-name "${ENVIRONMENT_NAME}-vpc" \
    --capabilities CAPABILITY_IAM \
    --template-file "${DIR}/vpc.yaml" \
    --parameter-overrides \
    EnvironmentName="${ENVIRONMENT_NAME}"


#!/usr/bin/env bash
# vim:syn=sh:ts=4:sw=4:et:ai

shopt -s nullglob

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
TEST_MESH_DIR="${DIR}"

print() {
    printf "[$(date)] : %s\n" "$*"
}

err() {
    msg="Error: $1"
    print "${msg}"
    code=${2:-"1"}
    exit ${code}
}

sanity_check() {
    if [ -z "${MESH_NAME}" ]; then
        err "MESH_NAME is not set"
    fi
}

appmesh_cmd="aws appmesh"

create_mesh() {
    spec_file=$1
    cmd=( $appmesh_cmd create-mesh --mesh-name "${MESH_NAME}" \
                ${PROFILE_OPT} \
                --cli-input-json "file:///${spec_file}" \
                --query mesh.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to create mesh" "$?"
    print "--> ${uid}"
}

delete_mesh() {
    cmd=( $appmesh_cmd delete-mesh --mesh-name "${MESH_NAME}" \
                ${PROFILE_OPT} \
                --query mesh.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to delete mesh" "$?"
    print "--> ${uid}"
}

create_vnode() {
    spec_file=$1
    vnode_name=$2
    dns_hostname="$3.${SERVICES_DOMAIN}"
    cli_input=$( jq -n \
        --arg ROOT_CA_ARN "${ROOT_CA_ARN}" \
        --arg CERTIFICATE_ARN "${CERTIFICATE_ARN}" \
        --arg DNS_HOSTNAME "$3.${SERVICES_DOMAIN}" \
        --arg COLOR_TELLER_VS "colorteller.${SERVICES_DOMAIN}" \
        -f "$spec_file" )
    cmd=( $appmesh_cmd create-virtual-node --mesh-name "${MESH_NAME}" \
                --virtual-node-name "${vnode_name}" \
                ${PROFILE_OPT} \
                --cli-input-json "$cli_input" \
                --query virtualNode.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to create virtual node" "$?"
    print "--> ${uid}"
}

update_vnode() {
    spec_file=$1
    vnode_name=$2
    dns_hostname="$3.${SERVICES_DOMAIN}"
    cli_input=$( jq -n \
        --arg ROOT_CA_ARN "${ROOT_CA_ARN}" \
        --arg CERTIFICATE_ARN "${CERTIFICATE_ARN}" \
        --arg DNS_HOSTNAME "$3.${SERVICES_DOMAIN}" \
        --arg COLOR_TELLER_VS "colorteller.${SERVICES_DOMAIN}" \
        -f "$spec_file" )
    cmd=( $appmesh_cmd update-virtual-node --mesh-name "${MESH_NAME}" \
                --virtual-node-name "${vnode_name}" \
                ${PROFILE_OPT} \
                --cli-input-json "$cli_input" \
                --query virtualNode.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to create virtual node" "$?"
    print "--> ${uid}"
}

delete_vnode() {
    vnode_name=$1
    cmd=( $appmesh_cmd delete-virtual-node --mesh-name "${MESH_NAME}" \
                --virtual-node-name "${vnode_name}" \
                ${PROFILE_OPT} \
                --query virtualNode.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to delete virtual node" "$?"
    print "--> ${uid}"
}

create_vservice() {
    spec_file=$1
    vservice_name=$2
    cmd=( $appmesh_cmd create-virtual-service --mesh-name "${MESH_NAME}" \
                --virtual-service-name "${vservice_name}" \
                ${PROFILE_OPT} \
                --cli-input-json "file:///${spec_file}" \
                --query virtualService.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to create virtual service" "$?"
    print "--> ${uid}"
}

delete_vservice() {
    vservice_name=$1
    cmd=( $appmesh_cmd delete-virtual-service --mesh-name "${MESH_NAME}" \
                --virtual-service-name "${vservice_name}" \
                ${PROFILE_OPT} \
                --query virtualService.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to delete virtual service" "$?"
    print "--> ${uid}"
}

create_vrouter() {
    spec_file=$1
    vrouter_name=$2
    cmd=( $appmesh_cmd create-virtual-router --mesh-name "${MESH_NAME}" \
                --virtual-router-name "${vrouter_name}" \
                ${PROFILE_OPT} \
                --cli-input-json "file:///${spec_file}" \
                --query virtualRouter.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to create virtual router" "$?"
    print "--> ${uid}"
}

delete_vrouter() {
    vrouter_name=$1
    cmd=( $appmesh_cmd delete-virtual-router --mesh-name "${MESH_NAME}" \
                --virtual-router-name "${vrouter_name}" \
                ${PROFILE_OPT} \
                --query virtualRouter.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to delete virtual router" "$?"
    print "--> ${uid}"
}

create_route() {
    spec_file=$1
    vrouter_name=$2
    route_name=$3
    cmd=( $appmesh_cmd create-route --mesh-name "${MESH_NAME}" \
                --virtual-router-name "${vrouter_name}" \
                --route-name "${route_name}" \
                ${PROFILE_OPT} \
                --cli-input-json "file:///${spec_file}" \
                --query route.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to create route" "$?"
    print "--> ${uid}"
}

delete_route() {
    vrouter_name=$1
    route_name=$2
    cmd=( $appmesh_cmd delete-route --mesh-name "${MESH_NAME}" \
                --virtual-router-name "${vrouter_name}" \
                --route-name "${route_name}" \
                ${PROFILE_OPT} \
                --query route.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to delete route" "$?"
    print "--> ${uid}"
}

create_vgateway() {
    spec_file=$1
    vgateway_name=$2
    cli_input=$( jq -n \
    --arg CERTIFICATE_ARN "${CERTIFICATE_ARN}" \
    -f "$spec_file" )
    cmd=( $appmesh_cmd create-virtual-gateway \
                --mesh-name "${MESH_NAME}" \
                --virtual-gateway-name "${vgateway_name}" \
                --cli-input-json "$cli_input" \
                --query virtualGateway.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to create virtual gateway" "$?"
    print "--> ${uid}"
}

delete_vgateway() {
    vgateway_name=$1
    cmd=( $appmesh_cmd delete-virtual-gateway \
                --mesh-name "${MESH_NAME}" \
                --virtual-gateway-name "${vgateway_name}" \
                --query virtualGateway.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to delete virtual gateway" "$?"
    print "--> ${uid}"
}

create_gateway_route() {
    spec_file=$1
    vgateway_name=$2
    gatewayroute_name=$3
    cli_input=$( jq -n \
        --arg VIRTUALSERVICE_NAME "$4" \
        -f "$spec_file" )
    cmd=( $appmesh_cmd create-gateway-route \
                --mesh-name "${MESH_NAME}" \
                --virtual-gateway-name "${vgateway_name}" \
                --gateway-route-name "${gatewayroute_name}" \
                --cli-input-json "$cli_input" \
                --query gatewayRoute.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to create gateway route" "$?"
    print "--> ${uid}"
}

delete_gateway_route() {
    vgateway_name=$1
    gatewayroute_name=$2
    cmd=( $appmesh_cmd delete-gateway-route \
                --mesh-name "${MESH_NAME}" \
                --virtual-gateway-name "${vgateway_name}" \
                --gateway-route-name "${gatewayroute_name}" \
                --query gatewayRoute.metadata.uid --output text )
    print "${cmd[@]}"
    uid=$("${cmd[@]}") || err "Unable to delete gateway route" "$?"
    print "--> ${uid}"
}

main() {
    action="$1"
    if [ -z "$action" ]; then
        echo "Usage:"
        echo "mesh.sh [up|down]"
    fi
    sanity_check

    case "$action" in
    up)
        create_mesh "${TEST_MESH_DIR}/mesh.json"
        create_vnode "${TEST_MESH_DIR}/colorgateway-vn.json" "ColorGateway" "colorgateway"
        create_vnode "${TEST_MESH_DIR}/colorteller-vn.json" "ColorTellerWhite" "colorteller"

        create_vrouter "${TEST_MESH_DIR}/colorteller-vr.json" "colorteller-vr"
        create_route "${TEST_MESH_DIR}/colorteller-route.json" "colorteller-vr" "colorteller-route"
        create_vservice "${TEST_MESH_DIR}/colorteller-vs.json" "colorteller.${SERVICES_DOMAIN}"

        ;;
    down)
        delete_vservice "colorteller.${SERVICES_DOMAIN}"
        delete_route "colorteller-vr" "colorteller-route"
        delete_vrouter "colorteller-vr"
        delete_vnode "ColorGateway"
        delete_vnode "ColorTellerWhite"
        delete_mesh
        ;;
    add_virtual_gateway)
        create_vgateway "${TEST_MESH_DIR}/publicgateway-vg.json" "publicgateway-vg"
        create_gateway_route "${TEST_MESH_DIR}/publicgateway-route.json" "publicgateway-vg" "publicgateway-route" "colorteller.${SERVICES_DOMAIN}"
        ;;
    add_red_node_and_routes)
        create_vnode "${TEST_MESH_DIR}/colorteller-vn.json" "ColorTellerRed" "colorteller-red"
        delete_route "colorteller-vr" "colorteller-route"
        create_route "${TEST_MESH_DIR}/colorteller-route1.json" "colorteller-vr" "colorteller-route"
        create_route "${TEST_MESH_DIR}/colorteller-route2.json" "colorteller-vr" "colorteller-route2"
        ;;
    delete_virtual_gateway_and_red_node_and_routes)
        delete_gateway_route "publicgateway-vg" "publicgateway-route"
        delete_vgateway "publicgateway-vg"
        delete_route "colorteller-vr" "colorteller-route2"
        delete_vnode "ColorTellerRed"
        ;;
    update_colorteller-white-vn)
        update_vnode "$2" "ColorTellerWhite" "colorteller"
        ;;
    update_colorteller-red-vn)
        update_vnode "$2" "ColorTellerRed" "colorteller-red"
        ;;
    update_colorgateway-vn)
        update_vnode "$2" "ColorGateway" "colorgateway"
        ;;
    *)
        err "Invalid action specified: $action"
        ;;
    esac
}

main $@


#!/usr/bin/env bash
# vim:syn=sh:ts=4:sw=4:et:ai

set -ex

if [ -z $COLOR_GATEWAY_IMAGE_NAME ]; then
    echo "COLOR_GATEWAY_IMAGE_NAME environment variable is not set"
    exit 1
fi

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"

ECR_URL="${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com"

IMAGE="${ECR_URL}/${COLOR_GATEWAY_IMAGE_NAME}:latest"

# build
docker build -t $IMAGE $DIR --build-arg GO_PROXY=${GO_PROXY:-"https://proxy.golang.org"}

# ECR login
AWS_CLI_VERSION=$(aws --version 2>&1 | cut -d/ -f2 | cut -d. -f1)

if [ $AWS_CLI_VERSION -gt 1 ]; then
    aws ecr get-login-password --region ${AWS_DEFAULT_REGION} | \
        docker login --username AWS --password-stdin ${ECR_URL}
else
    $(aws ecr get-login --no-include-email)
fi

# push
docker push $IMAGE


#!/usr/bin/env bash
# vim:syn=sh:ts=4:sw=4:et:ai

set -ex

if [ -z $COLOR_TELLER_IMAGE_NAME ]; then
    echo "COLOR_TELLER_IMAGE_NAME environment variable is not set"
    exit 1
fi

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"

ECR_URL="${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com"

IMAGE="${ECR_URL}/${COLOR_TELLER_IMAGE_NAME}:latest"

# build
docker build -t $IMAGE $DIR --build-arg GO_PROXY=${GO_PROXY:-"https://proxy.golang.org"}

# ECR login
AWS_CLI_VERSION=$(aws --version 2>&1 | cut -d/ -f2 | cut -d. -f1)

if [ $AWS_CLI_VERSION -gt 1 ]; then
    aws ecr get-login-password --region ${AWS_DEFAULT_REGION} | \
        docker login --username AWS --password-stdin ${ECR_URL}
else
    $(aws ecr get-login --no-include-email)
fi

# push
docker push $IMAGE


#!/bin/bash

set -ex

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"

aws --profile "${AWS_PROFILE}" --region "${AWS_DEFAULT_REGION}" \
    cloudformation deploy \
    --stack-name "${ENVIRONMENT_NAME}-ecr-repositories" \
    --capabilities CAPABILITY_IAM \
    --template-file "${DIR}/ecr-repositories.yaml" \
    --parameter-overrides \
    ColorTellerImageName="${COLOR_TELLER_IMAGE_NAME}" \
    ColorAppEnvoyImageName="${COLOR_APP_ENVOY_IMAGE_NAME}"


#!/bin/bash

set -ex

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"

aws --profile "${AWS_PROFILE}" --region "${AWS_DEFAULT_REGION}" \
    cloudformation deploy \
    --stack-name "${ENVIRONMENT_NAME}-ecs-service" \
    --capabilities CAPABILITY_IAM \
    --template-file "${DIR}/ecs-service.yaml"  \
    --parameter-overrides \
    EnvironmentName="${ENVIRONMENT_NAME}" \
    ECSServicesDomain="${SERVICES_DOMAIN}" \
    AppMeshMeshName="${MESH_NAME}" \
    EnvoyImage="${ENVOY_IMAGE}" \
    ColorTellerImageName="${COLOR_TELLER_IMAGE_NAME}" \
    ColorAppEnvoyImageName="${COLOR_APP_ENVOY_IMAGE_NAME}"


#!/bin/bash

set -ex

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
TEST_MESH_DIR="${DIR}"

sanity_check() {
    if [ -z "${MESH_NAME}" ]; then
        err "MESH_NAME is not set"
    fi
    if [ -z "${ENVIRONMENT_NAME}" ]; then
        err "ENVIRONMENT_NAME is not set"
    fi
    if [ -z "${SERVICES_DOMAIN}" ]; then
        err "SERVICES_DOMAIN is not set"
    fi
    if [ -z "${AWS_DEFAULT_REGION}" ]; then
        err "AWS_DEFAULT_REGION is not set"
    fi
}

# $1 ColorTellerGreenRouteWeight
# $2 EnableClientValidationFlag
# $3 ColorGatewayTlsValidationPath
callCloudformation() {
    aws --profile "${AWS_PROFILE}" --region "${AWS_DEFAULT_REGION}" \
        cloudformation deploy \
        --stack-name "${ENVIRONMENT_NAME}-mesh" \
        --capabilities CAPABILITY_IAM \
        --template-file "${DIR}/mesh.yaml" \
        --parameter-overrides \
        MeshName="${MESH_NAME}" \
        ServicesDomain="${SERVICES_DOMAIN}" \
        ColorTellerGreenRouteWeight=$1 \
        EnableClientValidationFlag=$2 \
        ColorGatewayTlsValidationPath=$3
}

main() {
    action="$1"
    if [ -z "$action" ]; then
        echo "Usage:"
        echo "mesh.sh [up|addGreen|updateGateway|updateGateway2]"
    fi
    sanity_check

    case "$action" in
    up)
        callCloudformation 0 "false"
        ;;
    addGreen)
        callCloudformation 1 "false"
        ;;
    updateGateway)
        callCloudformation 1 "true" "/keys/ca_1_cert.pem"
        ;;
    updateGateway2)
        callCloudformation 1 "true" "/keys/ca_1_ca_2_bundle.pem"
        ;;
    *)
        err "Invalid action specified: $action"
        ;;
    esac
}

main $@


#!/usr/bin/env bash
# vim:syn=sh:ts=4:sw=4:et:ai

set -ex

if [ -z $AWS_ACCOUNT_ID ]; then
    echo "AWS_ACCOUNT_ID environment variable is not set."
    exit 1
fi

if [ -z $AWS_DEFAULT_REGION ]; then
    echo "AWS_DEFAULT_REGION environment variable is not set."
    exit 1
fi

if [ -z $COLOR_TELLER_IMAGE_NAME ]; then
    echo "COLOR_TELLER_IMAGE_NAME environment variable is not set"
    exit 1
fi

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
AWS_CLI_VERSION=$(aws --version 2>&1 | cut -d/ -f2 | cut -d. -f1)

ECR_URL="${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com"
IMAGE="${ECR_URL}/${COLOR_TELLER_IMAGE_NAME}:latest"

ecr_login() {
    if [ $AWS_CLI_VERSION -gt 1 ]; then
        aws ecr get-login-password --region ${AWS_DEFAULT_REGION} | \
            docker login --username AWS --password-stdin ${ECR_URL}
    else
        $(aws ecr get-login --no-include-email)
    fi
}

# build and push
docker build -t $IMAGE $DIR --build-arg GO_PROXY=${GO_PROXY:-"https://proxy.golang.org"}
ecr_login
docker push $IMAGE


#!/usr/bin/env bash
# vim:syn=sh:ts=4:sw=4:et:ai

set -ex

if [ -z $AWS_ACCOUNT_ID ]; then
    echo "AWS_ACCOUNT_ID environment variable is not set."
    exit 1
fi

if [ -z $AWS_DEFAULT_REGION ]; then
    echo "AWS_DEFAULT_REGION environment variable is not set."
    exit 1
fi

if [ -z $COLOR_APP_ENVOY_IMAGE_NAME ]; then
    echo "COLOR_APP_ENVOY_IMAGE_NAME environment variable is not set"
    exit 1
fi

if [ -z $ENVOY_IMAGE ]; then
    echo "ENVOY_IMAGE environment variable is not set"
    exit 1
fi

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
AWS_CLI_VERSION=$(aws --version 2>&1 | cut -d/ -f2 | cut -d. -f1)

ENVOY_REGISTRY_ID=840364872350
DEMO_ECR_URL="${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com"
IMAGE="${DEMO_ECR_URL}/${COLOR_APP_ENVOY_IMAGE_NAME}:latest"

ecr_login() {
    REGISTRY_ID=$1

    if [ $AWS_CLI_VERSION -gt 1 ]; then
	REGISTRY_URL="${REGISTRY_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com"
        aws ecr get-login-password --region ${AWS_DEFAULT_REGION} | \
            docker login --username AWS --password-stdin ${REGISTRY_URL}
    else
	$(aws ecr get-login --no-include-email --registry-id ${REGISTRY_ID})
    fi
}

# login to envoy registry for pull
ecr_login $ENVOY_REGISTRY_ID

# build and push
docker build -t $IMAGE $DIR \
    --build-arg ENVOY_IMAGE=$ENVOY_IMAGE \
    --build-arg AWS_DEFAULT_REGION=$AWS_DEFAULT_REGION
ecr_login $AWS_ACCOUNT_ID
docker push $IMAGE


#!/bin/bash

# $1=Secret Name
getSecret() {
    aws secretsmanager get-secret-value --secret-id $1 --region $AWS_DEFAULT_REGION | jq -r .SecretString > /keys/${1}.pem
    echo "Added $1 to container"
}

getCertificates() {
    if [[ $CERTIFICATE_NAME = "colorgateway" ]];
    then
        getSecret "ca_1_cert"
        getSecret "ca_2_cert"
        getSecret "ca_1_ca_2_bundle"
    fi
    if [[ $CERTIFICATE_NAME = "colorteller_green" ]];
    then
        getSecret "colorteller_green_cert"
        getSecret "colorteller_green_key"
        getSecret "colorteller_green_cert_chain"
    fi
    if [[ $CERTIFICATE_NAME = "colorteller_white" ]];
    then
        getSecret "colorteller_white_cert"
        getSecret "colorteller_white_key"
        getSecret "colorteller_white_cert_chain"
    fi
}

# Get the appropriate certificates
getCertificates
# Start Envoy
/usr/bin/agent


#!/bin/bash

set -e

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"

# $1=<CA name>
generate_ca() {
  openssl genrsa -out $DIR/$1_key.pem 2048
  openssl req -new -key $DIR/$1_key.pem -out $DIR/$1_cert.csr -config $DIR/$1_cert.cfg -batch -sha256
  openssl x509 -req -days 3650 -in $DIR/$1_cert.csr -signkey $DIR/$1_key.pem -out $DIR/$1_cert.pem \
    -extensions v3_ca -extfile $DIR/$1_cert.cfg
}

# $1=<certificate name>
generate_rsa_key() {
  openssl genrsa -out $DIR/$1_key.pem 2048
}

# $1=<certificate_name>
generate_cert_config() {
  sed -e "s/\${services_domain}/${SERVICES_DOMAIN}/" $DIR/$1_cert.cfg > $DIR/$1_cert.cfg.generated
}

# $1=<certificate name> $2=<CA name>
generate_x509_cert() {
  generate_cert_config $1
  openssl req -new -key $DIR/$1_key.pem -out $DIR/$1_cert.csr -config $DIR/$1_cert.cfg.generated -batch -sha256
  openssl x509 -req -days 3650 -in $DIR/$1_cert.csr -sha256 -CA $DIR/$2_cert.pem -CAkey \
    $DIR/$2_key.pem -CAcreateserial -out $DIR/$1_cert.pem -extensions v3_req -extfile $DIR/$1_cert.cfg.generated
}

# $1=<certificate name> $2=<CA name>
generate_cert_chain() {
  cat $DIR/$1_cert.pem $DIR/$2_cert.pem > $DIR/$1_cert_chain.pem
}

# $1=<CA name> $2=<CA name>
generate_cert_bundle() {
  cat $DIR/$1_cert.pem $DIR/$2_cert.pem > $DIR/$1_$2_bundle.pem
}

# Generate cert for the CA.
echo "Generating CA certificates."
generate_ca ca_1
generate_ca ca_2

# Generate RSA cert for the white color teller.
echo "Generating backend certificate."
generate_rsa_key colorteller_white ca_1
generate_x509_cert colorteller_white ca_1
generate_cert_chain colorteller_white ca_1

# Generate cert for the green color teller.
echo "Generating frontend certificate."
generate_rsa_key colorteller_green ca_2
generate_x509_cert colorteller_green ca_2
generate_cert_chain colorteller_green ca_2

echo "Generating CA Bundle"
generate_cert_bundle ca_1 ca_2

rm $DIR/*.csr
rm $DIR/*.srl


#!/bin/bash

set -ex

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"

# $1= Certificate Name
removeSecret() {
    aws secretsmanager delete-secret --secret-id $1 --force-delete-without-recovery
}

main() {
    # Color Gateway
    removeSecret "ca_1_cert"
    removeSecret "ca_2_cert"
    removeSecret "ca_1_ca_2_bundle"
    # White Colorteller
    removeSecret "colorteller_white_cert"
    removeSecret "colorteller_white_key"
    removeSecret "colorteller_white_cert_chain"
    # Green Colorteller
    removeSecret "colorteller_green_cert"
    removeSecret "colorteller_green_key"
    removeSecret "colorteller_green_cert_chain"
    rm $DIR/*.pem
    rm $DIR/*.generated
}

main $@


#!/bin/bash

set -e

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"

# $1= Certificate Name
deploySecret() {
    secret=`cat $DIR/$1.pem`
    aws secretsmanager create-secret --name $1 --secret-string "$secret"
}

main() {
    # Color Gateway
    deploySecret "ca_1_cert"
    deploySecret "ca_2_cert"
    deploySecret "ca_1_ca_2_bundle"
    # White Colorteller
    deploySecret "colorteller_white_cert"
    deploySecret "colorteller_white_key"
    deploySecret "colorteller_white_cert_chain"
    # Green Colorteller
    deploySecret "colorteller_green_cert"
    deploySecret "colorteller_green_key"
    deploySecret "colorteller_green_cert_chain"
}

main $@


#!/bin/bash

set -ex

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"

aws --profile "${AWS_PROFILE}" --region "${AWS_DEFAULT_REGION}" \
    cloudformation deploy \
    --stack-name "${ENVIRONMENT_NAME}-ecr-repositories" \
    --capabilities CAPABILITY_IAM \
    --template-file "${DIR}/ecr-repositories.yaml" \
    --parameter-overrides \
    ColorTellerImageName="${COLOR_TELLER_IMAGE_NAME}"


#!/bin/bash

set -ex

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"

aws --profile "${AWS_PROFILE}" --region "${AWS_DEFAULT_REGION}" \
    cloudformation deploy \
    --stack-name "${ENVIRONMENT_NAME}-ecs-service" \
    --capabilities CAPABILITY_IAM \
    --template-file "${DIR}/ecs-service.yaml"  \
    --parameter-overrides \
    EnvironmentName="${ENVIRONMENT_NAME}" \
    ECSServicesDomain="${SERVICES_DOMAIN}" \
    AppMeshMeshName="${MESH_NAME}" \
    EnvoyImage="${ENVOY_IMAGE}" \
    ColorTellerImageName="${COLOR_TELLER_IMAGE_NAME}"


#!/bin/bash

set -ex

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"

aws --profile "${AWS_PROFILE}" --region "${AWS_DEFAULT_REGION}" \
    cloudformation deploy \
    --stack-name "${ENVIRONMENT_NAME}-mesh" \
    --capabilities CAPABILITY_IAM \
    --template-file "${DIR}/mesh.yaml" \
    --parameter-overrides \
    MeshName="${MESH_NAME}" \
    ServicesDomain="${SERVICES_DOMAIN}" \
    CertificateAuthorityArn="${ROOT_CA_ARN}" \
    CertificateArn="${CERTIFICATE_ARN}"


#!/usr/bin/env bash
# vim:syn=sh:ts=4:sw=4:et:ai

set -ex

if [ -z $COLOR_TELLER_IMAGE_NAME ]; then
    echo "COLOR_TELLER_IMAGE_NAME environment variable is not set"
    exit 1
fi

if [ -z $AWS_ACCOUNT_ID ]; then
    echo "AWS_ACCOUNT_ID environment variable is not set."
    exit 1
fi

if [ -z $AWS_DEFAULT_REGION ]; then
    echo "AWS_DEFAULT_REGION environment variable is not set."
    exit 1
fi

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
AWS_CLI_VERSION=$(aws --version 2>&1 | cut -d/ -f2 | cut -d. -f1)

ECR_URL="${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com"
IMAGE="${ECR_URL}/${COLOR_TELLER_IMAGE_NAME}:latest"

ecr_login() {
    if [ $AWS_CLI_VERSION -gt 1 ]; then
        aws ecr get-login-password --region ${AWS_DEFAULT_REGION} | \
            docker login --username AWS --password-stdin ${ECR_URL}
    else
        $(aws ecr get-login --no-include-email)
    fi
}

# build and push
docker build -t $IMAGE $DIR --build-arg GO_PROXY=${GO_PROXY:-"https://proxy.golang.org"}
ecr_login
docker push $IMAGE


#!/bin/bash

set -e

SDK_VENDOR_PATH="./scripts/aws_sdk_model_override/aws-sdk-go"
SDK_MODEL_OVERRIDE_DST_PATH="${SDK_VENDOR_PATH}/models"
SDK_MODEL_OVERRIDE_SRC_PATH="./scripts/aws_sdk_model_override/models"

# Clone the SDK to the vendor path (removing an old one if necessary)
rm -rf "${SDK_VENDOR_PATH}"
git clone --depth 1 https://github.com/aws/aws-sdk-go.git "${SDK_VENDOR_PATH}"

# Override the SDK models
cp -r "${SDK_MODEL_OVERRIDE_SRC_PATH}"/* "${SDK_MODEL_OVERRIDE_DST_PATH}"/.

# Generate the SDK
pushd "${SDK_VENDOR_PATH}"
make generate
popd

# Use the vendored version of aws-sdk-go
go mod edit -replace github.com/aws/aws-sdk-go="${SDK_VENDOR_PATH}"


#!/usr/bin/env bash
set -euo pipefail

K8S_VERSION="${K8S_VERSION:="1.22.x"}"
KUBEBUILDER_ASSETS="${KUBEBUILDER_ASSETS:="${HOME}/.kubebuilder/bin"}"

main() {
    tools
    kubebuilder
}

tools() {
    if ! echo "$PATH" | grep -q "${GOPATH:-undefined}/bin\|$HOME/go/bin"; then
        echo "Go workspace's \"bin\" directory is not in PATH. Run 'export PATH=\"\$PATH:\${GOPATH:-\$HOME/go}/bin\"'."
        exit 1
    fi

    go install github.com/golang/mock/mockgen@v1.6.0
    go install sigs.k8s.io/kustomize/kustomize/v4@v4.5.7
    go install sigs.k8s.io/controller-runtime/tools/setup-envtest@v0.0.0-20220421205612-c162794a9b12
}

kubebuilder() {
    mkdir -p $KUBEBUILDER_ASSETS
    arch=$(go env GOARCH)
    ## Kubebuilder does not support darwin/arm64, so use amd64 through Rosetta instead
    if [[ $(go env GOOS) == "darwin" ]] && [[ $(go env GOARCH) == "arm64" ]]; then
        arch="amd64"
    fi
    ln -sf $(setup-envtest use -p path "${K8S_VERSION}" --arch="${arch}" --bin-dir="${KUBEBUILDER_ASSETS}")/* ${KUBEBUILDER_ASSETS}
    find $KUBEBUILDER_ASSETS
}

main "$@"


## Note: mocks for interfaces from this project should be along with the original package.
##       mocks for interfaces from 3rd-party project should be put inside ./mocks folder.
## mockgen version v1.5.0
mockgen -package=mock_client -destination=./mocks/controller-runtime/client/client_mocks.go sigs.k8s.io/controller-runtime/pkg/client Client
mockgen -package=services -destination=./pkg/aws/services/eks_mocks.go -source=./pkg/aws/services/eks.go
mockgen -package=services -destination=./pkg/aws/services/vpclattice_mocks.go -source=./pkg/aws/services/vpclattice.go
mockgen -package=aws -destination=./pkg/aws/cloud_mocks.go -source=./pkg/aws/cloud.go
mockgen -package=lattice -destination=./pkg/deploy/lattice/service_network_manager_mock.go -source=./pkg/deploy/lattice/service_network_manager.go
mockgen -package=lattice -destination=./pkg/deploy/lattice/target_group_manager_mock.go -source=./pkg/deploy/lattice/target_group_manager.go
mockgen -package=lattice -destination=./pkg/deploy/lattice/targets_manager_mock.go -source=./pkg/deploy/lattice/targets_manager.go
mockgen -package=lattice -destination=./pkg/deploy/lattice/service_manager_mock.go -source=./pkg/deploy/lattice/service_manager.go
mockgen -package=lattice -destination=./pkg/deploy/lattice/listener_manager_mock.go -source=./pkg/deploy/lattice/listener_manager.go
mockgen -package=lattice -destination=./pkg/deploy/lattice/rule_manager_mock.go -source=./pkg/deploy/lattice/rule_manager.go
# need some manual update to remote core for stack_mock.go
mockgen -package=core -destination=./pkg/model/core/stack_mock.go -source=./pkg/model/core/stack.go
mockgen -package=services -destination=./pkg/aws/services/vpclattice_service_api_mock.go -source=./scripts/aws_sdk_model_override/aws-sdk-go/service/vpclattice/vpclatticeiface/interface.go


#!/bin/sh

# When Running the k8s Controller by GoLand IDE locally, it is required to set the environment variables, this script will generate a file called `envFile`
# that contains all needed environment variables, this `envFile` file can be use by GoLand "EnvFile" plugin
# When config the "green arrow"(how we `run` or `debug` this project) in  GoLand, we could set a "before launch" task to run this script `load_env_variables.sh`, and set the "EnvFile" plugin to load the `envFile` file
# "EnvFile" is a plugin, you can install it from GoLand plugin marketplace

echo "Setting environment variables"

> envFile

# Set KUBEBUILDER_ASSETS if not set
if [ -z "$KUBEBUILDER_ASSETS" ]; then
  KUBEBUILDER_ASSETS=${HOME}/.kubebuilder/bin
fi
echo "KUBEBUILDER_ASSETS=$KUBEBUILDER_ASSETS" >> envFile

# Set CLUSTER_NAME if not set
if [ -z "$CLUSTER_NAME" ]; then
  CLUSTER_NAME=$(kubectl config view --minify -o jsonpath='{.clusters[].name}' | rev | cut -d"/" -f1 | rev | cut -d"." -f1)
fi
echo "CLUSTER_NAME=$CLUSTER_NAME" >> envFile

# Set CLUSTER_VPC_ID if not set
if [ -z "$CLUSTER_VPC_ID" ]; then
  CLUSTER_VPC_ID=$(aws eks describe-cluster --name ${CLUSTER_NAME} | jq -r ".cluster.resourcesVpcConfig.vpcId")
fi
echo "CLUSTER_VPC_ID=$CLUSTER_VPC_ID" >> envFile

# Set AWS_ACCOUNT_ID if not set
if [ -z "$AWS_ACCOUNT_ID" ]; then
  AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
fi
echo "AWS_ACCOUNT_ID=$AWS_ACCOUNT_ID" >> envFile

if [ -z "$REGION" ]; then
  REGION=us-west-2
fi
echo "REGION=$REGION" >> envFile

GATEWAY_API_CONTROLLER_LOGLEVEL=debug
echo "GATEWAY_API_CONTROLLER_LOGLEVEL=$GATEWAY_API_CONTROLLER_LOGLEVEL" >> envFile


#!/usr/bin/env bash

set -eo pipefail

DEFAULT_IMAGE_REPOSITORY="public.ecr.aws/aws-application-networking-k8s/aws-gateway-controller"
DEFAULT_CHART_REGISTRY="public.ecr.aws/aws-application-networking-k8s"
DEFAULT_CHART_REPOSITORY="aws-gateway-controller-chart"

USAGE="
Usage:
  $(basename "$0")

Publishes the controller image and helm chart for the AWS Gateway controller.

When run as part of a CI job, when the source code repo is tagged with a semver
format '^v\d+\.\d+\.\d+$'

Environment variables:
  SKIP_BUILD_IMAGE:         If set to 1, does not build and publish the
                            controller container image, only the Helm chart.
  PULL_BASE_REF:            The value of tag on the source code repository that triggered the
                            postsubmit CI job. The value will either be in the format '^v\d+\.\d+\.\d+$'
                            or 'stable'.
  IMAGE_REPOSITORY:         Name for the ECR Public repository to push controller images to
                            Default: $DEFAULT_IMAGE_REPOSITORY
  IMAGE_TAG:                Controller container image tag
                            Default: \$PULL_BASE_REF
  QUIET:                    Build controller container image quietly (<true|false>)
                            Default: false
  CHART_REGISTRY:           Name for the OCI Artifact Registry to push to
                            Default: $DEFAULT_CHART_REGISTRY
  CHART_REPOSITORY:         Name for the Helm repository to push to
                            Default: $DEFAULT_CHART_REPOSITORY
  CHART_TAG:                Controller Helm Chart tag
                            Default: Based on \$PULL_BASE_REF
  ECR_PUBLISH_ROLE_ARN      IAM Role ARN for the Role that has permission to
                            publish to the image and Helm chart repositories on ECR Public. This role is
                            assumed by this script in order to upload artifacts.
"

# find out the service name and semver tag from the CI environment variable if not specified
VERSION=${VERSION:-$PULL_BASE_REF}

# Important Directory references based on prowjob configuration.
SCRIPTS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
WORKSPACE_DIR=$SCRIPTS_DIR/..

# Check all the dependencies are present in container.
source "$SCRIPTS_DIR/lib/common.sh"
source "$SCRIPTS_DIR/lib/login.sh"
check_is_installed git
check_is_installed jq
check_is_installed yq

if [[ $PULL_BASE_REF = stable ]]; then
  pushd $WORKSPACE_DIR 1>/dev/null
  echo "Triggering for the stable branch"
  _semver_tag=$(git describe --tags --abbrev=0 2>/dev/null)
  if [[ $? -ne 0 ]]; then
    echo "Unable to find semver tag on the 'stable' branch"
    exit 2
  fi
  echo "Semver tag on stable branch is $_semver_tag"

  if ! (echo "$_semver_tag" | grep -Eq "^v[0-9]+\.[0-9]+\.[0-9]+$"); then
    echo "semver tag on stable branch should have format ^v[0-9]+\.[0-9]+\.[0-9]+$"
    exit 2
  fi

  _major_version=$(echo "$_semver_tag" | cut -d"." -f1)
  if [[ -z "$_major_version" ]]; then
    echo "Unable to determine major version from latest semver tag on 'stable' branch"
    exit 2
  fi

  VERSION="$_major_version-stable"
  popd 1>/dev/null
else
  echo "release-controller.sh] Validating that controller image repository & tag in release artifacts is consistent with semver tag"
  pushd $WORKSPACE_DIR/helm 1>/dev/null
    _repository=$(yq eval ".image.repository" values.yaml)
    _image_tag=$(yq eval ".image.tag" values.yaml)
    if [[ $_repository != public.ecr.aws/aws-application-networking-k8s/aws-gateway-controller ]]; then
      echo "release-controller.sh] [ERROR] 'image.repository' value in release artifacts should be $DEFAULT_IMAGE_REPOSITORY. Current value: $_repository"
      exit 1
    fi
    if [[ $_image_tag != $VERSION ]]; then
      echo "release-controller.sh] [ERROR] 'image.tag' value in release artifacts should be $VERSION. Current value: $_image_tag"
      exit 1
    fi
    echo "release-controller.sh] Validation successful"
  popd 1>/dev/null
fi

IMAGE_REPOSITORY=${IMAGE_REPOSITORY:-$DEFAULT_IMAGE_REPOSITORY}
IMAGE_TAG=${IMAGE_TAG:-$VERSION}
CHART_REPOSITORY=${CHART_REPOSITORY:-$DEFAULT_CHART_REPOSITORY}
CHART_REGISTRY=${CHART_REGISTRY:-$DEFAULT_CHART_REGISTRY}

ECR_PUBLISH_ROLE_ARN=${ECR_PUBLISH_ROLE_ARN:-"undefined"}

if [[ "$ECR_PUBLISH_ROLE_ARN" = undefined ]]; then
    error_msg "Please set the ECR_PUBLISH_ROLE_ARN environment variable to the IAM Role ARN"
    error_msg  "that has permissions to upload artifacts to the ECR Public registry for"
    error_msg "$IMAGE_REPOSITORY"
    exit 2
fi

echo "VERSION is $VERSION"

# TODO(jaypipes): If we move to Prow setup like ACK, uncomment this. For now,
# just pass in ECR_PUBLISH_ROLE_ARN manually.
# ASSUME_EXIT_VALUE=0
# ECR_PUBLISH_ROLE_ARN=$(aws ssm get-parameter --name /ack/prow/cd/public_ecr/publish_role --query Parameter.Value --output text 2>/dev/null) || ASSUME_EXIT_VALUE=$?
# if [ "$ASSUME_EXIT_VALUE" -ne 0 ]; then
#   echo "release-controller.sh] [SETUP] Could not find the iam role to publish images to public ecr repository"
# exit 1
# fi
export ECR_PUBLISH_ROLE_ARN
echo "release-controller.sh] [SETUP] exported ECR_PUBLISH_ROLE_ARN"

ASSUME_COMMAND=$(aws --output json sts assume-role --role-arn $ECR_PUBLISH_ROLE_ARN --role-session-name 'publish-images' --duration-seconds 3600 | jq -r '.Credentials | "export AWS_ACCESS_KEY_ID=\(.AccessKeyId)\nexport AWS_SECRET_ACCESS_KEY=\(.SecretAccessKey)\nexport AWS_SESSION_TOKEN=\(.SessionToken)\n"')
eval $ASSUME_COMMAND
echo "release-controller.sh] [SETUP] Assumed ECR_PUBLISH_ROLE_ARN"

# Setup the destination repository for buildah and helm
perform_buildah_and_helm_login

# Do not rebuild controller image for stable releases
if [[ "$SKIP_IMAGE_BUILD" != "1" ]]; then
    if ! (echo "$VERSION" | grep -Eq "stable$"); then
      # Determine parameters for docker-build command

      cd "$WORKSPACE_DIR"

      CONTROLLER_GIT_COMMIT=$(git rev-parse HEAD)
      QUIET=${QUIET:-"false"}
      BUILD_DATE=$(date +%Y-%m-%dT%H:%M)
      CONTROLLER_IMAGE_DOCKERFILE_PATH=$WORKSPACE_DIR/Dockerfile

      IMG="$IMAGE_REPOSITORY:$IMAGE_TAG"
      DOCKER_BUILD_CONTEXT="$WORKSPACE_DIR"

      if [[ $QUIET = "false" ]]; then
          echo "building aws-gateway-controller image with tag: ${IMG}"
          echo " git commit: $CONTROLLER_GIT_COMMIT"
      fi

      # build controller image
      buildah bud \
        --quiet="$QUIET" \
        -t "$IMG" \
        -f "$CONTROLLER_IMAGE_DOCKERFILE_PATH" \
        --build-arg service_controller_git_version="$VERSION" \
        --build-arg service_controller_git_commit="$CONTROLLER_GIT_COMMIT" \
        --build-arg build_date="$BUILD_DATE" \
        "${DOCKER_BUILD_CONTEXT}"

      if [ $? -ne 0 ]; then
        exit 2
      fi

      echo "Pushing aws-gateway-controller image with tag: ${IMG}"

      buildah push "${IMG}"

      if [ $? -ne 0 ]; then
        exit 2
      fi
    fi
fi

export HELM_EXPERIMENTAL_OCI=1

echo "Generating Helm chart package for $CHART_REGISTRY/$CHART_REPOSITORY@$VERSION ... "
helm package "$WORKSPACE_DIR"/helm/
# Path to tarballed package (eg. `aws-application-networking-controller-v0.0.1.tgz`)
CHART_PACKAGE="$CHART_REPOSITORY-$VERSION.tgz"

helm push "$CHART_PACKAGE" "oci://$CHART_REGISTRY"


#!/usr/bin/env bash

# aws.sh contains functions for running common AWS command line methods.

LIB_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"

source "$LIB_DIR/common.sh"
source "$LIB_DIR/config.sh"
source "$LIB_DIR/logging.sh"

AWS_CLI_VERSION=${DEFAULT_AWS_CLI_VERSION:-"2.0.52"}

# daws() executes the AWS Python CLI tool from a Docker container.
#
# Instead of relying on developers having a particular version of the AWS
# Python CLI tool, this method allows a specific version of the CLI tool to be
# executed within a Docker container.
#
# You call the daws function just like you were calling the `aws` CLI tool.
#
# Usage:
#
#   daws SERVICE COMMAND [OPTIONS]
#
# Example:
#
#   daws ecr describe-repositories --repository-name my-repo
#
# To use a specific version of the AWS CLI, set the ACK_AWS_CLI_IMAGE_VERSION
# environment variable, otherwise the value of DEFAULT_AWS_CLI_VERSION is used.
daws() {
    local profile="$(get_aws_profile)"
    local identity_file="$(get_aws_token_file)"
    local default_region="$(get_aws_region)"

    aws_cli_profile_env=$([ ! -z "$profile" ] && echo "--env AWS_PROFILE=$profile")
    aws_cli_web_identity_env="$([ ! -z "$identity_file" ] && \
        echo "--env AWS_WEB_IDENTITY_TOKEN_FILE=/root/aws_token --env AWS_ROLE_ARN -v $identity_file:/root/aws_token:ro" )"
    aws_cli_img="amazon/aws-cli:$AWS_CLI_VERSION"

    docker run --rm -v ~/.aws:/root/.aws:z $(echo $aws_cli_profile_env) $(echo $aws_cli_web_identity_env) --env AWS_DEFAULT_REGION=$default_region -v $(pwd):/aws "$aws_cli_img" "$@"
}

# ensure_aws_credentials() calls the STS::GetCallerIdentity API call and
# verifies that there is a local identity for running AWS commands
ensure_aws_credentials() {
    daws sts get-caller-identity --query "Account" >/dev/null ||
        ( error_msg "No AWS credentials found. Please run \`aws configure\` to set up the CLI for your credentials" && exit 1)
}

# generate_aws_temp_creds function will generate temporary AWS credentials which
# are valid for 3600 seconds
aws_generate_temp_creds() {
    local __uuid=$(uuidgen | cut -d'-' -f1 | tr '[:upper:]' '[:lower:]')

    local assumed_role=$(get_assumed_role_arn)

    local json=$(daws sts assume-role \
           --role-arn "$assumed_role"  \
           --role-session-name tmp-role-"$__uuid" \
           --duration-seconds 3600 \
           --output json || exit 1)

    AWS_ACCESS_KEY_ID=$(echo "${json}" | jq --raw-output ".Credentials[\"AccessKeyId\"]")
    AWS_SECRET_ACCESS_KEY=$(echo "${json}" | jq --raw-output ".Credentials[\"SecretAccessKey\"]")
    AWS_SESSION_TOKEN=$(echo "${json}" | jq --raw-output ".Credentials[\"SessionToken\"]")
}

aws_account_id() {
    local json=$(daws sts get-caller-identity --output json || exit 1)
    echo "${json}" | jq --raw-output ".Account"
}

ensure_binaries() {
    check_is_installed "docker"
    check_is_installed "jq"
    check_is_installed "uuidgen"
}

ensure_binaries


#!/usr/bin/env bash

# common.sh contains commonly used functions, meant to be imported by other
# bash scripts.

LIB_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"

source "$LIB_DIR/logging.sh"

# check_is_installed checks to see if the supplied executable is installed and
# exits if not. An optional second argument is an extra message to display when
# the supplied executable is not installed.
#
# Usage:
#
#   check_is_installed PROGRAM [ MSG ]
#
# Example:
#
#   check_is_installed kind "You can install kind with the helper scripts/install-kind.sh"
check_is_installed() {
    local __name="$1"
    local __extra_msg="$2"
    if ! is_installed "$__name"; then
        error_msg "Missing required binary in PATH: '$__name'"
        error_msg "Please install $__name before running this script."
        if [[ -n $__extra_msg ]]; then
            error_msg ""
            error_msg "$__extra_msg"
            error_msg ""
        fi
        exit 1
    fi
}

is_installed() {
    local __name="$1"
    if $(which $__name >/dev/null 2>&1); then
        return 0
    else
        return 1
    fi
}


#!/usr/bin/env bash

# config.sh contains functions for extracting configuration elements from an ACK
# test config file, providing sane defaults when possible.

set -Eeo pipefail

LIB_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
SCRIPTS_DIR="$LIB_DIR/.."

TEST_CONFIG_PATH=${TEST_CONFIG_PATH:-"$SCRIPTS_DIR/../test_config.yaml"}

ASSUMED_ROLE_ARN="${ASSUMED_ROLE_ARN:-""}"

source "$LIB_DIR/common.sh"
source "$LIB_DIR/logging.sh"

_get_config_field() {
    local __field_path="$1"
    local __default="${2:-""}"

    if [[ "$__default" != "" ]]; then
        yq "$__field_path // \"$__default\"" $TEST_CONFIG_PATH 2>/dev/null
    else
        yq "$__field_path // \"\"" $TEST_CONFIG_PATH 2>/dev/null
    fi
}

_get_config_boolean() {
    # Booleans must be handled differently because the yq "Alternative" feature
    # returns the alternative value if the value of the field is "false" -
    # instead of simply returning "false" (as we would expect)
    local __field_path="$1"
    local __default="${2:-""}"

    local ret=$(yq "$__field_path" $TEST_CONFIG_PATH 2>/dev/null)
    if [[ "$ret" == "null" ]]; then
        echo $__default
    fi
    echo $ret
}

get_cluster_create() { _get_config_boolean ".cluster.create"; }
get_cluster_name() { _get_config_field ".cluster.name"; }
get_cluster_k8s_version() { _get_config_field ".cluster.k8s_version"; }
get_cluster_configuration_file_name() { _get_config_field ".cluster.configuration.file_name" "kind-two-node-cluster.yaml"; }
get_cluster_additional_controllers() { _get_config_field ".cluster.configuration.additional_controllers"; }
get_aws_profile() { _get_config_field ".aws.profile"; }
get_aws_token_file() { _get_config_field ".aws.token_file"; }
get_aws_region() { _get_config_field ".aws.region" "us-west-2"; }
get_assumed_role_arn() {
    [[ ! -z "${ASSUMED_ROLE_ARN}" ]] && echo "${ASSUMED_ROLE_ARN}" || _get_config_field ".aws.assumed_role_arn";
}
get_test_markers() { _get_config_field ".tests.markers"; }
get_test_methods() { _get_config_field ".tests.methods"; }
get_run_tests_locally() { _get_config_field ".tests.run_locally"; }
get_is_local_build() { _get_config_boolean ".local_build" "false"; }
get_debug_enabled() { _get_config_boolean ".debug.enabled" "false"; }
get_dump_controller_logs() { _get_config_boolean ".debug.dump_controller_logs" "false"; }

get_test_config_path() { echo "$TEST_CONFIG_PATH"; }

ensure_config_file_exists() {
    [[ ! -f "$TEST_CONFIG_PATH" ]] && { error_msg "Config file does not exist at path $TEST_CONFIG_PATH"; exit 1; } || :
}

ensure_required_fields() {
    # Allow if the ASSUMED_ROLE_ARN is substituting
    [[ -z $(_get_config_field ".aws.assumed_role_arn") && -z ${ASSUMED_ROLE_ARN} ]] && { error_msg "Required config path \`.aws.assumed_role_arn\` not provided"; exit 1; } || :

    local required_field_paths=( ".cluster.create" )
    for path in "${required_field_paths[@]}"; do
        [[ -z $(_get_config_boolean $path) ]] && { error_msg "Required config path \`$path\` not provided"; exit 1; } || :
    done
}

ensure_binaries() {
    check_is_installed "yq"
}

ensure_binaries
ensure_config_file_exists
ensure_required_fields


#!/usr/bin/env bash

# logging.sh contains functions for writing log messages to the console for
# three different severities: debug, info and error.

# Prints out a message with an optional second argument indicating the
# "indentation level" for the message. If the indentation level argument is
# missing, we look for the existence of an environs variable called
# "indent_level" and use that.
_indented_msg() {
    local __msg=${1:-}
    local __indent_level=${2:-}
    local indent=""
    if [ -n "$__indent_level" ]; then
        indent="$( for each in $( seq 0 $__indent_level ); do printf " "; done )"
    fi

    local timestamp=$(date -Is)

    echo "$timestamp $__indent$__msg"
}

# debug_msg prints out a supplied message if the ACK_TEST_DEBUGGING_MODE environ
# variable is set.
debug_msg() {
    local __debug="${ACK_TEST_DEBUGGING_MODE:-""}"
    if [ ! -n "$__debug" ]; then
        return 0
    fi

    local __msg=${1:-}
    local __indent=${2:-}
    local __debug_prefix="${DEBUG_PREFIX:-"[DEBUG] "}"
    _indented_msg "$__debug_prefix$__msg" $__indent
}

# info_msg prints out a supplied message if the DEBUG environs variable is
# set.
info_msg() {
    local __msg=${1:-}
    local __indent=${2:-}
    local __info_prefix="${INFO_PREFIX:-"[INFO] "}"
    _indented_msg "$__info_prefix$__msg" $__indent
}

# debug_msg prints out a supplied message if the DEBUG environs variable is
# set.
error_msg() {
    local __msg=${1:-}
    local __indent=${2:-}
    local __error_prefix="${ERROR_PREFIX:-"[ERROR] "}"
    >&2 _indented_msg "$__error_prefix$__msg" $__indent
}


#!/usr/bin/env bash

# login.sh contains functions for logging into container repositories.
# Note: These functions are not placed inside tools specific file like
# helm.sh, because those files ensure binaries(ex: kind) that are not
# really needed for simple actions like repository login.
# A future refactor can make those files more modular and then login
# functions can be refactored in tool specific file like buildah.sh
# and helm.sh

perform_buildah_and_helm_login() {
  #ecr-public only exists in us-east-1 so use that region specifically
  local __pw=$(aws ecr-public get-login-password --region us-east-1)
  echo "$__pw" | buildah login -u AWS --password-stdin public.ecr.aws
  export HELM_EXPERIMENTAL_OCI=1
  echo "$__pw" | helm registry login -u AWS --password-stdin public.ecr.aws
}

ensure_binaries() {
    check_is_installed "aws"
    check_is_installed "buildah" "See https://github.com/containers/buildah/blob/main/install.md"
    check_is_installed "helm"
}

ensure_binaries


#!/bin/bash
if [ $0 != "/root/scripts/setup.sh" ]; then
	echo "Script will not execute outside of Docker context."
	exit
fi
/usr/bin/apt-get update
/usr/bin/apt-get install -y apache2 libapache2-mod-python software-properties-common tzdata
/usr/bin/add-apt-repository -y ppa:certbot/certbot
/usr/bin/apt-get update
/usr/bin/apt-get install -y python-certbot-apache
/usr/sbin/a2enmod ssl cgi rewrite proxy_http allowmethods
/usr/bin/certbot --apache --email $CERTBOT_EMAIL -d $CERTBOT_HOSTNAME --agree-tos --non-interactive
/usr/sbin/a2ensite 0-api.conf
/usr/sbin/a2ensite 1-api-80.conf
/usr/sbin/a2ensite 2-api-internal.conf
/usr/sbin/a2ensite 3-api-internal-80.conf
/usr/sbin/a2dissite 000-default
/usr/sbin/a2dissite 000-default-le-ssl

/bin/chown -R www-data: /var/www/state
/bin/chown -R www-data: /var/log/apache2

Copy_ServerName=`/bin/egrep -o '^ServerName.*$' /etc/apache2/sites-available/000-default-le-ssl.conf`
/bin/sed -i "s|##ServerName##|$Copy_ServerName|" /etc/apache2/sites-available/0-api.conf
/bin/sed -i "s|##ServerName##|$Copy_ServerName|" /etc/apache2/sites-available/1-api-80.conf
Copy_SSLCertificateFile=`/bin/egrep -o '^SSLCertificateFile.*$' /etc/apache2/sites-available/000-default-le-ssl.conf`
/bin/sed -i "s|##SSLCertificateFile##|$Copy_SSLCertificateFile|" /etc/apache2/sites-available/0-api.conf
Copy_SSLCertificateKeyFile=`/bin/egrep -o '^SSLCertificateKeyFile.*$' /etc/apache2/sites-available/000-default-le-ssl.conf`
/bin/sed -i "s|##SSLCertificateKeyFile##|$Copy_SSLCertificateKeyFile|" /etc/apache2/sites-available/0-api.conf
Copy_Include=`/bin/egrep -o '^Include.*$' /etc/apache2/sites-available/000-default-le-ssl.conf`
/bin/sed -i "s|##Include##|$Copy_Include|" /etc/apache2/sites-available/0-api.conf


#!/bin/bash
# --------------------------------------------------------------------------------------------------
#
# This script is intended to be used to bump the version of the CDK modules, update package.json,
# package-lock.json, and create a commit.
#
# to start a version bump, run:
#     bump.sh <version | version Type>
#
# If a version is not provided, the 'minor' version will be bumped.
# The version can be an explicit version _or_ one of:
# 'major', 'minor', 'patch', 'premajor', 'preminor', 'prepatch', or 'prerelease'.
#
# --------------------------------------------------------------------------------------------------
set -euo pipefail
scriptdir=$(cd $(dirname $0) && pwd)
cd ${scriptdir}
yarn install --frozen-lockfile
if [[ "${LEGACY_BUMP:-}" == "" ]]; then
  #  if we're using 'cdk-release' for the bump, build that package, including all of its dependencies
  npx lerna run build --include-dependencies --scope @aws-cdk/cdk-release
fi
VERBOSE=1 exec ${scriptdir}/scripts/bump.js ${1:-minor}


#!/bin/bash
set -euo pipefail

mkdir -p .tools
[[ ! -d .tools/git-secrets ]] && {
    echo "============================================================================================="
    echo "Downloading git-secrets..."
    (cd .tools && git clone --depth 1 https://github.com/awslabs/git-secrets.git)
}

# As the name implies, git-secrets heavily depends on git:
#
# a) the config is stored and fetched using 'git config'.
# b) the search is performed using 'git grep' (other search methods don't work
#    properly, see https://github.com/awslabs/git-secrets/issues/66)
#
# When we run in a CodeBuild build, we don't have a git repo, unfortunately. So
# when that's the case, 'git init' one on the spot, add all files to it (which
# because of the .gitignore will exclude dependencies and generated files) and
# then call 'git-secrets' as usual.
git rev-parse --git-dir > /dev/null 2>&1 || {
    git init --quiet
    git add -A .
}

# AWS config needs to be added to this repository's config
.tools/git-secrets/git-secrets --register-aws

.tools/git-secrets/git-secrets --scan
echo "git-secrets scan ok"


#!/bin/bash
set -euo pipefail
exec npx yarn install --frozen-lockfile


#!/bin/bash
# creates symlinks under node_modules for all packages in this repo
# can be used to work against this code base.
set -euo pipefail
root="$(cd $(dirname $0) && pwd)"

mkdir -p node_modules node_modules/.bin

modules="$(find ${root}/packages -name package.json | grep -v node_modules | grep -v init-templates | xargs -n1 dirname)"
for module in ${modules}; do
  if [[ $(basename $(dirname $module)) == @* ]]; then
    # This is a @scope/based package
    scope=$(basename $(dirname $module))
    link_dir=node_modules/$(basename $(dirname $module))
    mkdir -p $link_dir
  else
    link_dir=node_modules
  fi

  module_dir=${link_dir}/$(basename $module)
  echo "${module} => ${module_dir}"
  rm -fr ${module_dir}
  ln -fs ${module} ${link_dir}

  # Symlink executable scripts into place as well. This is not completely
  # according to spec (we look in the bin/ directory instead of the { "scripts"
  # } entry in package.json but it's quite a bit easier.
  if [[ -d $module/bin ]]; then
    for script in $(find $module/bin -perm +111); do
      echo "${script} => node_modules/.bin/$(basename $script)"
      ln -fs ${script} node_modules/.bin
    done
  fi
done