feat(dash): Terraform AWS Beanstalk 92/35492/13
authorPeter Mikus <pmikus@cisco.com>
Tue, 1 Mar 2022 13:10:13 +0000 (14:10 +0100)
committerPeter Mikus <pmikus@cisco.com>
Wed, 16 Mar 2022 15:06:29 +0000 (15:06 +0000)
Signed-off-by: Peter Mikus <pmikus@cisco.com>
Change-Id: Ib89677de3818b46aa622f56f28b7bbb54458dbe0

14 files changed:
fdio.infra.terraform/1n_aws_t3/fdio-csit-dash-env/main.tf [new file with mode: 0644]
fdio.infra.terraform/1n_aws_t3/fdio-csit-dash-env/output.tf [new file with mode: 0644]
fdio.infra.terraform/1n_aws_t3/fdio-csit-dash-env/providers.tf [new file with mode: 0644]
fdio.infra.terraform/1n_aws_t3/fdio-csit-dash-env/variables.tf [new file with mode: 0644]
fdio.infra.terraform/1n_aws_t3/fdio-csit-dash-env/versions.tf [new file with mode: 0644]
fdio.infra.terraform/1n_aws_t3/main.tf [new file with mode: 0644]
fdio.infra.terraform/1n_aws_t3/output.tf [new file with mode: 0644]
fdio.infra.terraform/1n_aws_t3/variables.tf [new file with mode: 0644]
fdio.infra.terraform/1n_aws_t3/versions.tf [new file with mode: 0644]
resources/tools/dash/app/Procfile [new file with mode: 0644]
resources/tools/dash/app/app.ini
resources/tools/dash/app/config.py
resources/tools/dash/app/wsgi.py
resources/tools/dash/docker-compose.yaml

