From 7f95b1b33ebec67b802a88d065ff28da92a05981 Mon Sep 17 00:00:00 2001 From: Greg Ochmanski <84852800+GrzesiekO@users.noreply.github.com> Date: Tue, 17 Sep 2024 22:12:19 +0200 Subject: [PATCH] feat(helix-core): add ARM64 support (#239) Co-authored-by: Henry Kiem --- .../perforce/helix-core/p4_configure.sh | 151 ++++++++++++++---- .../helix-core/perforce_arm64.pkr.hcl | 98 ++++++++++++ ...{perforce.pkr.hcl => perforce_x86.pkr.hcl} | 0 modules/perforce/helix-core/data.tf | 4 + modules/perforce/helix-core/main.tf | 13 +- modules/perforce/helix-core/plan | Bin 0 -> 13399 bytes modules/perforce/helix-core/pln | Bin 0 -> 13515 bytes modules/perforce/helix-core/variables.tf | 10 ++ modules/perforce/helix-swarm/README.md | 78 ++++----- modules/perforce/helix-swarm/efs.tf | 2 +- samples/simple-build-pipeline/README.md | 78 ++++----- samples/simple-build-pipeline/dns.tf | 14 +- samples/simple-build-pipeline/local.tf | 1 - samples/simple-build-pipeline/main.tf | 17 +- samples/simple-build-pipeline/variables.tf | 4 + 15 files changed, 337 insertions(+), 133 deletions(-) create mode 100644 assets/packer/perforce/helix-core/perforce_arm64.pkr.hcl rename assets/packer/perforce/helix-core/{perforce.pkr.hcl => perforce_x86.pkr.hcl} (100%) create mode 100644 modules/perforce/helix-core/plan create mode 100644 modules/perforce/helix-core/pln create mode 100644 samples/simple-build-pipeline/variables.tf diff --git a/assets/packer/perforce/helix-core/p4_configure.sh b/assets/packer/perforce/helix-core/p4_configure.sh index f5bb3f9c..90113fd3 100644 --- a/assets/packer/perforce/helix-core/p4_configure.sh +++ b/assets/packer/perforce/helix-core/p4_configure.sh @@ -1,8 +1,5 @@ #!/bin/bash - -#Currently this needs proper EBS volume locations from /dev with proper nvme names $1 is a hxlogs $2 hxmetadata $3 hxdepots $4 perforce server type p4d_master/ p4d_replica - # Log file location LOG_FILE="/var/log/p4_configure.log" @@ -80,7 +77,6 @@ setup_helix_auth() { >> $LOG_FILE 2>> $LOG_FILE } - # Function to create and mount XFS on EBS prepare_ebs_volume() { local ebs_volume=$1 @@ -99,7 +95,6 @@ prepare_ebs_volume() { } # Function to copy SiteTags template and update with AWS regions -> This file will be updated by Ansible with replica AWS regions. - prepare_site_tags() { log_message "Setting up SiteTags for installation" local source="/hxdepots/sdp/Server/Unix/p4/common/config/SiteTags.cfg.sample" @@ -131,21 +126,98 @@ prepare_site_tags() { # Starting the script log_message "Starting the p4 configure script." -# Check if the script received 7 arguments -if [[ "$#" < 6 || "$#" > 7 ]]; then - log_message "Incorrect usage. Expected 6 or 7 arguments, got $#." - log_message "Usage: $0 " +# Function to print help +print_help() { + echo "Usage: $0 [OPTIONS]" + echo "Options:" + echo " --p4d_type Specify the type of Helix Core server (p4d_master, p4d_replica, p4d_edge)" + echo " --username AWS Secrets Manager secret ID for the Helix Core admin username" + echo " --password AWS Secrets Manager secret ID for the Helix Core admin password" + echo " --auth Helix Authentication Service URL" + echo " --fqdn Fully Qualified Domain Name for the Helix Core server" + echo " --hx_logs Path for Helix Core logs" + echo " --hx_metadata Path for Helix Core metadata" + echo " --hx_depots Path for Helix Core depots" + echo " --help Display this help and exit" +} + +# Parse command-line options +OPTS=$(getopt -o '' --long p4d_type:,username:,password:,auth:,fqdn:,hx_logs:,hx_metadata:,hx_depots:,help -n 'parse-options' -- "$@") + +if [ $? != 0 ]; then + log_message "Failed to parse options" exit 1 fi -# Assigning arguments to variables -EBS_LOGS=$1 -EBS_METADATA=$2 -EBS_DEPOTS=$3 -P4D_TYPE=$4 -[[ "$P4D_TYPE" == "p4d_commit" ]] && P4D_TYPE="p4d_master" || P4D_TYPE="$4" -P4D_ADMIN_USERNAME_SECRET_ID=$5 -P4D_ADMIN_PASS_SECRET_ID=$6 +eval set -- "$OPTS" + +while true; do + case "$1" in + --p4d_type) + P4D_TYPE=$([ "$2" = "p4d_commit" ] && echo "p4d_master" || echo "$2") + case "$P4D_TYPE" in + p4d_master|p4d_replica|p4d_edge) + shift 2 + ;; + *) + log_message "Invalid value for --p4d_type: $2" + print_help + exit 1 + ;; + esac + ;; + --username) + P4D_ADMIN_USERNAME_SECRET_ID="$2" + shift 2 + ;; + --password) + P4D_ADMIN_PASS_SECRET_ID="$2" + shift 2 + ;; + --auth) + HELIX_AUTH_SERVICE_URL="$2" + shift 2 + ;; + --fqdn) + FQDN="$2" + shift 2 + ;; + --hx_logs) + EBS_LOGS="$2" + log_message "EBS_LOGS: $EBS_LOGS" + shift 2 + ;; + --hx_metadata) + EBS_METADATA="$2" + log_message "EBS_METADATA: $EBS_METADATA" + shift 2 + ;; + --hx_depots) + EBS_DEPOTS="$2" + log_message "EBS_DEPOTS: $EBS_DEPOTS" + shift 2 + ;; + --help) + print_help + exit 0 + ;; + --) + shift + break + ;; + *) + log_message "Invalid option: $1" + print_help + exit 1 + ;; + esac +done + +# Validate P4D_TYPE +if [[ "$P4D_TYPE" != "p4d_master" && "$P4D_TYPE" != "p4d_replica" && "$P4D_TYPE" != "p4d_edge" ]]; then + log_message "Invalid P4D_TYPE: $P4D_TYPE. Valid options are p4d_master, p4d_replica, or p4d_edge." + exit 1 +fi # Fetch credentials for admin user from secrets manager P4D_ADMIN_USERNAME=$(resolve_aws_secret $P4D_ADMIN_USERNAME_SECRET_ID) @@ -211,15 +283,35 @@ perform_operations() { log_message "Operation completed successfully." } -# Check if EBS volumes or FSx mount points are provided for all required paths -if ( [ -e "$EBS_LOGS" ] || is_fsx_mount "$EBS_LOGS" ) && \ - ( [ -e "$EBS_METADATA" ] || is_fsx_mount "$EBS_METADATA" ) && \ - ( [ -e "$EBS_DEPOTS" ] || is_fsx_mount "$EBS_DEPOTS" ); then - perform_operations -else - log_message "One or more required paths are not valid EBS volumes or FSx mount points. No operations performed. Will continue with single disk setup" + +# Maximum number of attempts (added due to terraform not mounting EBS fast enough at instance boot) +MAX_ATTEMPTS=3 + +# Counter for attempts +attempt=1 + +# Flag to track if the condition is met +condition_met=false + +while [ $attempt -le $MAX_ATTEMPTS ] && [ "$condition_met" = false ]; do + # Check if EBS volumes or FSx mount points are provided for all required paths + if ( [ -e "$EBS_LOGS" ] || is_fsx_mount "$EBS_LOGS" ) && \ + ( [ -e "$EBS_METADATA" ] || is_fsx_mount "$EBS_METADATA" ) && \ + ( [ -e "$EBS_DEPOTS" ] || is_fsx_mount "$EBS_DEPOTS" ); then + condition_met=true + perform_operations + else + log_message "Attempt $attempt: One or more required paths are not valid EBS volumes or FSx mount points." + sleep 5 # Wait for 1 second before the next attempt + ((attempt++)) + fi +done + +if [ "$condition_met" = false ]; then + log_message "All attempts failed. No operations performed. Will continue with single disk setup." fi + log_message "$0" "$@" log_message "Starting the configuration part after mounting was done later will configure the commit or replica depending on configuration." @@ -278,12 +370,12 @@ fi FILE_PATH="/p4/ssl/config.txt" # Retrieve the EC2 instance DNS name -if [ -z $7 ]; then +if [ -z $FQDN ]; then log_message "FQDN was not provided. Retrieving from EC2 metadata." EC2_DNS_NAME=$(curl -s http://169.254.169.254/latest/meta-data/public-hostname --header "X-aws-ec2-metadata-token: $TOKEN") else - log_message "FQDN was provided: $7" - EC2_DNS_NAME=$7 + log_message "FQDN was provided: $FQDN" + EC2_DNS_NAME=$FQDN fi # Check if the DNS name was successfully retrieved @@ -382,11 +474,10 @@ else fi # Check if the HELIX_AUTH_SERVICE_URL is empty. if not, configure Helix Authentication Extension -if [-z $8]; then +if [-z $HELIX_AUTH_SERVICE_URL ]; then log_message "Helix Authentication Service URL was not provided. Skipping configuration." else - log_message "Configuring Helix Authentication Extension against $8" - HELIX_AUTH_SERVICE_URL=$8 + log_message "Configuring Helix Authentication Extension against $HELIX_AUTH_SERVICE_URL" setup_helix_auth "$P4PORT" "$P4D_ADMIN_USERNAME" "$P4D_ADMIN_PASS" "$HELIX_AUTH_SERVICE_URL" "oidc" "email" "email" fi diff --git a/assets/packer/perforce/helix-core/perforce_arm64.pkr.hcl b/assets/packer/perforce/helix-core/perforce_arm64.pkr.hcl new file mode 100644 index 00000000..7096649f --- /dev/null +++ b/assets/packer/perforce/helix-core/perforce_arm64.pkr.hcl @@ -0,0 +1,98 @@ +packer { + required_plugins { + amazon = { + version = ">= 0.0.2" + source = "github.com/hashicorp/amazon" + } + } +} + +locals { + timestamp = regex_replace(timestamp(), "[- TZ:]", "") + ami_prefix = "p4_al2023" +} + +variable "region" { + type = string + default = "us-west-2" +} + +variable "vpc_id" { + type = string + default = null +} + +variable "subnet_id" { + type = string + default = null +} + +variable "associate_public_ip_address" { + type = bool + default = true +} + +variable "ssh_interface" { + type = string + default = "public_ip" +} + +source "amazon-ebs" "al2023" { + region = var.region + ami_name = "${local.ami_prefix}-${local.timestamp}" + instance_type = "t4g.medium" + + vpc_id = var.vpc_id + subnet_id = var.subnet_id + + associate_public_ip_address = var.associate_public_ip_address + ssh_interface = var.ssh_interface + + source_ami_filter { + filters = { + name = "al2023-ami-2023.5.*" + architecture = "arm64" + root-device-type = "ebs" + virtualization-type = "hvm" + } + most_recent = true + owners = ["amazon"] + } + + ssh_username = "ec2-user" +} + +build { + name = "P4_SDP_AWS" + sources = [ + "source.amazon-ebs.al2023" + ] + + provisioner "shell" { + inline = [ + "cloud-init status --wait", + "sudo dnf install -y git sendmail nfs-utils s-nail unzip cronie" + ] + } + + provisioner "shell" { + script = "${path.root}/p4_setup.sh" + execute_command = "sudo sh {{.Path}}" + } + + provisioner "file" { + source = "${path.root}/p4_configure.sh" + destination = "/tmp/p4_configure.sh" + } + + provisioner "shell" { + inline = ["mkdir -p /home/ec2-user/gpic_scripts", + "sudo mv /tmp/p4_configure.sh /home/ec2-user/gpic_scripts" + ] + } + + provisioner "shell" { + inline = ["sudo chmod +x /home/ec2-user/gpic_scripts/p4_configure.sh"] + } + +} diff --git a/assets/packer/perforce/helix-core/perforce.pkr.hcl b/assets/packer/perforce/helix-core/perforce_x86.pkr.hcl similarity index 100% rename from assets/packer/perforce/helix-core/perforce.pkr.hcl rename to assets/packer/perforce/helix-core/perforce_x86.pkr.hcl diff --git a/modules/perforce/helix-core/data.tf b/modules/perforce/helix-core/data.tf index 1816611c..d39bc874 100644 --- a/modules/perforce/helix-core/data.tf +++ b/modules/perforce/helix-core/data.tf @@ -22,4 +22,8 @@ data "aws_ami" "helix_core_ami" { name = "virtualization-type" values = ["hvm"] } + filter { + name = "architecture" + values = [var.instance_architecture] + } } diff --git a/modules/perforce/helix-core/main.tf b/modules/perforce/helix-core/main.tf index bfee77b7..82035cc7 100644 --- a/modules/perforce/helix-core/main.tf +++ b/modules/perforce/helix-core/main.tf @@ -35,14 +35,15 @@ resource "aws_instance" "helix_core_instance" { user_data = <<-EOT #!/bin/bash - /home/ec2-user/gpic_scripts/p4_configure.sh /dev/sdf /dev/sdg /dev/sdh \ - ${var.server_type} \ - ${var.helix_core_super_user_username_secret_arn == null ? awscc_secretsmanager_secret.helix_core_super_user_username[0].secret_id : var.helix_core_super_user_username_secret_arn} \ - ${var.helix_core_super_user_password_secret_arn == null ? awscc_secretsmanager_secret.helix_core_super_user_password[0].secret_id : var.helix_core_super_user_password_secret_arn} \ - ${var.FQDN == null ? "" : var.FQDN} \ - ${var.helix_authentication_service_url == null ? "" : var.helix_authentication_service_url} + /home/ec2-user/gpic_scripts/p4_configure.sh --hx_logs /dev/sdf --hx_metadata /dev/sdg --hx_depots /dev/sdh \ + --p4d_type ${var.server_type} \ + --username ${var.helix_core_super_user_username_secret_arn == null ? awscc_secretsmanager_secret.helix_core_super_user_username[0].secret_id : var.helix_core_super_user_username_secret_arn} \ + --password ${var.helix_core_super_user_password_secret_arn == null ? awscc_secretsmanager_secret.helix_core_super_user_password[0].secret_id : var.helix_core_super_user_password_secret_arn} \ + --fqdn ${var.FQDN == null ? "" : var.FQDN} \ + --auth ${var.helix_authentication_service_url == null ? "" : var.helix_authentication_service_url} EOT + vpc_security_group_ids = concat(var.existing_security_groups, [aws_security_group.helix_core_security_group[0].id]) metadata_options { diff --git a/modules/perforce/helix-core/plan b/modules/perforce/helix-core/plan new file mode 100644 index 0000000000000000000000000000000000000000..dd02cb100aaeb3fffb1516c7913f3e386d33230a GIT binary patch literal 13399 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 [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | 5.59.0 | +| [aws](#requirement\_aws) | 5.66.0 | | [random](#requirement\_random) | 3.6.2 | ## Providers @@ -24,46 +24,46 @@ No modules. | Name | Type | |------|------| -| [aws_cloudwatch_log_group.helix_swarm_redis_service_log_group](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/cloudwatch_log_group) | resource | -| [aws_cloudwatch_log_group.helix_swarm_service_log_group](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/cloudwatch_log_group) | resource | -| [aws_ecs_cluster.helix_swarm_cluster](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/ecs_cluster) | resource | -| [aws_ecs_cluster_capacity_providers.helix_swarm_cluster_fargate_providers](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/ecs_cluster_capacity_providers) | resource | -| [aws_ecs_service.helix_swarm_service](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/ecs_service) | resource | -| [aws_ecs_task_definition.helix_swarm_task_definition](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/ecs_task_definition) | resource | -| [aws_efs_access_point.helix_swarm_efs_access_point](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/efs_access_point) | resource | -| [aws_efs_access_point.redis_efs_access_point](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/efs_access_point) | resource | -| [aws_efs_file_system.helix_swarm_efs_file_system](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/efs_file_system) | resource | -| [aws_efs_mount_target.helix_swarm_efs_mount_target](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/efs_mount_target) | resource | -| [aws_iam_policy.helix_swarm_default_policy](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/iam_policy) | resource | -| [aws_iam_policy.helix_swarm_efs_policy](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/iam_policy) | resource | -| [aws_iam_policy.helix_swarm_ssm_policy](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/iam_policy) | resource | -| [aws_iam_role.helix_swarm_default_role](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/iam_role) | resource | -| [aws_iam_role.helix_swarm_task_execution_role](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/iam_role) | resource | -| [aws_lb.helix_swarm_alb](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/lb) | resource | -| [aws_lb_listener.swarm_alb_https_listener](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/lb_listener) | resource | -| [aws_lb_target_group.helix_swarm_alb_target_group](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/lb_target_group) | resource | -| [aws_s3_bucket.helix_swarm_alb_access_logs_bucket](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/s3_bucket) | resource | -| [aws_s3_bucket_lifecycle_configuration.access_logs_bucket_lifecycle_configuration](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/s3_bucket_lifecycle_configuration) | resource | -| [aws_s3_bucket_policy.alb_access_logs_bucket_policy](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/s3_bucket_policy) | resource | -| [aws_s3_bucket_public_access_block.access_logs_bucket_public_block](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/s3_bucket_public_access_block) | resource | -| [aws_security_group.helix_swarm_alb_sg](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/security_group) | resource | -| [aws_security_group.helix_swarm_efs_security_group](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/security_group) | resource | -| [aws_security_group.helix_swarm_service_sg](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/security_group) | resource | -| [aws_vpc_security_group_egress_rule.helix_swarm_alb_outbound_service](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/vpc_security_group_egress_rule) | resource | -| [aws_vpc_security_group_egress_rule.helix_swarm_service_outbound_ipv4](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/vpc_security_group_egress_rule) | resource | -| [aws_vpc_security_group_egress_rule.helix_swarm_service_outbound_ipv6](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/vpc_security_group_egress_rule) | resource | -| [aws_vpc_security_group_ingress_rule.helix_swarm_efs_inbound_service](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/vpc_security_group_ingress_rule) | resource | -| [aws_vpc_security_group_ingress_rule.helix_swarm_service_inbound_alb](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/vpc_security_group_ingress_rule) | resource | +| [aws_cloudwatch_log_group.helix_swarm_redis_service_log_group](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/cloudwatch_log_group) | resource | +| [aws_cloudwatch_log_group.helix_swarm_service_log_group](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/cloudwatch_log_group) | resource | +| [aws_ecs_cluster.helix_swarm_cluster](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/ecs_cluster) | resource | +| [aws_ecs_cluster_capacity_providers.helix_swarm_cluster_fargate_providers](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/ecs_cluster_capacity_providers) | resource | +| [aws_ecs_service.helix_swarm_service](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/ecs_service) | resource | +| [aws_ecs_task_definition.helix_swarm_task_definition](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/ecs_task_definition) | resource | +| [aws_efs_access_point.helix_swarm_efs_access_point](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/efs_access_point) | resource | +| [aws_efs_access_point.redis_efs_access_point](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/efs_access_point) | resource | +| [aws_efs_file_system.helix_swarm_efs_file_system](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/efs_file_system) | resource | +| [aws_efs_mount_target.helix_swarm_efs_mount_target](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/efs_mount_target) | resource | +| [aws_iam_policy.helix_swarm_default_policy](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/iam_policy) | resource | +| [aws_iam_policy.helix_swarm_efs_policy](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/iam_policy) | resource | +| [aws_iam_policy.helix_swarm_ssm_policy](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/iam_policy) | resource | +| [aws_iam_role.helix_swarm_default_role](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/iam_role) | resource | +| [aws_iam_role.helix_swarm_task_execution_role](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/iam_role) | resource | +| [aws_lb.helix_swarm_alb](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/lb) | resource | +| [aws_lb_listener.swarm_alb_https_listener](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/lb_listener) | resource | +| [aws_lb_target_group.helix_swarm_alb_target_group](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/lb_target_group) | resource | +| [aws_s3_bucket.helix_swarm_alb_access_logs_bucket](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/s3_bucket) | resource | +| [aws_s3_bucket_lifecycle_configuration.access_logs_bucket_lifecycle_configuration](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/s3_bucket_lifecycle_configuration) | resource | +| [aws_s3_bucket_policy.alb_access_logs_bucket_policy](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/s3_bucket_policy) | resource | +| [aws_s3_bucket_public_access_block.access_logs_bucket_public_block](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/s3_bucket_public_access_block) | resource | +| [aws_security_group.helix_swarm_alb_sg](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/security_group) | resource | +| [aws_security_group.helix_swarm_efs_security_group](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/security_group) | resource | +| [aws_security_group.helix_swarm_service_sg](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/security_group) | resource | +| [aws_vpc_security_group_egress_rule.helix_swarm_alb_outbound_service](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/vpc_security_group_egress_rule) | resource | +| [aws_vpc_security_group_egress_rule.helix_swarm_service_outbound_ipv4](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/vpc_security_group_egress_rule) | resource | +| [aws_vpc_security_group_egress_rule.helix_swarm_service_outbound_ipv6](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/vpc_security_group_egress_rule) | resource | +| [aws_vpc_security_group_ingress_rule.helix_swarm_efs_inbound_service](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/vpc_security_group_ingress_rule) | resource | +| [aws_vpc_security_group_ingress_rule.helix_swarm_service_inbound_alb](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/vpc_security_group_ingress_rule) | resource | | [random_string.helix_swarm](https://registry.terraform.io/providers/hashicorp/random/3.6.2/docs/resources/string) | resource | | [random_string.helix_swarm_alb_access_logs_bucket_suffix](https://registry.terraform.io/providers/hashicorp/random/3.6.2/docs/resources/string) | resource | -| [aws_ecs_cluster.helix_swarm_cluster](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/data-sources/ecs_cluster) | data source | -| [aws_elb_service_account.main](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/data-sources/elb_service_account) | data source | -| [aws_iam_policy_document.access_logs_bucket_alb_write](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_policy_document.ecs_tasks_trust_relationship](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_policy_document.helix_swarm_default_policy](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_policy_document.helix_swarm_efs_policy](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_policy_document.helix_swarm_ssm_policy](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/data-sources/iam_policy_document) | data source | -| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/data-sources/region) | data source | +| [aws_ecs_cluster.helix_swarm_cluster](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/data-sources/ecs_cluster) | data source | +| [aws_elb_service_account.main](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/data-sources/elb_service_account) | data source | +| [aws_iam_policy_document.access_logs_bucket_alb_write](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.ecs_tasks_trust_relationship](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.helix_swarm_default_policy](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.helix_swarm_efs_policy](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.helix_swarm_ssm_policy](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/data-sources/iam_policy_document) | data source | +| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/data-sources/region) | data source | ## Inputs diff --git a/modules/perforce/helix-swarm/efs.tf b/modules/perforce/helix-swarm/efs.tf index 82cc8222..cd1aa183 100644 --- a/modules/perforce/helix-swarm/efs.tf +++ b/modules/perforce/helix-swarm/efs.tf @@ -20,7 +20,7 @@ resource "aws_efs_file_system" "helix_swarm_efs_file_system" { lifecycle_policy { transition_to_primary_storage_class = "AFTER_1_ACCESS" } - + #checkov:skip=CKV_AWS_184: CMK encryption not supported currently tags = merge(local.tags, { Name = "${local.name_prefix}-efs-file-system" }) diff --git a/samples/simple-build-pipeline/README.md b/samples/simple-build-pipeline/README.md index 3b9c499b..7abf0abe 100644 --- a/samples/simple-build-pipeline/README.md +++ b/samples/simple-build-pipeline/README.md @@ -4,13 +4,13 @@ | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | 5.59.0 | +| [aws](#requirement\_aws) | 5.66.0 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | 5.59.0 | +| [aws](#provider\_aws) | 5.66.0 | ## Modules @@ -25,45 +25,47 @@ | Name | Type | |------|------| -| [aws_acm_certificate.helix](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/acm_certificate) | resource | -| [aws_acm_certificate.jenkins](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/acm_certificate) | resource | -| [aws_acm_certificate_validation.helix](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/acm_certificate_validation) | resource | -| [aws_acm_certificate_validation.jenkins](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/acm_certificate_validation) | resource | -| [aws_default_security_group.default](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/default_security_group) | resource | -| [aws_ecs_cluster.build_pipeline_cluster](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/ecs_cluster) | resource | -| [aws_ecs_cluster_capacity_providers.providers](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/ecs_cluster_capacity_providers) | resource | -| [aws_eip.nat_gateway_eip](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/eip) | resource | -| [aws_internet_gateway.igw](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/internet_gateway) | resource | -| [aws_nat_gateway.nat_gateway](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/nat_gateway) | resource | -| [aws_route53_record.helix_authentication_service](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/route53_record) | resource | -| [aws_route53_record.helix_cert](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/route53_record) | resource | -| [aws_route53_record.helix_swarm](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/route53_record) | resource | -| [aws_route53_record.jenkins](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/route53_record) | resource | -| [aws_route53_record.jenkins_cert](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/route53_record) | resource | -| [aws_route53_record.perforce_helix_core](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/route53_record) | resource | -| [aws_route53_record.perforce_helix_core_pvt](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/route53_record) | resource | -| [aws_route53_zone.helix_private_zone](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/route53_zone) | resource | -| [aws_route_table.private_rt](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/route_table) | resource | -| [aws_route_table.public_rt](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/route_table) | resource | -| [aws_route_table_association.private_rt_asso](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/route_table_association) | resource | -| [aws_route_table_association.public_rt_asso](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/route_table_association) | resource | -| [aws_subnet.private_subnets](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/subnet) | resource | -| [aws_subnet.public_subnets](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/subnet) | resource | -| [aws_vpc.build_pipeline_vpc](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/vpc) | resource | -| [aws_vpc_security_group_ingress_rule.helix_auth_access](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/vpc_security_group_ingress_rule) | resource | -| [aws_vpc_security_group_ingress_rule.helix_auth_inbound_core](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/vpc_security_group_ingress_rule) | resource | -| [aws_vpc_security_group_ingress_rule.helix_core_access](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/vpc_security_group_ingress_rule) | resource | -| [aws_vpc_security_group_ingress_rule.helix_core_inbound_build_farm](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/vpc_security_group_ingress_rule) | resource | -| [aws_vpc_security_group_ingress_rule.helix_core_inbound_swarm](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/vpc_security_group_ingress_rule) | resource | -| [aws_vpc_security_group_ingress_rule.helix_swarm_access](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/vpc_security_group_ingress_rule) | resource | -| [aws_vpc_security_group_ingress_rule.helix_swarm_inbound_core](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/vpc_security_group_ingress_rule) | resource | -| [aws_vpc_security_group_ingress_rule.jenkins_access](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/resources/vpc_security_group_ingress_rule) | resource | -| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/data-sources/availability_zones) | data source | -| [aws_route53_zone.root](https://registry.terraform.io/providers/hashicorp/aws/5.59.0/docs/data-sources/route53_zone) | data source | +| [aws_acm_certificate.helix](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/acm_certificate) | resource | +| [aws_acm_certificate.jenkins](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/acm_certificate) | resource | +| [aws_acm_certificate_validation.helix](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/acm_certificate_validation) | resource | +| [aws_acm_certificate_validation.jenkins](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/acm_certificate_validation) | resource | +| [aws_default_security_group.default](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/default_security_group) | resource | +| [aws_ecs_cluster.build_pipeline_cluster](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/ecs_cluster) | resource | +| [aws_ecs_cluster_capacity_providers.providers](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/ecs_cluster_capacity_providers) | resource | +| [aws_eip.nat_gateway_eip](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/eip) | resource | +| [aws_internet_gateway.igw](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/internet_gateway) | resource | +| [aws_nat_gateway.nat_gateway](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/nat_gateway) | resource | +| [aws_route53_record.helix_authentication_service](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/route53_record) | resource | +| [aws_route53_record.helix_cert](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/route53_record) | resource | +| [aws_route53_record.helix_swarm](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/route53_record) | resource | +| [aws_route53_record.jenkins](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/route53_record) | resource | +| [aws_route53_record.jenkins_cert](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/route53_record) | resource | +| [aws_route53_record.perforce_helix_core](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/route53_record) | resource | +| [aws_route53_record.perforce_helix_core_pvt](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/route53_record) | resource | +| [aws_route53_zone.helix_private_zone](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/route53_zone) | resource | +| [aws_route_table.private_rt](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/route_table) | resource | +| [aws_route_table.public_rt](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/route_table) | resource | +| [aws_route_table_association.private_rt_asso](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/route_table_association) | resource | +| [aws_route_table_association.public_rt_asso](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/route_table_association) | resource | +| [aws_subnet.private_subnets](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/subnet) | resource | +| [aws_subnet.public_subnets](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/subnet) | resource | +| [aws_vpc.build_pipeline_vpc](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/vpc) | resource | +| [aws_vpc_security_group_ingress_rule.helix_auth_access](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/vpc_security_group_ingress_rule) | resource | +| [aws_vpc_security_group_ingress_rule.helix_auth_inbound_core](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/vpc_security_group_ingress_rule) | resource | +| [aws_vpc_security_group_ingress_rule.helix_core_access](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/vpc_security_group_ingress_rule) | resource | +| [aws_vpc_security_group_ingress_rule.helix_core_inbound_build_farm](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/vpc_security_group_ingress_rule) | resource | +| [aws_vpc_security_group_ingress_rule.helix_core_inbound_swarm](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/vpc_security_group_ingress_rule) | resource | +| [aws_vpc_security_group_ingress_rule.helix_swarm_access](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/vpc_security_group_ingress_rule) | resource | +| [aws_vpc_security_group_ingress_rule.helix_swarm_inbound_core](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/vpc_security_group_ingress_rule) | resource | +| [aws_vpc_security_group_ingress_rule.jenkins_access](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/resources/vpc_security_group_ingress_rule) | resource | +| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/data-sources/availability_zones) | data source | +| [aws_route53_zone.root](https://registry.terraform.io/providers/hashicorp/aws/5.66.0/docs/data-sources/route53_zone) | data source | ## Inputs -No inputs. +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [root\_domain\_name](#input\_root\_domain\_name) | The fully qualified domain name of your existing Route53 Hosted Zone. | `string` | n/a | yes | ## Outputs diff --git a/samples/simple-build-pipeline/dns.tf b/samples/simple-build-pipeline/dns.tf index 677e09eb..a4ae3487 100644 --- a/samples/simple-build-pipeline/dns.tf +++ b/samples/simple-build-pipeline/dns.tf @@ -3,16 +3,10 @@ # Route53 Hosted Zone for FQDN ########################################## data "aws_route53_zone" "root" { - name = local.fully_qualified_domain_name + name = var.root_domain_name private_zone = false } -# resource "aws_route53_zone" "root" { -# name = local.fully_qualified_domain_name -# #checkov:skip=CKV2_AWS_38: DNSSEC signing disabled by design -# #checkov:skip=CKV2_AWS_39: Query logging disabled by design -# } - resource "aws_route53_record" "jenkins" { zone_id = data.aws_route53_zone.root.id name = data.aws_route53_zone.root.name @@ -82,7 +76,7 @@ resource "aws_route53_record" "perforce_helix_core_pvt" { ########################################## resource "aws_acm_certificate" "jenkins" { - domain_name = "jenkins.${local.fully_qualified_domain_name}" + domain_name = "jenkins.${var.root_domain_name}" validation_method = "DNS" tags = { @@ -123,8 +117,8 @@ resource "aws_acm_certificate_validation" "jenkins" { ########################################## resource "aws_acm_certificate" "helix" { - domain_name = "helix.${local.fully_qualified_domain_name}" - subject_alternative_names = ["*.helix.${local.fully_qualified_domain_name}"] + domain_name = "helix.${var.root_domain_name}" + subject_alternative_names = ["*.helix.${var.root_domain_name}"] validation_method = "DNS" diff --git a/samples/simple-build-pipeline/local.tf b/samples/simple-build-pipeline/local.tf index 3d6c3b8e..fa389239 100644 --- a/samples/simple-build-pipeline/local.tf +++ b/samples/simple-build-pipeline/local.tf @@ -2,7 +2,6 @@ data "aws_availability_zones" "available" {} locals { # Simple Build Pipeline Configuration - fully_qualified_domain_name = "PLACEHOLDER" # update this to the root domain name you own # IPV4 CIDR blocks that need Jenkins access. For example: # "/32" diff --git a/samples/simple-build-pipeline/main.tf b/samples/simple-build-pipeline/main.tf index 71c23621..8dbd36d3 100644 --- a/samples/simple-build-pipeline/main.tf +++ b/samples/simple-build-pipeline/main.tf @@ -28,18 +28,19 @@ resource "aws_ecs_cluster_capacity_providers" "providers" { ########################################## module "perforce_helix_core" { - source = "../../modules/perforce/helix-core" - vpc_id = aws_vpc.build_pipeline_vpc.id - server_type = "p4d_commit" - instance_subnet_id = aws_subnet.public_subnets[0].id - instance_type = "c6in.large" + source = "../../modules/perforce/helix-core" + vpc_id = aws_vpc.build_pipeline_vpc.id + server_type = "p4d_commit" + instance_subnet_id = aws_subnet.public_subnets[0].id + instance_type = "c6g.large" + instance_architecture = "arm64" storage_type = "EBS" depot_volume_size = 64 metadata_volume_size = 32 logs_volume_size = 32 - FQDN = "core.helix.perforce.${local.fully_qualified_domain_name}" + FQDN = "core.helix.perforce.${var.root_domain_name}" helix_authentication_service_url = "https://${aws_route53_record.helix_authentication_service.name}" } @@ -57,7 +58,7 @@ module "perforce_helix_authentication_service" { certificate_arn = aws_acm_certificate.helix.arn enable_web_based_administration = true - fqdn = "https://auth.helix.${local.fully_qualified_domain_name}" + fqdn = "https://auth.helix.${var.root_domain_name}" depends_on = [aws_ecs_cluster.build_pipeline_cluster, aws_acm_certificate_validation.helix] } @@ -80,7 +81,7 @@ module "perforce_helix_swarm" { p4d_swarm_user_arn = module.perforce_helix_core.helix_core_super_user_username_secret_arn p4d_swarm_password_arn = module.perforce_helix_core.helix_core_super_user_password_secret_arn - fqdn = "swarm.helix.${local.fully_qualified_domain_name}" + fqdn = "swarm.helix.${var.root_domain_name}" depends_on = [aws_ecs_cluster.build_pipeline_cluster, aws_acm_certificate_validation.helix] } diff --git a/samples/simple-build-pipeline/variables.tf b/samples/simple-build-pipeline/variables.tf new file mode 100644 index 00000000..7099b5ad --- /dev/null +++ b/samples/simple-build-pipeline/variables.tf @@ -0,0 +1,4 @@ +variable "root_domain_name" { + type = string + description = "The fully qualified domain name of your existing Route53 Hosted Zone." +}