diff --git a/fdio.infra.terraform/1n_aws_t3/fdio-csit-dash-env/main.tf b/fdio.infra.terraform/1n_aws_t3/fdio-csit-dash-env/main.tf
new file mode 100644 (file)
index 0000000..01b2351
--- /dev/null
@@ -0,0 +1,101 @@
+data "vault_generic_secret" "fdio_docs" {
+  path = "kv/secret/data/etl/fdio_docs"
+}
+
+data "vault_aws_access_credentials" "creds" {
+  backend = "${var.vault_name}-path"
+  role    = "${var.vault_name}-role"
+}
+
+module "elastic_beanstalk_environment" {
+  source = "../"
+
+  # vpc
+  vpc_cidr_block           = "192.168.0.0/24"
+  vpc_enable_dns_hostnames = true
+  vpc_enable_dns_support   = true
+  vpc_instance_tenancy     = "default"
+
+  # subnet
+  subnet_availability_zone = "us-east-1a"
+
+  # application
+  application_description                    = "FD.io CSIT Results Dashboard"
+  application_name                           = "fdio-csit-dash-app"
+  appversion_lifecycle_service_role_arn      = ""
+  appversion_lifecycle_max_count             = 2
+  appversion_lifecycle_delete_source_from_s3 = false
+
+  # environment
+  environment_description            = "FD.io CSIT Results Dashboard"
+  environment_name                   = "fdio-csit-dash-env"
+  environment_solution_stack_name    = "64bit Amazon Linux 2 v3.3.11 running Python 3.8"
+  environment_tier                   = "WebServer"
+  environment_wait_for_ready_timeout = "20m"
+  environment_version_label          = ""
+
+  # aws:ec2:instances
+  instances_instance_types = "t3a.2xlarge"
+
+  # aws:ec2:vpc
+  associate_public_ip_address = true
+  elb_scheme                  = "public"
+
+  # aws:elbv2:listener:default
+  default_listener_enabled = true
+
+  # aws:elasticbeanstalk:environment
+  environment_loadbalancer_type = "network"
+
+  # aws:elasticbeanstalk:environment:process:default
+  environment_process_default_healthcheck_interval      = 10
+  environment_process_default_healthy_threshold_count   = 3
+  environment_process_default_port                      = 5000
+  environment_process_default_unhealthy_threshold_count = 3
+
+  # aws:elasticbeanstalk:healthreporting:system
+  healthreporting_system_type = "enhanced"
+
+  # aws:elasticbeanstalk:managedactions
+  managedactions_managed_actions_enabled = true
+  managedactions_preferred_start_time    = "Sun:10:00"
+
+  # aws:elasticbeanstalk:managedactions:platformupdate
+  managedactions_platformupdate_update_level             = "minor"
+  managedactions_platformupdate_instance_refresh_enabled = true
+
+  # aws:autoscaling:asg
+  autoscaling_asg_minsize = 1
+  autoscaling_asg_maxsize = 2
+
+  # aws:autoscaling:trigger
+  autoscaling_trigger_measure_name                 = "CPUUtilization"
+  autoscaling_trigger_statistic                    = "Average"
+  autoscaling_trigger_unit                         = "Percent"
+  autoscaling_trigger_lower_threshold              = 20
+  autoscaling_trigger_lower_breach_scale_increment = -1
+  autoscaling_trigger_upper_threshold              = 80
+  autoscaling_trigger_upper_breach_scale_increment = 1
+
+  # aws:elasticbeanstalk:hostmanager
+  hostmanager_log_publication_control = true
+
+  # aws:elasticbeanstalk:cloudwatch:logs
+  cloudwatch_logs_stream_logs         = true
+  cloudwatch_logs_delete_on_terminate = true
+  cloudwatch_logs_retention_in_days   = 3
+
+  # aws:elasticbeanstalk:cloudwatch:logs:health
+  cloudwatch_logs_health_health_streaming_enabled = true
+  cloudwatch_logs_health_delete_on_terminate      = true
+  cloudwatch_logs_health_retention_in_days        = 3
+
+  environment_type = "LoadBalanced"
+
+  # aws:elasticbeanstalk:application:environment
+  environment_variables = {
+    "AWS_ACCESS_KEY_ID"     = data.vault_generic_secret.fdio_docs.data["access_key"]
+    "AWS_SECRET_ACCESS_KEY" = data.vault_generic_secret.fdio_docs.data["secret_key"]
+    "AWS_DEFAULT_REGION"    = data.vault_generic_secret.fdio_docs.data["region"]
+  }
+}
diff --git a/fdio.infra.terraform/1n_aws_t3/fdio-csit-dash-env/output.tf b/fdio.infra.terraform/1n_aws_t3/fdio-csit-dash-env/output.tf
new file mode 100644 (file)
index 0000000..adcfc4b
--- /dev/null
@@ -0,0 +1,9 @@
+output "elastic_beanstalk_environment_hostname" {
+  description = "DNS hostname"
+  value       = module.elastic_beanstalk_environment.cname
+}
+
+output "elastic_beanstalk_environment_name" {
+  description = "Name of the Elastic Beanstalk environment"
+  value       = module.elastic_beanstalk_environment.envName
+}
\ No newline at end of file
diff --git a/fdio.infra.terraform/1n_aws_t3/fdio-csit-dash-env/providers.tf b/fdio.infra.terraform/1n_aws_t3/fdio-csit-dash-env/providers.tf
new file mode 100644 (file)
index 0000000..7241b27
--- /dev/null
@@ -0,0 +1,11 @@
+provider "aws" {
+  region     = var.region
+  access_key = data.vault_aws_access_credentials.creds.access_key
+  secret_key = data.vault_aws_access_credentials.creds.secret_key
+}
+
+provider "vault" {
+  address         = var.vault_provider_address
+  skip_tls_verify = var.vault_provider_skip_tls_verify
+  token           = var.vault_provider_token
+}
diff --git a/fdio.infra.terraform/1n_aws_t3/fdio-csit-dash-env/variables.tf b/fdio.infra.terraform/1n_aws_t3/fdio-csit-dash-env/variables.tf
new file mode 100644 (file)
index 0000000..2579029
--- /dev/null
@@ -0,0 +1,28 @@
+variable "region" {
+  description = "AWS Region."
+  type        = string
+  default     = "us-east-1"
+}
+
+variable "vault_provider_address" {
+  description = "Vault cluster address."
+  type        = string
+  default     = "http://10.30.51.28:8200"
+}
+
+variable "vault_provider_skip_tls_verify" {
+  description = "Verification of the Vault server's TLS certificate."
+  type        = bool
+  default     = false
+}
+
+variable "vault_provider_token" {
+  description = "Vault root token."
+  type        = string
+  sensitive   = true
+}
+
+variable "vault_name" {
+  type    = string
+  default = "dynamic-aws-creds-vault-fdio-csit-jenkins"
+}
diff --git a/fdio.infra.terraform/1n_aws_t3/fdio-csit-dash-env/versions.tf b/fdio.infra.terraform/1n_aws_t3/fdio-csit-dash-env/versions.tf
new file mode 100644 (file)
index 0000000..4afbbc0
--- /dev/null
@@ -0,0 +1,17 @@
+terraform {
+  backend "consul" {
+    address = "10.32.8.14:8500"
+    scheme  = "http"
+    path    = "terraform/dash"
+  }
+  required_providers {
+    aws = {
+      source  = "hashicorp/aws"
+      version = ">= 4.3.0"
+    }
+    vault = {
+      version = ">= 3.2.1"
+    }
+  }
+  required_version = ">= 1.1.4"
+}
diff --git a/fdio.infra.terraform/1n_aws_t3/main.tf b/fdio.infra.terraform/1n_aws_t3/main.tf
new file mode 100644 (file)
index 0000000..eb0c046
--- /dev/null
@@ -0,0 +1,613 @@
+locals {
+  bucket = "${var.application_name}-bucket"
+  tags = {
+    "Name"        = "${var.application_name}"
+    "Environment" = "${var.application_name}"
+  }
+}
+
+# Create elastic beanstalk VPC
+resource "aws_vpc" "vpc" {
+  assign_generated_ipv6_cidr_block = true
+  cidr_block                       = var.vpc_cidr_block
+  enable_dns_hostnames             = var.vpc_enable_dns_hostnames
+  enable_dns_support               = var.vpc_enable_dns_support
+  instance_tenancy                 = var.vpc_instance_tenancy
+  tags                             = local.tags
+}
+
+# Create elastic beanstalk Subnets
+resource "aws_subnet" "subnet" {
+  depends_on = [
+    aws_vpc.vpc
+  ]
+  availability_zone               = var.subnet_availability_zone
+  assign_ipv6_address_on_creation = true
+  cidr_block                      = aws_vpc.vpc.cidr_block
+  ipv6_cidr_block                 = cidrsubnet(aws_vpc.vpc.ipv6_cidr_block, 8, 1)
+  map_public_ip_on_launch         = true
+  vpc_id                          = aws_vpc.vpc.id
+  tags                            = local.tags
+}
+
+resource "aws_internet_gateway" "internet_gateway" {
+  depends_on = [
+    aws_vpc.vpc
+  ]
+  vpc_id = aws_vpc.vpc.id
+  tags   = local.tags
+}
+
+resource "aws_route" "route" {
+  depends_on = [
+    aws_vpc.vpc,
+    aws_internet_gateway.internet_gateway
+  ]
+  destination_cidr_block = "0.0.0.0/0"
+  gateway_id             = aws_internet_gateway.internet_gateway.id
+  route_table_id         = aws_vpc.vpc.main_route_table_id
+}
+
+# Create elastic beanstalk IAM mapping
+data "aws_iam_policy_document" "service" {
+  statement {
+    actions = [
+      "sts:AssumeRole"
+    ]
+    principals {
+      type        = "Service"
+      identifiers = ["elasticbeanstalk.amazonaws.com"]
+    }
+    effect = "Allow"
+  }
+}
+
+resource "aws_iam_role" "service" {
+  assume_role_policy = data.aws_iam_policy_document.service.json
+  name               = "${var.application_name}-eb-service"
+}
+
+resource "aws_iam_role_policy_attachment" "enhanced_health" {
+  policy_arn = "arn:aws:iam::aws:policy/service-role/AWSElasticBeanstalkEnhancedHealth"
+  role       = aws_iam_role.service.name
+}
+
+resource "aws_iam_role_policy_attachment" "service" {
+  policy_arn = "arn:aws:iam::aws:policy/service-role/AWSElasticBeanstalkService"
+  role       = aws_iam_role.service.name
+}
+
+data "aws_iam_policy_document" "ec2" {
+  statement {
+    actions = [
+      "sts:AssumeRole"
+    ]
+    principals {
+      type        = "Service"
+      identifiers = ["ec2.amazonaws.com"]
+    }
+    effect = "Allow"
+  }
+  statement {
+    actions = [
+      "sts:AssumeRole",
+    ]
+    principals {
+      type        = "Service"
+      identifiers = ["ssm.amazonaws.com"]
+    }
+    effect = "Allow"
+  }
+}
+
+resource "aws_iam_role" "ec2" {
+  assume_role_policy = data.aws_iam_policy_document.ec2.json
+  name               = "${var.application_name}-eb-ec2"
+}
+
+resource "aws_iam_instance_profile" "ec2_iam_instance_profile" {
+  name = "${var.application_name}-iam-instance-profile"
+  role = aws_iam_role.ec2.name
+}
+
+resource "aws_iam_role_policy_attachment" "multicontainer_docker" {
+  policy_arn = "arn:aws:iam::aws:policy/AWSElasticBeanstalkMulticontainerDocker"
+  role       = aws_iam_role.ec2.name
+}
+
+resource "aws_iam_role_policy_attachment" "web_tier" {
+  policy_arn = "arn:aws:iam::aws:policy/AWSElasticBeanstalkWebTier"
+  role       = aws_iam_role.ec2.name
+}
+
+resource "aws_iam_role_policy_attachment" "worker_tier" {
+  policy_arn = "arn:aws:iam::aws:policy/AWSElasticBeanstalkWorkerTier"
+  role       = aws_iam_role.ec2.name
+}
+
+resource "aws_iam_role_policy_attachment" "ssm_automation" {
+  policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonSSMAutomationRole"
+  role       = aws_iam_role.ec2.name
+}
+
+resource "aws_iam_role_policy_attachment" "ssm_ec2" {
+  policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
+  role       = aws_iam_role.ec2.name
+}
+
+resource "aws_iam_role_policy_attachment" "ecr_readonly" {
+  policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
+  role       = aws_iam_role.ec2.name
+}
+
+resource "aws_ssm_activation" "ec2" {
+  depends_on = [
+    aws_iam_role.ec2,
+    aws_iam_role_policy_attachment.ssm_ec2
+  ]
+  name               = "${var.application_name}-ec2-activation"
+  iam_role           = aws_iam_role.ec2.id
+  registration_limit = 3
+}
+
+data "aws_iam_policy_document" "default" {
+  statement {
+    actions = [
+      "elasticloadbalancing:DescribeInstanceHealth",
+      "elasticloadbalancing:DescribeLoadBalancers",
+      "elasticloadbalancing:DescribeTargetHealth",
+      "ec2:DescribeInstances",
+      "ec2:DescribeInstanceStatus",
+      "ec2:GetConsoleOutput",
+      "ec2:AssociateAddress",
+      "ec2:DescribeAddresses",
+      "ec2:DescribeSecurityGroups",
+      "sqs:GetQueueAttributes",
+      "sqs:GetQueueUrl",
+      "autoscaling:DescribeAutoScalingGroups",
+      "autoscaling:DescribeAutoScalingInstances",
+      "autoscaling:DescribeScalingActivities",
+      "autoscaling:DescribeNotificationConfigurations",
+    ]
+    resources = ["*"]
+    effect    = "Allow"
+  }
+
+  statement {
+    sid = "AllowOperations"
+    actions = [
+      "autoscaling:AttachInstances",
+      "autoscaling:CreateAutoScalingGroup",
+      "autoscaling:CreateLaunchConfiguration",
+      "autoscaling:DeleteLaunchConfiguration",
+      "autoscaling:DeleteAutoScalingGroup",
+      "autoscaling:DeleteScheduledAction",
+      "autoscaling:DescribeAccountLimits",
+      "autoscaling:DescribeAutoScalingGroups",
+      "autoscaling:DescribeAutoScalingInstances",
+      "autoscaling:DescribeLaunchConfigurations",
+      "autoscaling:DescribeLoadBalancers",
+      "autoscaling:DescribeNotificationConfigurations",
+      "autoscaling:DescribeScalingActivities",
+      "autoscaling:DescribeScheduledActions",
+      "autoscaling:DetachInstances",
+      "autoscaling:PutScheduledUpdateGroupAction",
+      "autoscaling:ResumeProcesses",
+      "autoscaling:SetDesiredCapacity",
+      "autoscaling:SetInstanceProtection",
+      "autoscaling:SuspendProcesses",
+      "autoscaling:TerminateInstanceInAutoScalingGroup",
+      "autoscaling:UpdateAutoScalingGroup",
+      "cloudwatch:PutMetricAlarm",
+      "ec2:AssociateAddress",
+      "ec2:AllocateAddress",
+      "ec2:AuthorizeSecurityGroupEgress",
+      "ec2:AuthorizeSecurityGroupIngress",
+      "ec2:CreateSecurityGroup",
+      "ec2:DeleteSecurityGroup",
+      "ec2:DescribeAccountAttributes",
+      "ec2:DescribeAddresses",
+      "ec2:DescribeImages",
+      "ec2:DescribeInstances",
+      "ec2:DescribeKeyPairs",
+      "ec2:DescribeSecurityGroups",
+      "ec2:DescribeSnapshots",
+      "ec2:DescribeSubnets",
+      "ec2:DescribeVpcs",
+      "ec2:DisassociateAddress",
+      "ec2:ReleaseAddress",
+      "ec2:RevokeSecurityGroupEgress",
+      "ec2:RevokeSecurityGroupIngress",
+      "ec2:TerminateInstances",
+      "ecs:CreateCluster",
+      "ecs:DeleteCluster",
+      "ecs:DescribeClusters",
+      "ecs:RegisterTaskDefinition",
+      "elasticbeanstalk:*",
+      "elasticloadbalancing:ApplySecurityGroupsToLoadBalancer",
+      "elasticloadbalancing:ConfigureHealthCheck",
+      "elasticloadbalancing:CreateLoadBalancer",
+      "elasticloadbalancing:DeleteLoadBalancer",
+      "elasticloadbalancing:DeregisterInstancesFromLoadBalancer",
+      "elasticloadbalancing:DescribeInstanceHealth",
+      "elasticloadbalancing:DescribeLoadBalancers",
+      "elasticloadbalancing:DescribeTargetHealth",
+      "elasticloadbalancing:RegisterInstancesWithLoadBalancer",
+      "elasticloadbalancing:DescribeTargetGroups",
+      "elasticloadbalancing:RegisterTargets",
+      "elasticloadbalancing:DeregisterTargets",
+      "iam:ListRoles",
+      "iam:PassRole",
+      "logs:CreateLogGroup",
+      "logs:PutRetentionPolicy",
+      "rds:DescribeDBEngineVersions",
+      "rds:DescribeDBInstances",
+      "rds:DescribeOrderableDBInstanceOptions",
+      "s3:GetObject",
+      "s3:GetObjectAcl",
+      "s3:ListBucket",
+      "sns:CreateTopic",
+      "sns:GetTopicAttributes",
+      "sns:ListSubscriptionsByTopic",
+      "sns:Subscribe",
+      "sqs:GetQueueAttributes",
+      "sqs:GetQueueUrl",
+      "codebuild:CreateProject",
+      "codebuild:DeleteProject",
+      "codebuild:BatchGetBuilds",
+      "codebuild:StartBuild",
+    ]
+    resources = ["*"]
+    effect    = "Allow"
+  }
+
+  statement {
+    sid = "AllowS3OperationsOnElasticBeanstalkBuckets"
+    actions = [
+      "s3:*"
+    ]
+    resources = [
+      "arn:aws:s3:::*"
+    ]
+    effect = "Allow"
+  }
+
+  statement {
+    sid = "AllowDeleteCloudwatchLogGroups"
+    actions = [
+      "logs:DeleteLogGroup"
+    ]
+    resources = [
+      "arn:aws:logs:*:*:log-group:/aws/elasticbeanstalk*"
+    ]
+    effect = "Allow"
+  }
+
+  statement {
+    sid = "AllowCloudformationOperationsOnElasticBeanstalkStacks"
+    actions = [
+      "cloudformation:*"
+    ]
+    resources = [
+      "arn:aws:cloudformation:*:*:stack/awseb-*",
+      "arn:aws:cloudformation:*:*:stack/eb-*"
+    ]
+    effect = "Allow"
+  }
+}
+
+resource "aws_iam_role_policy" "default" {
+  depends_on = [
+    aws_iam_role.ec2
+  ]
+  name   = "${var.application_name}-eb-default"
+  policy = data.aws_iam_policy_document.default.json
+  role   = aws_iam_role.ec2.id
+}
+
+# Create elastic beanstalk Application
+resource "aws_s3_bucket" "bucket" {
+  bucket = local.bucket
+  tags   = local.tags
+}
+
+resource "aws_s3_object" "object" {
+  bucket = aws_s3_bucket.bucket.id
+  key    = "beanstalk/app.zip"
+  source = "app.zip"
+  tags   = local.tags
+}
+
+resource "aws_elastic_beanstalk_application_version" "application_version" {
+  depends_on = [
+    aws_elastic_beanstalk_application.application
+  ]
+  name        = "${var.application_name}-base"
+  application = var.application_name
+  description = var.application_description
+  bucket      = aws_s3_bucket.bucket.id
+  key         = aws_s3_object.object.id
+  tags        = local.tags
+}
+
+resource "aws_elastic_beanstalk_application" "application" {
+  depends_on = [
+    aws_vpc.vpc,
+    aws_subnet.subnet,
+    aws_ssm_activation.ec2
+  ]
+  name        = var.application_name
+  description = var.application_description
+
+  dynamic "appversion_lifecycle" {
+    for_each = var.appversion_lifecycle_service_role_arn != "" ? ["true"] : []
+    content {
+      service_role          = var.appversion_lifecycle_service_role_arn
+      max_count             = var.appversion_lifecycle_max_count
+      delete_source_from_s3 = var.appversion_lifecycle_delete_source_from_s3
+    }
+  }
+  tags = local.tags
+}
+
+# Create elastic beanstalk Environment
+resource "aws_elastic_beanstalk_environment" "environment" {
+  depends_on = [
+    aws_vpc.vpc,
+    aws_subnet.subnet,
+    aws_ssm_activation.ec2
+  ]
+  application            = aws_elastic_beanstalk_application.application.name
+  description            = var.environment_description
+  name                   = var.environment_name
+  solution_stack_name    = var.environment_solution_stack_name
+  tier                   = var.environment_tier
+  wait_for_ready_timeout = var.environment_wait_for_ready_timeout
+  version_label          = var.environment_version_label
+  tags                   = local.tags
+
+  # aws:ec2:instances
+  setting {
+    namespace = "aws:ec2:instances"
+    name      = "InstanceTypes"
+    value     = var.instances_instance_types
+  }
+
+  # aws:ec2:vpc
+  setting {
+    namespace = "aws:ec2:vpc"
+    name      = "VPCId"
+    value     = aws_vpc.vpc.id
+  }
+
+  setting {
+    namespace = "aws:ec2:vpc"
+    name      = "Subnets"
+    value     = aws_subnet.subnet.id
+  }
+
+  setting {
+    namespace = "aws:ec2:vpc"
+    name      = "ELBSubnets"
+    value     = aws_subnet.subnet.id
+  }
+
+  setting {
+    namespace = "aws:ec2:vpc"
+    name      = "ELBScheme"
+    value     = var.environment_type == "LoadBalanced" ? var.elb_scheme : ""
+  }
+
+  setting {
+    namespace = "aws:ec2:vpc"
+    name      = "AssociatePublicIpAddress"
+    value     = var.associate_public_ip_address
+  }
+
+  setting {
+    namespace = "aws:elasticbeanstalk:application"
+    name      = "Application Healthcheck URL"
+    value     = "/"
+  }
+
+  # aws:elbv2:listener:default
+  setting {
+    namespace = "aws:elbv2:listener:default"
+    name      = "ListenerEnabled"
+    value     = var.default_listener_enabled
+  }
+
+  # aws:elasticbeanstalk:environment
+  setting {
+    namespace = "aws:elasticbeanstalk:environment"
+    name      = "LoadBalancerType"
+    value     = var.environment_loadbalancer_type
+  }
+
+  setting {
+    namespace = "aws:elasticbeanstalk:environment"
+    name      = "ServiceRole"
+    value     = aws_iam_role.service.name
+  }
+
+  # aws:elasticbeanstalk:environment:process:default
+  setting {
+    namespace = "aws:elasticbeanstalk:environment:process:default"
+    name      = "HealthCheckInterval"
+    value     = var.environment_process_default_healthcheck_interval
+  }
+
+  setting {
+    namespace = "aws:elasticbeanstalk:environment:process:default"
+    name      = "HealthyThresholdCount"
+    value     = var.environment_process_default_healthy_threshold_count
+  }
+
+  setting {
+    namespace = "aws:elasticbeanstalk:environment:process:default"
+    name      = "Port"
+    value     = var.environment_process_default_port
+  }
+
+  setting {
+    namespace = "aws:elasticbeanstalk:environment:process:default"
+    name      = "Protocol"
+    value     = var.environment_loadbalancer_type == "network" ? "TCP" : "HTTP"
+  }
+
+  setting {
+    namespace = "aws:elasticbeanstalk:environment:process:default"
+    name      = "UnhealthyThresholdCount"
+    value     = var.environment_process_default_unhealthy_threshold_count
+  }
+
+  # aws:autoscaling:launchconfiguration
+  setting {
+    namespace = "aws:autoscaling:launchconfiguration"
+    name      = "IamInstanceProfile"
+    value     = aws_iam_instance_profile.ec2_iam_instance_profile.name
+  }
+
+  # aws:elasticbeanstalk:healthreporting:system
+  setting {
+    namespace = "aws:elasticbeanstalk:healthreporting:system"
+    name      = "SystemType"
+    value     = var.healthreporting_system_type
+  }
+
+  # aws:elasticbeanstalk:managedactions
+  setting {
+    namespace = "aws:elasticbeanstalk:managedactions"
+    name      = "ManagedActionsEnabled"
+    value     = var.managedactions_managed_actions_enabled ? "true" : "false"
+  }
+
+  setting {
+    namespace = "aws:elasticbeanstalk:managedactions"
+    name      = "PreferredStartTime"
+    value     = var.managedactions_preferred_start_time
+  }
+
+  # aws:elasticbeanstalk:managedactions:platformupdate
+  setting {
+    namespace = "aws:elasticbeanstalk:managedactions:platformupdate"
+    name      = "UpdateLevel"
+    value     = var.managedactions_platformupdate_update_level
+  }
+
+  setting {
+    namespace = "aws:elasticbeanstalk:managedactions:platformupdate"
+    name      = "InstanceRefreshEnabled"
+    value     = var.managedactions_platformupdate_instance_refresh_enabled
+  }
+
+  # aws:autoscaling:asg
+  setting {
+    namespace = "aws:autoscaling:asg"
+    name      = "MinSize"
+    value     = var.autoscaling_asg_minsize
+  }
+  setting {
+    namespace = "aws:autoscaling:asg"
+    name      = "MaxSize"
+    value     = var.autoscaling_asg_maxsize
+  }
+
+  # aws:autoscaling:trigger
+  setting {
+    namespace = "aws:autoscaling:trigger"
+    name      = "MeasureName"
+    value     = var.autoscaling_trigger_measure_name
+  }
+
+  setting {
+    namespace = "aws:autoscaling:trigger"
+    name      = "Statistic"
+    value     = var.autoscaling_trigger_statistic
+  }
+
+  setting {
+    namespace = "aws:autoscaling:trigger"
+    name      = "Unit"
+    value     = var.autoscaling_trigger_unit
+  }
+
+  setting {
+    namespace = "aws:autoscaling:trigger"
+    name      = "LowerThreshold"
+    value     = var.autoscaling_trigger_lower_threshold
+  }
+
+  setting {
+    namespace = "aws:autoscaling:trigger"
+    name      = "LowerBreachScaleIncrement"
+    value     = var.autoscaling_trigger_lower_breach_scale_increment
+  }
+
+  setting {
+    namespace = "aws:autoscaling:trigger"
+    name      = "UpperThreshold"
+    value     = var.autoscaling_trigger_upper_threshold
+  }
+
+  setting {
+    namespace = "aws:autoscaling:trigger"
+    name      = "UpperBreachScaleIncrement"
+    value     = var.autoscaling_trigger_upper_breach_scale_increment
+  }
+
+  # aws:elasticbeanstalk:hostmanager
+  setting {
+    namespace = "aws:elasticbeanstalk:hostmanager"
+    name      = "LogPublicationControl"
+    value     = var.hostmanager_log_publication_control ? "true" : "false"
+  }
+
+  # aws:elasticbeanstalk:cloudwatch:logs
+  setting {
+    namespace = "aws:elasticbeanstalk:cloudwatch:logs"
+    name      = "StreamLogs"
+    value     = var.cloudwatch_logs_stream_logs ? "true" : "false"
+  }
+
+  setting {
+    namespace = "aws:elasticbeanstalk:cloudwatch:logs"
+    name      = "DeleteOnTerminate"
+    value     = var.cloudwatch_logs_delete_on_terminate ? "true" : "false"
+  }
+
+  setting {
+    namespace = "aws:elasticbeanstalk:cloudwatch:logs"
+    name      = "RetentionInDays"
+    value     = var.cloudwatch_logs_retention_in_days
+  }
+
+  # aws:elasticbeanstalk:cloudwatch:logs:health
+  setting {
+    namespace = "aws:elasticbeanstalk:cloudwatch:logs:health"
+    name      = "HealthStreamingEnabled"
+    value     = var.cloudwatch_logs_health_health_streaming_enabled ? "true" : "false"
+  }
+
+  setting {
+    namespace = "aws:elasticbeanstalk:cloudwatch:logs:health"
+    name      = "DeleteOnTerminate"
+    value     = var.cloudwatch_logs_health_delete_on_terminate ? "true" : "false"
+  }
+
+  setting {
+    namespace = "aws:elasticbeanstalk:cloudwatch:logs:health"
+    name      = "RetentionInDays"
+    value     = var.cloudwatch_logs_health_retention_in_days
+  }
+
+  # aws:elasticbeanstalk:application:environment
+  dynamic "setting" {
+    for_each = var.environment_variables
+    content {
+      namespace = "aws:elasticbeanstalk:application:environment"
+      name      = setting.key
+      value     = setting.value
+    }
+  }
+}
diff --git a/fdio.infra.terraform/1n_aws_t3/output.tf b/fdio.infra.terraform/1n_aws_t3/output.tf
new file mode 100644 (file)
index 0000000..58d6627
--- /dev/null
@@ -0,0 +1,15 @@
+output "cname" {
+  value = aws_elastic_beanstalk_environment.environment.cname
+}
+
+output "envName" {
+  value = aws_elastic_beanstalk_environment.environment.name
+}
+
+output "asgName" {
+  value = aws_elastic_beanstalk_environment.environment.autoscaling_groups[0]
+}
+
+output "lbarn" {
+  value = aws_elastic_beanstalk_environment.environment.load_balancers[0]
+}
\ No newline at end of file
diff --git a/fdio.infra.terraform/1n_aws_t3/variables.tf b/fdio.infra.terraform/1n_aws_t3/variables.tf
new file mode 100644 (file)
index 0000000..4a74df6
--- /dev/null
@@ -0,0 +1,305 @@
+# Variables for elastic beanstalk VPC
+variable "vpc_cidr_block" {
+  description = "The CIDR block for the association."
+  type        = string
+  default     = "192.168.0.0/24"
+}
+
+variable "vpc_enable_dns_hostnames" {
+  description = "Whether or not the VPC has DNS hostname support."
+  type        = bool
+  default     = true
+}
+
+variable "vpc_enable_dns_support" {
+  description = "Whether or not the VPC has DNS support."
+  type        = bool
+  default     = true
+}
+
+variable "vpc_instance_tenancy" {
+  description = "The allowed tenancy of instances launched into the selected VPC."
+  type        = string
+  default     = "default"
+}
+
+# Variables for elastic beanstalk Subnet
+variable "subnet_availability_zone" {
+  description = "AWS availability zone"
+  type        = string
+  default     = "us-east-1a"
+}
+
+# Variables for elastic beanstalk Application
+variable "application_description" {
+  description = "Short description of the application."
+  type        = string
+  default     = "Beanstalk Application"
+}
+
+variable "application_name" {
+  description = "The name of the application, must be unique within account."
+  type        = string
+  default     = "Beanstalk"
+}
+
+variable "appversion_lifecycle_service_role_arn" {
+  description = "The service role ARN to use for application version cleanup. If left empty, the `appversion_lifecycle` block will not be created."
+  type        = string
+  default     = ""
+}
+
+variable "appversion_lifecycle_max_count" {
+  description = "The max number of application versions to keep"
+  type        = number
+  default     = 2
+}
+
+variable "appversion_lifecycle_delete_source_from_s3" {
+  description = "Whether to delete application versions from S3 source"
+  type        = bool
+  default     = false
+}
+
+# Variables for elastic beanstalk Environment
+variable "environment_description" {
+  description = "Short description of the environment."
+  type        = string
+  default     = "Beanstalk Environment"
+}
+
+variable "environment_name" {
+  description = "A unique name for this Environment. This name is used in the application URL."
+  type        = string
+  default     = "Beanstalk-env"
+}
+
+variable "environment_solution_stack_name" {
+  description = "A solution stack to base your environment off of."
+  type        = string
+  default     = "64bit Amazon Linux 2 v3.3.11 running Python 3.8"
+}
+
+variable "environment_tier" {
+  description = "The environment tier specified."
+  type        = string
+  default     = "WebServer"
+}
+
+variable "environment_wait_for_ready_timeout" {
+  description = "The maximum duration to wait for the Elastic Beanstalk Environment to be in a ready state before timing out"
+  type        = string
+  default     = "20m"
+}
+
+variable "environment_version_label" {
+  description = "The name of the Elastic Beanstalk Application Version to use in deployment."
+  type        = string
+  default     = ""
+}
+
+# aws:ec2:instances
+variable "instances_instance_types" {
+  description = "Instances type"
+  type        = string
+  default     = "t3.medium"
+}
+
+# aws:ec2:vpc
+variable "associate_public_ip_address" {
+  description = "Whether to associate public IP addresses to the instances."
+  type        = bool
+  default     = true
+}
+
+variable "elb_scheme" {
+  description = "Specify `internal` if you want to create an internal load balancer in your Amazon VPC so that your Elastic Beanstalk application cannot be accessed from outside your Amazon VPC."
+  type        = string
+  default     = "public"
+}
+
+# aws:elbv2:listener:default
+variable "default_listener_enabled" {
+  description = "Set to false to disable the listener. You can use this option to disable the default listener on port 80."
+  type        = bool
+  default     = true
+}
+
+# aws:elasticbeanstalk:environment
+variable "environment_loadbalancer_type" {
+  description = "Load Balancer type, e.g. 'application' or 'classic'."
+  type        = string
+  default     = "network"
+}
+
+# aws:elasticbeanstalk:environment:process:default
+variable "environment_process_default_healthcheck_interval" {
+  description = "The interval of time, in seconds, that Elastic Load Balancing checks the health of the Amazon EC2 instances of your application."
+  type        = number
+  default     = 10
+}
+
+variable "environment_process_default_healthy_threshold_count" {
+  description = "The number of consecutive successful requests before Elastic Load Balancing changes the instance health status."
+  type        = number
+  default     = 3
+}
+
+variable "environment_process_default_port" {
+  description = "Port application is listening on."
+  type        = number
+  default     = 5000
+}
+
+variable "environment_process_default_unhealthy_threshold_count" {
+  description = "The number of consecutive unsuccessful requests before Elastic Load Balancing changes the instance health status."
+  type        = number
+  default     = 3
+}
+
+# aws:elasticbeanstalk:healthreporting:system
+variable "healthreporting_system_type" {
+  description = "Whether to enable enhanced health reporting for this environment"
+  type        = string
+  default     = "enhanced"
+}
+
+# aws:elasticbeanstalk:managedactions
+variable "managedactions_managed_actions_enabled" {
+  description = "Enable managed platform updates. When you set this to true, you must also specify a `PreferredStartTime` and `UpdateLevel`"
+  type        = bool
+  default     = true
+}
+
+variable "managedactions_preferred_start_time" {
+  description = "Configure a maintenance window for managed actions in UTC"
+  type        = string
+  default     = "Sun:10:00"
+}
+
+# aws:elasticbeanstalk:managedactions:platformupdate
+variable "managedactions_platformupdate_update_level" {
+  description = "The highest level of update to apply with managed platform updates"
+  type        = string
+  default     = "minor"
+}
+
+variable "managedactions_platformupdate_instance_refresh_enabled" {
+  description = "Enable weekly instance replacement."
+  type        = bool
+  default     = true
+}
+
+# aws:autoscaling:asg
+variable "autoscaling_asg_minsize" {
+  description = "Minumum instances to launch"
+  type        = number
+  default     = 1
+}
+
+variable "autoscaling_asg_maxsize" {
+  description = "Maximum instances to launch"
+  type        = number
+  default     = 2
+}
+
+# aws:autoscaling:trigger
+variable "autoscaling_trigger_measure_name" {
+  description = "Metric used for your Auto Scaling trigger"
+  type        = string
+  default     = "CPUUtilization"
+}
+
+variable "autoscaling_trigger_statistic" {
+  description = "Statistic the trigger should use, such as Average"
+  type        = string
+  default     = "Average"
+}
+
+variable "autoscaling_trigger_unit" {
+  description = "Unit for the trigger measurement, such as Bytes"
+  type        = string
+  default     = "Percent"
+}
+
+variable "autoscaling_trigger_lower_threshold" {
+  description = "Minimum level of autoscale metric to remove an instance"
+  type        = number
+  default     = 20
+}
+
+variable "autoscaling_trigger_lower_breach_scale_increment" {
+  description = "How many Amazon EC2 instances to remove when performing a scaling activity."
+  type        = number
+  default     = -1
+}
+
+variable "autoscaling_trigger_upper_threshold" {
+  description = "Maximum level of autoscale metric to add an instance"
+  type        = number
+  default     = 80
+}
+
+variable "autoscaling_trigger_upper_breach_scale_increment" {
+  description = "How many Amazon EC2 instances to add when performing a scaling activity"
+  type        = number
+  default     = 1
+}
+
+# aws:elasticbeanstalk:hostmanager
+variable "hostmanager_log_publication_control" {
+  description = "Copy the log files for your application's Amazon EC2 instances to the Amazon S3 bucket associated with your application"
+  type        = bool
+  default     = true
+}
+
+# aws:elasticbeanstalk:cloudwatch:logs
+variable "cloudwatch_logs_stream_logs" {
+  description = "Whether to create groups in CloudWatch Logs for proxy and deployment logs, and stream logs from each instance in your environment"
+  type        = bool
+  default     = true
+}
+
+variable "cloudwatch_logs_delete_on_terminate" {
+  description = "Whether to delete the log groups when the environment is terminated. If false, the logs are kept RetentionInDays days"
+  type        = bool
+  default     = true
+}
+
+variable "cloudwatch_logs_retention_in_days" {
+  description = "The number of days to keep log events before they expire."
+  type        = number
+  default     = 3
+}
+
+# aws:elasticbeanstalk:cloudwatch:logs:health
+variable "cloudwatch_logs_health_health_streaming_enabled" {
+  description = "For environments with enhanced health reporting enabled, whether to create a group in CloudWatch Logs for environment health and archive Elastic Beanstalk environment health data. For information about enabling enhanced health, see aws:elasticbeanstalk:healthreporting:system."
+  type        = bool
+  default     = true
+}
+
+variable "cloudwatch_logs_health_delete_on_terminate" {
+  description = "Whether to delete the log group when the environment is terminated. If false, the health data is kept RetentionInDays days."
+  type        = bool
+  default     = true
+}
+
+variable "cloudwatch_logs_health_retention_in_days" {
+  description = "The number of days to keep the archived health data before it expires."
+  type        = number
+  default     = 3
+}
+
+variable "environment_type" {
+  description = "Environment type, e.g. 'LoadBalanced' or 'SingleInstance'. If setting to 'SingleInstance', `rolling_update_type` must be set to 'Time', `updating_min_in_service` must be set to 0, and `loadbalancer_subnets` will be unused (it applies to the ELB, which does not exist in SingleInstance environments)."
+  type        = string
+  default     = "LoadBalanced"
+}
+
+# aws:elasticbeanstalk:application:environment
+variable "environment_variables" {
+  description = "Map of custom ENV variables to be provided to the application."
+  type        = map(string)
+  default     = {}
+}
diff --git a/fdio.infra.terraform/1n_aws_t3/versions.tf b/fdio.infra.terraform/1n_aws_t3/versions.tf
new file mode 100644 (file)
index 0000000..d0e9db3
--- /dev/null
@@ -0,0 +1,12 @@
+terraform {
+  required_providers {
+    aws = {
+      source  = "hashicorp/aws"
+      version = "~> 4.3.0"
+    }
+    vault = {
+      version = ">= 3.2.1"
+    }
+  }
+  required_version = ">= 1.1.4"
+}
diff --git a/resources/tools/dash/app/Procfile b/resources/tools/dash/app/Procfile
new file mode 100644 (file)
index 0000000..c79d502
--- /dev/null
@@ -0,0 +1 @@
+uwsgi: uwsgi app.ini
index bbf2943..0df9d83 100644 (file)
@@ -12,6 +12,4 @@ master = true
 http-socket = :5000
 socket = /tmp/app.sock
 chmod-socket = 666
-vacuum = true
 
-die-on-term = true
\ No newline at end of file
index 55f92cc..76f6641 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from os import environ
-
-
 class Config:
     """Flask configuration variables.
     """
 
     # General Config
-    FLASK_APP = environ.get("FLASK_APP")
-    FLASK_ENV = environ.get("FLASK_ENV")
-    SECRET_KEY = environ.get("SECRET_KEY")
+    FLASK_APP = "wsgi.py"
+    FLASK_ENV = "production"
 
     # Assets
-    LESS_BIN = environ.get("LESS_BIN")
-    ASSETS_DEBUG = environ.get("ASSETS_DEBUG")
-    LESS_RUN_IN_DEBUG = environ.get("LESS_RUN_IN_DEBUG")
+    LESS_BIN = "/usr/local/bin/lessc"
+    ASSETS_DEBUG = "False"
+    LESS_RUN_IN_DEBUG = "False"
 
     # Static Assets
     STATIC_FOLDER = "static"
     TEMPLATES_FOLDER = "templates"
-    COMPRESSOR_DEBUG = environ.get("COMPRESSOR_DEBUG")
+    COMPRESSOR_DEBUG ="True"
index 316901c..ab18bbf 100644 (file)
@@ -17,4 +17,5 @@ from pal import app
 
 if __name__ == "__main__":
     # Main entry point.
+    app.debug = True
     app.run(host="0.0.0.0")
index 4fe12bd..155678a 100644 (file)
@@ -6,12 +6,6 @@ services:
     environment:
       AWS_ACCESS_KEY_ID: ""
       AWS_SECRET_ACCESS_KEY: ""
-      FLASK_APP: "wsgi.py"
-      FLASK_ENV: "production"
-      LESS_BIN: "/usr/local/bin/lessc"
-      ASSETS_DEBUG: "False"
-      LESS_RUN_IN_DEBUG: "False"
-      COMPRESSOR_DEBUG: "True"
     ports:
       - "5000:5000"
     volumes: