diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml index b05f777..6c57245 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yml +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -10,19 +10,12 @@ body: value: | Thank you for taking the time to file a bug report. Please make sure to search for existing issues before filing a new one. - - - type: input - id: contact - attributes: - label: Contact Details - description: An email address that we can reach out to you if we need more information. - placeholder: ex. email@example.com - type: textarea id: what-happened attributes: label: What happened? description: What did you expect to happen? (provide screenshots if possible) - value: "A bug happened!" + placeholder: "A bug happened!" validations: required: true - type: input @@ -30,12 +23,13 @@ body: attributes: label: Which module? description: "Which module(s) are you having problems with?" - value: "ex. Root, S3, EFS, IAM, VPC, S3-Policy, SecurityGroup" + placeholder: "ex. Root, S3, EFS, IAM, VPC, S3-Policy, SecurityGroup" - type: dropdown id: version attributes: label: Module version description: What version of the modules are you using? + multiple: false options: - 0.1.0 (Default) validations: @@ -45,6 +39,7 @@ body: attributes: label: Terraform version description: What version of Terraform are you using? + multiple: false options: - 1.3.x (Default) - 1.2.x @@ -58,6 +53,7 @@ body: attributes: label: Is it blocking work? description: Please choose one? + multiple: false options: - "no" - "yes" diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature-request.yml index c627950..da8205d 100644 --- a/.github/ISSUE_TEMPLATE/feature-request.yml +++ b/.github/ISSUE_TEMPLATE/feature-request.yml @@ -10,19 +10,12 @@ body: value: | Thank you for taking the time to request a new feature. Please make sure to search for existing issues before filing a new one. - - - type: input - id: contact - attributes: - label: Contact Details - description: An email address that we can reach out to you if we need more information. - placeholder: ex. email@example.com - type: textarea id: new-feature attributes: label: What are you looking for? description: Please provide a detailed explanation of the new feature request you are looking for. - value: "Feature request!!" + placeholder: "Feature request!!" validations: required: true - type: input @@ -30,12 +23,13 @@ body: attributes: label: Which module? description: "Which module(s) are you having problems with?" - value: "ex. Root, S3, EFS, IAM, VPC, S3-Policy, SecurityGroup" + placeholder: "ex. Root, S3, EFS, IAM, VPC, S3-Policy, SecurityGroup" - type: dropdown id: blocking_work attributes: label: Is it blocking work? description: Please choose one? + multiple: false options: - "no" - "yes" @@ -46,6 +40,7 @@ body: attributes: label: Terraform version description: What version of Terraform are you using? + multiple: false options: - 1.3.x (Default) - 1.2.x diff --git a/.github/labeler.yml b/.github/labeler.yml index d1768db..c64869a 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,17 +1,5 @@ -name: "Pull Request Labeler" -on: [pull_request] - -permissions: read-all - -jobs: - add-label: - permissions: - contents: read - pull-requests: write - runs-on: ubuntu-latest - steps: - - uses: actions/labeler@v4 - with: - repo-token: "${{ secrets.GITHUB_TOKEN }}" - configuration-path: ".github/labeler.yml" - sync-labels: true +# See https://github.com/actions/labeler for details +# "dependencies" label for any changes in dependency files +# Add 'repo' label to any root file changes +repo: +- '*' diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml new file mode 100644 index 0000000..ceeb12a --- /dev/null +++ b/.github/workflows/labeler.yml @@ -0,0 +1,16 @@ +name: "Pull Request Labeler" +on: + - pull_request + +jobs: + add-label: + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + steps: + - uses: actions/labeler@v4 + with: + repo-token: "${{ secrets.GITHUB_TOKEN }}" + configuration-path: ".github/labeler.yml" + sync-labels: true diff --git a/.github/main.yml b/.github/workflows/main.yml similarity index 100% rename from .github/main.yml rename to .github/workflows/main.yml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d10d4f3..d18002f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,7 +2,7 @@ default_stages: [commit] repos: - repo: https://github.com/antonbabenko/pre-commit-terraform - rev: v1.77.0 + rev: v1.77.1 hooks: - id: terraform_fmt - id: terraform_validate diff --git a/README.md b/README.md index 1bc16b1..67a187a 100644 --- a/README.md +++ b/README.md @@ -70,32 +70,45 @@ No resources. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| [anyscale\_access\_steadystate\_policy\_name](#input\_anyscale\_access\_steadystate\_policy\_name) | (Optional)
Name for the Anyscale default steady state IAM policy.
If left `null`, will default to `anyscale_access_steadystate_policy_prefix`
If provided, overrides the `anyscale_access_steadystate_policy_prefix` variable.
Default is `null`. | `string` | `null` | no | +| [anyscale\_access\_steadystate\_policy\_prefix](#input\_anyscale\_access\_steadystate\_policy\_prefix) | (Optional)
Name prefix for the Anyscale default steady state IAM policy.
If `anyscale_access_steadystate_policy_name` is provided, it will override this variable.
The variable `general_prefix` is a fall-back prefix if this is not provided.
Default is `null` but is set to `anyscale-steady_state-` in a local variable. | `string` | `null` | no | | [anyscale\_cloud\_id](#input\_anyscale\_cloud\_id) | (Optional) Anyscale Cloud ID. Default is `null`. | `string` | `null` | no | +| [anyscale\_custom\_s3\_policy](#input\_anyscale\_custom\_s3\_policy) | (Optional)
A valid bucket policy in JSON. This will be an additional S3 bucket policy to the required Anyscale policy.
For more information about building AWS IAM policy documents with Terraform, see the AWS IAM Policy Document Guide.
And for more additional examples, please look at the s3-policy sub-module examples folder.
Default is `null`. | `string` | `null` | no | | [anyscale\_deploy\_env](#input\_anyscale\_deploy\_env) | (Required) Anyscale deploy environment. Used in resource names and tags. | `string` | n/a | yes | +| [anyscale\_efs\_tags](#input\_anyscale\_efs\_tags) | (Optional)
A map of tags for EFS resources.
Duplicate tags found in the "tags" variable will get duplicated on the resource.
ex:
anyscale\_iam\_tags = {
"purpose" : "storage",
"criticality" : "critical"
}
Default is an empty map. | `map(string)` | `{}` | no | +| [anyscale\_gateway\_vpc\_endpoints](#input\_anyscale\_gateway\_vpc\_endpoints) | A map of Gateway VPC Endpoints to provision into the VPC. This is a map of objects with the following attributes:
- `name`: Short service name (either "s3" or "dynamodb")
- `policy` = A policy (as JSON string) to attach to the endpoint that controls access to the service. May be `null` for full access.
See the submodule variable for a full example.
It is Anyscale's recommendation to have an S3 VPC Endpoint to minimize S3 costs and maximize S3 performance.
Set to an empty map `{}` to skip creating VPC Endpoints.
Default is S3 with an empty (full access) policy. |
map(object({
name = string
policy = string
}))
|
{
"s3": {
"name": "s3",
"policy": null
}
}
| no | | [anyscale\_iam\_access\_role\_name](#input\_anyscale\_iam\_access\_role\_name) | (Optional, forces creation of new resource)
The name of the Anyscale IAM access role.
If left `null`, will default to anyscale\_iam\_access\_role\_name\_prefix.
If provided, overrides the anyscale\_iam\_access\_role\_name\_prefix variable.
Default is `null`. | `string` | `null` | no | -| [anyscale\_iam\_access\_role\_name\_prefix](#input\_anyscale\_iam\_access\_role\_name\_prefix) | (Optional, forces creation of new resource)
The prefix for the Anyscale IAM access role.
The variable, anyscale\_iam\_access\_role\_name, will override this variable.
Default is `anyscale-iam-role-`. | `string` | `"anyscale-iam-role-"` | no | +| [anyscale\_iam\_access\_role\_name\_prefix](#input\_anyscale\_iam\_access\_role\_name\_prefix) | (Optional, forces creation of new resource)
The prefix for the Anyscale IAM access role.
If `anyscale_iam_access_role_name_prefix` is provided, it will override this variable.
The variable `general_prefix` is a fall-back prefix if this is not provided.
Default is `null` but is set to `anyscale-iam-role-` in a local variable. | `string` | `null` | no | | [anyscale\_iam\_cluster\_node\_role\_name](#input\_anyscale\_iam\_cluster\_node\_role\_name) | (Optional, forces creation of new resource)
The name of the Anyscale IAM cluster node role.
If left `null`, will default to anyscale\_iam\_access\_role\_name\_prefix.
Default is `null`. | `string` | `null` | no | -| [anyscale\_iam\_cluster\_node\_role\_name\_prefix](#input\_anyscale\_iam\_cluster\_node\_role\_name\_prefix) | (Optional, forces creation of new resource)
The prefix of the Anyscale Cluster Node IAM role.
The variable, anyscale\_iam\_cluster\_node\_role\_name, will override this variable.
Default is `anyscale-cluster-node-`. | `string` | `"anyscale-cluster-node-"` | no | +| [anyscale\_iam\_cluster\_node\_role\_name\_prefix](#input\_anyscale\_iam\_cluster\_node\_role\_name\_prefix) | (Optional, forces creation of new resource)
The prefix of the Anyscale Cluster Node IAM role.
If `anyscale_iam_cluster_node_role_name` is provided, it will override this variable.
The variable `general_prefix` is a fall-back prefix if this is not provided.
Default is `null` but is set to `anyscale-cluster-node-` in a local variable. | `string` | `null` | no | +| [anyscale\_iam\_tags](#input\_anyscale\_iam\_tags) | (Optional)
A map of tags for IAM resources.
Duplicate tags found in the "tags" variable will get duplicated on the resource.
ex:
anyscale\_iam\_tags = {
"purpose" : "iam",
"criticality" : "critical"
}
Default is an empty map. | `map(string)` | `{}` | no | | [anyscale\_s3\_bucket\_name](#input\_anyscale\_s3\_bucket\_name) | (Optional - forces new resource)
The name of the bucket used to store Anyscale related logs and other shared resources.
If left `null`, will default to anyscale\_s3\_bucket\_prefix.
If provided, overrides the anyscale\_s3\_bucket\_prefix variable.
Conflicts with anyscale\_bucket\_prefix. Default is `null`. | `string` | `null` | no | -| [anyscale\_s3\_bucket\_prefix](#input\_anyscale\_s3\_bucket\_prefix) | (Optional - forces new resource)
Creates a unique bucket name beginning with the specified prefix.
If `anyscale_s3_bucket_name` is provided, it will override this variable.
Default is `anyscale-`. | `string` | `"anyscale-"` | no | +| [anyscale\_s3\_bucket\_prefix](#input\_anyscale\_s3\_bucket\_prefix) | (Optional - forces new resource)
Creates a unique bucket name beginning with the specified prefix.
If `anyscale_s3_bucket_name` is provided, it will override this variable.
The variable `general_prefix` is a fall-back prefix if this is not provided.
Default is `null` but is set to `anyscale-` in a local variable. | `string` | `null` | no | +| [anyscale\_s3\_force\_destroy](#input\_anyscale\_s3\_force\_destroy) | (Optional)
Set to true to delete all objects from the bucket so that the bucket can be destroyed without error.
If set to true and bucket is destroyed, objects are not recoverable.
Default is `false`.
Note: With this default, you need to empty the bucket if there are objects before `terraform destroy` can be completed succesfully. | `bool` | `false` | no | +| [anyscale\_s3\_server\_side\_encryption](#input\_anyscale\_s3\_server\_side\_encryption) | (Optional)
Configuration to enforce server side encryption (KMS or AES256).
If you are using KMS, you must proivde the KMS Key ID.
ex using kms:
apply\_server\_side\_encryption\_by\_default = {
kms\_master\_key\_id = "1234abcd-12ab-34cd-56ef-1234567890ab"
sse\_algorithm = "aws:kms"
}
Default is `{ sse_algorithm = "AES256" }` | `map(string)` |
{
"sse_algorithm": "AES256"
}
| no | +| [anyscale\_s3\_tags](#input\_anyscale\_s3\_tags) | (Optional)
A map of tags for S3 resources.
Duplicate tags found in the "tags" variable will get duplicated on the resource.
ex:
anyscale\_iam\_tags = {
"purpose" : "storage",
"criticality" : "critical"
}
Default is an empty map. | `map(string)` | `{}` | no | +| [anyscale\_securitygroup\_tags](#input\_anyscale\_securitygroup\_tags) | (Optional)
A map of tags for Security Group resources.
Duplicate tags found in the "tags" variable will get duplicated on the resource.
ex:
anyscale\_iam\_tags = {
"purpose" : "security",
"criticality" : "critical"
}
Default is an empty map. | `map(string)` | `{}` | no | | [anyscale\_vpc\_cidr\_block](#input\_anyscale\_vpc\_cidr\_block) | (Optional) The IPv4 CIDR block for the VPC. CIDR can be explicitly set or it can be derived from IPAM using `ipv4_netmask_length` & `ipv4_ipam_pool_id`. Default is `10.0.0.0/16` | `string` | `"10.0.0.0/16"` | no | | [anyscale\_vpc\_name](#input\_anyscale\_vpc\_name) | (Optional) VPC name. Will default to `vpc_`. | `string` | `null` | no | | [anyscale\_vpc\_private\_subnets](#input\_anyscale\_vpc\_private\_subnets) | (Optional) A list of private subnets inside the VPC. Default is an empty list. | `list(string)` | `[]` | no | | [anyscale\_vpc\_public\_subnets](#input\_anyscale\_vpc\_public\_subnets) | (Optional) A list of public subnets inside the VPC. Default is an empty list. | `list(string)` | `[]` | no | -| [cloud\_provider](#input\_cloud\_provider) | (Required) Which cloud provider would you like to run this module on? Valid options are `aws` or `gcp`. Default is `aws`. | `string` | `"aws"` | no | +| [anyscale\_vpc\_tags](#input\_anyscale\_vpc\_tags) | (Optional)
A map of tags for VPC resources.
Duplicate tags found in the "tags" variable will get duplicated on the resource.
ex:
anyscale\_vpc\_tags = {
"purpose" : "networking",
"criticality" : "critical"
}
Default is an empty map. | `map(string)` | `{}` | no | | [efs\_creation\_token](#input\_efs\_creation\_token) | (Optional) A unique token used as reference when creating the Elastic File System to ensure idempotent file system creation.
Default is `null` which forces Terraform to generate it. | `string` | `null` | no | | [efs\_lifecycle\_transition\_to\_ia](#input\_efs\_lifecycle\_transition\_to\_ia) | (Optional) Indicates how long it takes to transition files to Infrequent Access storage class.
No value, or an empty list, means never.
Must either be an empty list or one of "AFTER\_7\_DAYS", "AFTER\_14\_DAYS", "AFTER\_30\_DAYS", "AFTER\_60\_DAYS", "AFTER\_90\_DAYS".
Default is `AFTER_60_DAYS` which will transition to IA after 60 days. | `list(string)` |
[
"AFTER_60_DAYS"
]
| no | | [efs\_lifecycle\_transition\_to\_primary\_storage\_class](#input\_efs\_lifecycle\_transition\_to\_primary\_storage\_class) | (Optional) Indicates the policy used to transition a file from Infrequent Access (IA) storage to primary storage.
Must either be an empty list or `AFTER_1_ACCESS`.
Default is `AFTER_1_ACCESS`. | `list(string)` |
[
"AFTER_1_ACCESS"
]
| no | | [efs\_name](#input\_efs\_name) | (Optional) Elastic file system name. Will default to `efs_anyscale` if this var `null` and anyscale\_cloud\_id is also `null`.
Default is `null`. | `string` | `null` | no | -| [existing\_subnet\_ids](#input\_existing\_subnet\_ids) | (Optional) Existing subnet IDs to create Anyscale resources in. If provided, this will skip creating resources with the Anyscale VPC module. VPC ID is also required is this is provided. Default is an empty list. | `list(string)` | `[]` | no | +| [existing\_s3\_bucket\_arn](#input\_existing\_s3\_bucket\_arn) | (Optional)
The name of an existing S3 bucket that you'd like to use.
Please make sure that it meets the minimum requirements for Anyscale including:
- Bucket Policy
- CORS Policy
- Encryption configuration
Default is `null` | `string` | `null` | no | | [existing\_vpc\_id](#input\_existing\_vpc\_id) | (Optional) An existing VPC ID. If provided, this will skip creating resources with the Anyscale VPC module. Subnet IDs is also required if this is provided. Default is `null`. | `string` | `null` | no | +| [existing\_vpc\_route\_table\_ids](#input\_existing\_vpc\_route\_table\_ids) | (Optional)
Existing VPC Route Table IDs.
If provided, this will map new subnets to these route table IDs. If no new subnets are created, these route tables will be used to create VPC Endpoint(s). | `list(string)` | `[]` | no | +| [existing\_vpc\_subnet\_ids](#input\_existing\_vpc\_subnet\_ids) | (Optional) Existing subnet IDs to create Anyscale resources in. If provided, this will skip creating resources with the Anyscale VPC module. VPC ID is also required is this is provided. Default is an empty list. | `list(string)` | `[]` | no | +| [general\_prefix](#input\_general\_prefix) | (Optional)
A general prefix to add to resources created (where prefixes are allowed). This applies to:
- S3 Buckets
- IAM Resources
- Security Groups
Resource specific prefixes override this variable.
Default is `null` | `string` | `null` | no | | [security\_group\_create\_anyscale\_public\_ingress](#input\_security\_group\_create\_anyscale\_public\_ingress) | (Optional) Determines if public ingress rules should be created. Default is `false`. | `bool` | `false` | no | | [security\_group\_ingress\_allow\_access\_from\_cidr\_range](#input\_security\_group\_ingress\_allow\_access\_from\_cidr\_range) | (Required) Comma delimited string of IPv4 CIDR range to allow access to anyscale resources.
This should be the list of CIDR ranges that have access to the clusters. If using Anyscale v1,
this should be public IPs. If using Anyscale v2, public or private IPs are supported. SSH and HTTPs
ports will be opened to these CIDR ranges.
ex: "10.0.1.0/24,24.1.24.24/32" | `string` | n/a | yes | | [security\_group\_ingress\_with\_existing\_security\_groups\_map](#input\_security\_group\_ingress\_with\_existing\_security\_groups\_map) | (Optional) List of security groups and rules to allow ingress from. Default is an empty list. | `list(map(string))` | `[]` | no | | [security\_group\_name](#input\_security\_group\_name) | (Optional) The name for the security group. If provided, overrides the security\_group\_name\_prefix.
Default is `null`. | `string` | `null` | no | -| [security\_group\_name\_prefix](#input\_security\_group\_name\_prefix) | (Optional) The name prefix for the security group. Conflicts with security\_group\_name. Default is `anyscale-security-group-`. | `string` | `"anyscale-security-group-"` | no | +| [security\_group\_name\_prefix](#input\_security\_group\_name\_prefix) | (Optional)
The name prefix for the security group.
If `security_group_name` is provided, it will override this variable.
The variable `general_prefix` is a fall-back prefix if this is not provided.

Default is `null` but is set to `anyscale-security-group-` in a local variable. | `string` | `null` | no | | [security\_group\_override\_ingress\_from\_cidr\_map](#input\_security\_group\_override\_ingress\_from\_cidr\_map) | (Optional) List of ingress rules to create with cidr ranges.
If this variable is provided/populated, the default rules will not be created. At a minimum, https and ssh need
to be allowed from a IPv4 CIDR block that allows access for the users who are using Anyscale.
Default is an empty list. | `list(map(string))` | `[]` | no | -| [tags](#input\_tags) | (Optional) A map of tags to all resources that accept tags. | `map(string)` | `{}` | no | +| [tags](#input\_tags) | (Optional)
A map of default tags to be added to all resources that accept tags.
Resource dependent tags will be appended to this list.
ex:
tags = {
application = "Anyscale",
environment = "prod"
}
Default is an empty map. | `map(string)` | `{}` | no | ## Outputs diff --git a/examples/anyscale-v1-existing-vpc/main.tf b/examples/anyscale-v1-existing-vpc/main.tf index 408be43..4848d08 100644 --- a/examples/anyscale-v1-existing-vpc/main.tf +++ b/examples/anyscale-v1-existing-vpc/main.tf @@ -23,11 +23,10 @@ module "aws_anyscale_v1_existing_vpc" { anyscale_deploy_env = var.anyscale_deploy_env anyscale_cloud_id = var.anyscale_cloud_id - cloud_provider = "aws" # VPC Related - existing_vpc_id = local.existing_vpc_id - existing_subnet_ids = local.existing_subnet_ids + existing_vpc_id = local.existing_vpc_id + existing_vpc_subnet_ids = local.existing_subnet_ids # Security Group Related security_group_create_anyscale_public_ingress = true diff --git a/examples/anyscale-v1/main.tf b/examples/anyscale-v1/main.tf index 5e03246..7b2b188 100644 --- a/examples/anyscale-v1/main.tf +++ b/examples/anyscale-v1/main.tf @@ -26,7 +26,6 @@ module "aws_anyscale_v1" { anyscale_deploy_env = var.anyscale_deploy_env anyscale_cloud_id = var.anyscale_cloud_id - cloud_provider = "aws" # VPC Related anyscale_vpc_cidr_block = local.cidr_block diff --git a/examples/anyscale-v2-existing-vpc/main.tf b/examples/anyscale-v2-existing-vpc/main.tf new file mode 100644 index 0000000..9188c0c --- /dev/null +++ b/examples/anyscale-v2-existing-vpc/main.tf @@ -0,0 +1,33 @@ +# --------------------------------------------------------------------------------------------------------------------- +# Create core Anyscale v2 Stack with existing VPC (Public Subnets) +# Creates a v2 stack including +# - IAM Roles +# - S3 Bucket +# - VPC Security Groups +# - EFS +# --------------------------------------------------------------------------------------------------------------------- +locals { + full_tags = merge(tomap({ + anyscale-cloud-id = var.anyscale_cloud_id, + anyscale-deploy-environment = var.anyscale_deploy_env + }), + var.tags + ) + existing_vpc_id = "vpc-086408b268f481027" + existing_public_subnet_ids = ["subnet-06154a164989c0f8d", "subnet-05f678cbbba3d9a1d", "subnet-0f7b63788905e3eb2"] +} + +module "aws_anyscale_v2_existing_vpc" { + source = "../../" + tags = local.full_tags + + anyscale_deploy_env = var.anyscale_deploy_env + anyscale_cloud_id = var.anyscale_cloud_id + + # VPC Related + existing_vpc_id = local.existing_vpc_id + existing_vpc_subnet_ids = local.existing_public_subnet_ids + + # Security Group Related + security_group_ingress_allow_access_from_cidr_range = var.customer_ingress_cidr_ranges +} diff --git a/examples/anyscale-v2-existing-vpc/outputs.tf b/examples/anyscale-v2-existing-vpc/outputs.tf new file mode 100644 index 0000000..bd9ac1f --- /dev/null +++ b/examples/anyscale-v2-existing-vpc/outputs.tf @@ -0,0 +1,27 @@ +# --------------------------------------------------------------------------------------------------------------------- +# Anyscale v2 Stack with existing VPC +# --------------------------------------------------------------------------------------------------------------------- +output "anyscale_v2_existing_vpc_s3_bucket_id" { + description = "Anyscale S3 Bucket ID. If a bucket was not created, return an empty string." + value = try(module.aws_anyscale_v2_existing_vpc.anyscale_s3_bucket_id, "") +} + +output "anyscale_v2_existing_vpc_security_group_id" { + description = "Anyscale Security Group ID. If a security group was not created, return an empty string." + value = try(module.aws_anyscale_v2_existing_vpc.anyscale_security_group_id, "") +} + +output "anyscale_v2_existing_vpc_iam_role_arn" { + description = "Anyscale IAM access role arn." + value = try(module.aws_anyscale_v2_existing_vpc.anyscale_iam_role_arn, "") +} + +output "anyscale_v2_existing_vpc_iam_instance_role_arn" { + description = "Anyscale IAM instance role arn." + value = try(module.aws_anyscale_v2_existing_vpc.anyscale_iam_role_cluster_node_arn, "") +} + +output "anyscale_v2_existing_vpc_efs_id" { + description = "Anyscale Elastic File System ID." + value = try(module.aws_anyscale_v2_existing_vpc.anyscale_efs_id, "") +} diff --git a/examples/anyscale-v2-existing-vpc/variables.tf b/examples/anyscale-v2-existing-vpc/variables.tf new file mode 100644 index 0000000..64ece92 --- /dev/null +++ b/examples/anyscale-v2-existing-vpc/variables.tf @@ -0,0 +1,66 @@ +# --------------------------------------------------------------------------------------------------------------------- +# ENVIRONMENT VARIABLES +# Define these secrets as environment variables +# --------------------------------------------------------------------------------------------------------------------- + +# AWS_ACCESS_KEY_ID +# AWS_SECRET_ACCESS_KEY + +# --------------------------------------------------------------------------------------------------------------------- +# REQUIRED VARIABLES +# These variables must be set when using this module. +# --------------------------------------------------------------------------------------------------------------------- + +variable "aws_region" { + description = "The AWS region in which all resources will be created." + type = string +} + +variable "anyscale_deploy_env" { + description = "(Required) Anyscale deploy environment. Used in resource names and tags." + type = string + validation { + condition = ( + var.anyscale_deploy_env == "production" || var.anyscale_deploy_env == "development" || var.anyscale_deploy_env == "test" + ) + error_message = "The anyscale_deploy_env only allows `production`, `test`, or `development`" + } +} + +# ------------------------------------------------------------------------------ +# OPTIONAL PARAMETERS +# These variables have defaults, but may be overridden. +# ------------------------------------------------------------------------------ +variable "anyscale_cloud_id" { + description = "(Optional) Anyscale Cloud ID. Default is `null`." + type = string + default = null + validation { + condition = ( + var.anyscale_cloud_id == null ? true : ( + length(var.anyscale_cloud_id) > 4 && + substr(var.anyscale_cloud_id, 0, 4) == "cld_" + ) + ) + error_message = "The anyscale_cloud_id value must start with \"cld_\"." + } +} + +variable "tags" { + description = "(Optional) A map of tags to all resources that accept tags." + type = map(string) + default = { + "test" : true, + "environment" : "test" + } +} + +variable "customer_ingress_cidr_ranges" { + description = <<-EOT + The IPv4 CIDR block that is allowed to access the clusters. + This provides the ability to lock down the v1 stack to just the public IPs of a corporate network. + This is added to the security group and allows port 443 (https) and 22 (ssh) access. + ex: `52.1.1.23/32,10.1.0.0/16' + EOT + type = string +} diff --git a/examples/anyscale-v2-existing-vpc/versions.tf b/examples/anyscale-v2-existing-vpc/versions.tf new file mode 100644 index 0000000..df08979 --- /dev/null +++ b/examples/anyscale-v2-existing-vpc/versions.tf @@ -0,0 +1,13 @@ +terraform { + required_version = ">= 1.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.0" + } + } +} + +provider "aws" { + region = var.aws_region +} diff --git a/examples/anyscale-v2/main.tf b/examples/anyscale-v2/main.tf new file mode 100644 index 0000000..8ce759b --- /dev/null +++ b/examples/anyscale-v2/main.tf @@ -0,0 +1,36 @@ +# --------------------------------------------------------------------------------------------------------------------- +# Create core Anyscale v2 Stack resources with minimal parameters +# Should be executed in us-east-2 +# Creates a v2 stack including +# - IAM Roles +# - S3 Bucket +# - VPC with publicly routed subnets (no internal) +# - VPC Security Groups +# - EFS +# --------------------------------------------------------------------------------------------------------------------- + +locals { + full_tags = merge(tomap({ + anyscale-cloud-id = var.anyscale_cloud_id, + anyscale-deploy-environment = var.anyscale_deploy_env + }), + var.tags + ) + cidr_block = "172.24.0.0/16" + public_subnets = ["172.24.101.0/24", "172.24.102.0/24", "172.24.103.0/24"] +} + +module "aws_anyscale_v2" { + source = "../.." + tags = local.full_tags + + anyscale_deploy_env = var.anyscale_deploy_env + anyscale_cloud_id = var.anyscale_cloud_id + + # VPC Related + anyscale_vpc_cidr_block = local.cidr_block + anyscale_vpc_public_subnets = local.public_subnets + + # Security Group Related + security_group_ingress_allow_access_from_cidr_range = var.customer_ingress_cidr_ranges +} diff --git a/examples/anyscale-v2/outputs.tf b/examples/anyscale-v2/outputs.tf new file mode 100644 index 0000000..3451f46 --- /dev/null +++ b/examples/anyscale-v2/outputs.tf @@ -0,0 +1,41 @@ +# --------------------------------------------------------------------------------------------------------------------- +# Anyscale v2 Stack resources with minimal parameters +# --------------------------------------------------------------------------------------------------------------------- +output "anyscale_v2_vpc_id" { + description = "Anyscale VPC ID. If there was not one created, return the one that was used during other resource creation." + value = try(module.aws_anyscale_v2.anyscale_vpc_id, "") +} + +output "anyscale_v2_vpc_public_subnet_ids" { + description = "Anyscale VPC Public Subnet IDs. If there were none created, return an empty string." + value = try(module.aws_anyscale_v2.anyscale_vpc_public_subnet_ids, []) +} +output "anyscale_v2_vpc_private_subnet_ids" { + description = "Anyscale VPC Private Subnet IDs. If there were none created, return an empty string." + value = try(module.aws_anyscale_v2.anyscale_vpc_private_subnet_ids, []) +} + +output "anyscale_v2_s3_bucket_id" { + description = "Anyscale S3 Bucket ID. If a bucket was not created, return an empty string." + value = try(module.aws_anyscale_v2.anyscale_s3_bucket_id, "") +} + +output "anyscale_v2_security_group_id" { + description = "Anyscale Security Group ID. If a security group was not created, return an empty string." + value = try(module.aws_anyscale_v2.anyscale_security_group_id, "") +} + +output "anyscale_v2_iam_role_arn" { + description = "Anyscale IAM access role arn." + value = try(module.aws_anyscale_v2.anyscale_iam_role_arn, "") +} + +output "anyscale_v2_iam_instance_role_arn" { + description = "Anyscale IAM instance role arn." + value = try(module.aws_anyscale_v2.anyscale_iam_role_cluster_node_arn, "") +} + +output "anyscale_v2_efs_id" { + description = "Anyscale Elastic File System ID." + value = try(module.aws_anyscale_v2.anyscale_efs_id, "") +} diff --git a/examples/anyscale-v2/variables.tf b/examples/anyscale-v2/variables.tf new file mode 100644 index 0000000..64ece92 --- /dev/null +++ b/examples/anyscale-v2/variables.tf @@ -0,0 +1,66 @@ +# --------------------------------------------------------------------------------------------------------------------- +# ENVIRONMENT VARIABLES +# Define these secrets as environment variables +# --------------------------------------------------------------------------------------------------------------------- + +# AWS_ACCESS_KEY_ID +# AWS_SECRET_ACCESS_KEY + +# --------------------------------------------------------------------------------------------------------------------- +# REQUIRED VARIABLES +# These variables must be set when using this module. +# --------------------------------------------------------------------------------------------------------------------- + +variable "aws_region" { + description = "The AWS region in which all resources will be created." + type = string +} + +variable "anyscale_deploy_env" { + description = "(Required) Anyscale deploy environment. Used in resource names and tags." + type = string + validation { + condition = ( + var.anyscale_deploy_env == "production" || var.anyscale_deploy_env == "development" || var.anyscale_deploy_env == "test" + ) + error_message = "The anyscale_deploy_env only allows `production`, `test`, or `development`" + } +} + +# ------------------------------------------------------------------------------ +# OPTIONAL PARAMETERS +# These variables have defaults, but may be overridden. +# ------------------------------------------------------------------------------ +variable "anyscale_cloud_id" { + description = "(Optional) Anyscale Cloud ID. Default is `null`." + type = string + default = null + validation { + condition = ( + var.anyscale_cloud_id == null ? true : ( + length(var.anyscale_cloud_id) > 4 && + substr(var.anyscale_cloud_id, 0, 4) == "cld_" + ) + ) + error_message = "The anyscale_cloud_id value must start with \"cld_\"." + } +} + +variable "tags" { + description = "(Optional) A map of tags to all resources that accept tags." + type = map(string) + default = { + "test" : true, + "environment" : "test" + } +} + +variable "customer_ingress_cidr_ranges" { + description = <<-EOT + The IPv4 CIDR block that is allowed to access the clusters. + This provides the ability to lock down the v1 stack to just the public IPs of a corporate network. + This is added to the security group and allows port 443 (https) and 22 (ssh) access. + ex: `52.1.1.23/32,10.1.0.0/16' + EOT + type = string +} diff --git a/examples/anyscale-v2/versions.tf b/examples/anyscale-v2/versions.tf new file mode 100644 index 0000000..df08979 --- /dev/null +++ b/examples/anyscale-v2/versions.tf @@ -0,0 +1,13 @@ +terraform { + required_version = ">= 1.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.0" + } + } +} + +provider "aws" { + region = var.aws_region +} diff --git a/main.tf b/main.tf index c688642..71cd306 100644 --- a/main.tf +++ b/main.tf @@ -6,13 +6,32 @@ locals { }), var.tags ) - existing_subnet_count = length(var.existing_subnet_ids) + + vpc_tags = merge(local.full_tags, var.anyscale_vpc_tags) + iam_tags = merge(local.full_tags, var.anyscale_iam_tags) + securitygroup_tags = merge(local.full_tags, var.anyscale_securitygroup_tags) + efs_tags = merge(local.full_tags, var.anyscale_efs_tags) + s3_tags = merge(local.full_tags, var.anyscale_s3_tags) + + existing_subnet_count = length(var.existing_vpc_subnet_ids) anyscale_private_subnet_count = length(var.anyscale_vpc_private_subnets) anyscale_public_subnet_count = length(var.anyscale_vpc_public_subnets) efs_mount_targets_subnet_count = local.existing_subnet_count > 0 ? local.existing_subnet_count : local.anyscale_private_subnet_count > 0 ? local.anyscale_private_subnet_count : local.anyscale_public_subnet_count > 0 ? local.anyscale_public_subnet_count : 0 - aws_cloud_provider = var.cloud_provider == "aws" ? true : false - create_aws_vpc = var.existing_vpc_id == null && length(var.existing_subnet_ids) < 1 && local.aws_cloud_provider ? true : false + create_new_s3_bucket = var.existing_s3_bucket_arn == null ? true : false + + create_new_vpc = var.existing_vpc_id == null ? true : false + create_vpc_subnets = local.anyscale_private_subnet_count > 0 || local.anyscale_public_subnet_count > 0 ? true : false + create_vpc_gateway_endpoint = length(var.anyscale_gateway_vpc_endpoints) > 0 && (local.create_new_vpc || length(var.existing_vpc_route_table_ids) > 0) ? true : false + create_internet_gw = local.create_new_vpc ? true : false + create_nat_gw = local.create_new_vpc ? true : false + execute_vpc_sub_module = local.create_new_vpc || local.create_vpc_subnets || local.create_vpc_gateway_endpoint ? true : false + + s3_bucket_prefix = coalesce(var.anyscale_s3_bucket_prefix, var.general_prefix, "anyscale-") + iam_access_role_name_prefix = coalesce(var.anyscale_iam_access_role_name_prefix, var.general_prefix, "anyscale-iam-role-") + iam_cluster_node_role_name_prefix = coalesce(var.anyscale_iam_cluster_node_role_name_prefix, var.general_prefix, "anyscale-cluster-node-") + security_group_name_prefix = coalesce(var.security_group_name_prefix, var.general_prefix, "anyscale-security-group-") + steadystate_policy_prefix = coalesce(var.anyscale_access_steadystate_policy_prefix, var.general_prefix, "anyscale-steady_state-") } @@ -21,13 +40,15 @@ locals { # ------------------------------ module "aws_anyscale_s3" { source = "./modules/aws-anyscale-s3" - tags = local.full_tags + tags = local.s3_tags anyscale_cloud_id = var.anyscale_cloud_id anyscale_bucket_name = var.anyscale_s3_bucket_name - anyscale_bucket_prefix = var.anyscale_s3_bucket_prefix + anyscale_bucket_prefix = local.s3_bucket_prefix + server_side_encryption = var.anyscale_s3_server_side_encryption + force_destroy = var.anyscale_s3_force_destroy - module_enabled = local.aws_cloud_provider + module_enabled = local.create_new_s3_bucket } # ------------------------------ @@ -35,16 +56,19 @@ module "aws_anyscale_s3" { # ------------------------------ module "aws_anyscale_iam" { source = "./modules/aws-anyscale-iam" - tags = local.full_tags + tags = local.iam_tags anyscale_access_role_name = var.anyscale_iam_access_role_name - anyscale_access_role_name_prefix = var.anyscale_iam_access_role_name_prefix + anyscale_access_role_name_prefix = local.iam_access_role_name_prefix anyscale_cluster_node_role_name = var.anyscale_iam_cluster_node_role_name - anyscale_cluster_node_role_name_prefix = var.anyscale_iam_cluster_node_role_name_prefix - anyscale_cloud_id = var.anyscale_cloud_id - anyscale_s3_bucket_arn = module.aws_anyscale_s3.s3_bucket_arn + anyscale_cluster_node_role_name_prefix = local.iam_cluster_node_role_name_prefix + + anyscale_access_steadystate_policy_name = var.anyscale_access_steadystate_policy_name + anyscale_access_steadystate_policy_prefix = local.steadystate_policy_prefix + + anyscale_cloud_id = var.anyscale_cloud_id - module_enabled = local.aws_cloud_provider + anyscale_s3_bucket_arn = local.create_new_s3_bucket ? module.aws_anyscale_s3.s3_bucket_arn : var.existing_s3_bucket_arn } # ------------------------------ @@ -57,7 +81,9 @@ module "aws_anyscale_s3_policy" { anyscale_iam_access_role_arn = module.aws_anyscale_iam.iam_anyscale_access_role_arn anyscale_iam_cluster_node_role_arn = module.aws_anyscale_iam.iam_cluster_node_role_arn - module_enabled = local.aws_cloud_provider + custom_s3_policy = var.anyscale_custom_s3_policy + + module_enabled = local.create_new_s3_bucket } # ------------------------------ @@ -65,7 +91,7 @@ module "aws_anyscale_s3_policy" { # ------------------------------ module "aws_anyscale_vpc" { source = "./modules/aws-anyscale-vpc" - tags = local.full_tags + tags = local.vpc_tags anyscale_vpc_name = var.anyscale_vpc_name cidr_block = var.anyscale_vpc_cidr_block @@ -73,7 +99,16 @@ module "aws_anyscale_vpc" { public_subnets = var.anyscale_vpc_public_subnets private_subnets = var.anyscale_vpc_private_subnets - module_enabled = local.create_aws_vpc + create_igw = local.create_internet_gw + create_ngw = local.create_nat_gw + + gateway_vpc_endpoints = var.anyscale_gateway_vpc_endpoints + + existing_vpc_id = var.existing_vpc_id + existing_private_subnet_ids = var.existing_vpc_subnet_ids + existing_route_table_ids = var.existing_vpc_route_table_ids + + module_enabled = local.execute_vpc_sub_module } # ------------------------------ @@ -98,21 +133,19 @@ locals { module "aws_anyscale_securitygroup_self" { source = "./modules/aws-anyscale-securitygroups" - tags = local.full_tags + tags = local.securitygroup_tags vpc_id = coalesce(var.existing_vpc_id, module.aws_anyscale_vpc.vpc_id) security_group_name = var.security_group_name - security_group_name_prefix = var.security_group_name_prefix + security_group_name_prefix = local.security_group_name_prefix create_anyscale_public_ingress = var.security_group_create_anyscale_public_ingress ingress_from_cidr_map = local.ingress_from_cidr_range_override_defined ? var.security_group_override_ingress_from_cidr_map : local.ingress_cidr_block_defined ? local.ingress_from_cidr_map : [{}] ingress_with_existing_security_groups_map = local.ingress_existing_sg_defined ? var.security_group_ingress_with_existing_security_groups_map : [] - - module_enabled = local.aws_cloud_provider } module "aws_anyscale_efs" { source = "./modules/aws-anyscale-efs" - tags = local.full_tags + tags = local.efs_tags # File system anyscale_efs_name = var.efs_name @@ -123,11 +156,9 @@ module "aws_anyscale_efs" { # Mount targets / security group mount_targets_subnet_count = local.efs_mount_targets_subnet_count - mount_targets_subnets = coalescelist(var.existing_subnet_ids, module.aws_anyscale_vpc.private_subnet_ids, module.aws_anyscale_vpc.public_subnet_ids) + mount_targets_subnets = coalescelist(var.existing_vpc_subnet_ids, module.aws_anyscale_vpc.private_subnet_ids, module.aws_anyscale_vpc.public_subnet_ids) associated_security_group_ids = [module.aws_anyscale_securitygroup_self.security_group_id] # Backup policy enable_backup_policy = true - - module_enabled = local.aws_cloud_provider } diff --git a/modules/aws-anyscale-s3-policy/examples/README.md b/modules/aws-anyscale-s3-policy/examples/README.md index 68de6dc..2780937 100644 --- a/modules/aws-anyscale-s3-policy/examples/README.md +++ b/modules/aws-anyscale-s3-policy/examples/README.md @@ -1 +1,60 @@ +[![Build Status][badge-build]][build-status] +[![Terraform Version][badge-terraform]](https://github.com/hashicorp/terraform/releases) +[![AWS Provider Version][badge-tf-aws]](https://github.com/terraform-providers/terraform-provider-aws/releases) + # Examples for using the aws-anyscale-s3-policy module + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0 | +| [aws](#requirement\_aws) | ~> 4.0 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | 4.53.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [anyscale\_s3\_bucket\_policy](#module\_anyscale\_s3\_bucket\_policy) | ../ | n/a | +| [anyscale\_s3\_bucket\_policy\_complete](#module\_anyscale\_s3\_bucket\_policy\_complete) | ../ | n/a | +| [iam\_roles](#module\_iam\_roles) | ../../aws-anyscale-iam | n/a | +| [s3\_bucket\_custom\_policy](#module\_s3\_bucket\_custom\_policy) | ../../aws-anyscale-s3 | n/a | +| [s3\_bucket\_defaults](#module\_s3\_bucket\_defaults) | ../../aws-anyscale-s3 | n/a | + +## Resources + +| Name | Type | +|------|------| +| [aws_iam_policy_document.custom_s3_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [anyscale\_cloud\_id](#input\_anyscale\_cloud\_id) | (Optional) Anyscale Cloud ID | `string` | `null` | no | +| [anyscale\_deploy\_env](#input\_anyscale\_deploy\_env) | (Required) Anyscale deploy environment. Used in resource names and tags. | `string` | n/a | yes | +| [aws\_region](#input\_aws\_region) | The AWS region in which all resources will be created. | `string` | `"us-east-2"` | no | +| [tags](#input\_tags) | (Optional) A map of tags to all resources that accept tags. | `map(string)` |
{
"environment": "test",
"test": true
}
| no | + +## Outputs + +| Name | Description | +|------|-------------| +| [s3\_bucket\_custom\_policy\_id](#output\_s3\_bucket\_custom\_policy\_id) | The ID of the anyscasle resource. | +| [s3\_bucket\_id\_defaults](#output\_s3\_bucket\_id\_defaults) | The ID of the anyscale resource. | + + + +[Terraform]: https://www.terraform.io +[Issues]: https://github.com/anyscale/sa-sandbox-terraform/issues +[badge-build]: https://github.com/anyscale/sa-sandbox-terraform/workflows/CI/CD%20Pipeline/badge.svg +[badge-terraform]: https://img.shields.io/badge/terraform-1.x%20-623CE4.svg?logo=terraform +[badge-tf-aws]: https://img.shields.io/badge/AWS-4.+-F8991D.svg?logo=terraform +[build-status]: https://github.com/anyscale/sa-sandbox-terraform/actions diff --git a/modules/aws-anyscale-s3-policy/examples/main.tf b/modules/aws-anyscale-s3-policy/examples/main.tf new file mode 100644 index 0000000..25639e9 --- /dev/null +++ b/modules/aws-anyscale-s3-policy/examples/main.tf @@ -0,0 +1,80 @@ +# --------------------------------------------------------------------------------------------------------------------- +# CREATE Anyscale AWS S3 Policy Resources +# This template creates S3 Policy resources for Anyscale +# For testing, it also creates: +# S3 bucket +# IAM Roles +# --------------------------------------------------------------------------------------------------------------------- +locals { + full_tags = merge(tomap({ + anyscale-cloud-id = var.anyscale_cloud_id, + anyscale-deploy-environment = var.anyscale_deploy_env + }), + var.tags + ) +} + +# --------------------------------------------------------------------------------------------------------------------- +# Create an S3 buckets for module testing +# --------------------------------------------------------------------------------------------------------------------- +module "s3_bucket_defaults" { + source = "../../aws-anyscale-s3" + tags = local.full_tags +} + +module "s3_bucket_custom_policy" { + source = "../../aws-anyscale-s3" + tags = local.full_tags +} + +# --------------------------------------------------------------------------------------------------------------------- +# Create IAM Roles for module testing +# --------------------------------------------------------------------------------------------------------------------- +module "iam_roles" { + source = "../../aws-anyscale-iam" + tags = local.full_tags +} + +# --------------------------------------------------------------------------------------------------------------------- +# Create an S3 bucket policy with no optional parameters +# --------------------------------------------------------------------------------------------------------------------- +module "anyscale_s3_bucket_policy" { + source = "../" + + anyscale_bucket_name = module.s3_bucket_defaults.s3_bucket_id + anyscale_iam_access_role_arn = module.iam_roles.iam_anyscale_access_role_arn + anyscale_iam_cluster_node_role_arn = module.iam_roles.iam_cluster_node_role_arn +} + +# --------------------------------------------------------------------------------------------------------------------- +# Create an S3 bucket policy using all variables +# --------------------------------------------------------------------------------------------------------------------- +module "anyscale_s3_bucket_policy_complete" { + source = "../" + anyscale_bucket_name = module.s3_bucket_custom_policy.s3_bucket_id + anyscale_iam_access_role_arn = module.iam_roles.iam_anyscale_access_role_arn + anyscale_iam_cluster_node_role_arn = module.iam_roles.iam_cluster_node_role_arn + custom_s3_policy = data.aws_iam_policy_document.custom_s3_policy.json + +} + +data "aws_iam_policy_document" "custom_s3_policy" { + statement { + sid = "TestCustomS3Policy" + actions = ["s3:PutObject"] + effect = "Deny" + resources = [ + "arn:aws:s3:::${module.s3_bucket_custom_policy.s3_bucket_id}", + "arn:aws:s3:::${module.s3_bucket_custom_policy.s3_bucket_id}/*" + ] + condition { + test = "Bool" + variable = "aws:SecureTransport" + values = ["false"] + } + principals { + type = "*" + identifiers = ["*"] + } + } +} diff --git a/modules/aws-anyscale-s3-policy/examples/outputs.tf b/modules/aws-anyscale-s3-policy/examples/outputs.tf new file mode 100644 index 0000000..21645de --- /dev/null +++ b/modules/aws-anyscale-s3-policy/examples/outputs.tf @@ -0,0 +1,25 @@ +# -------------- +# Defaults Test +# -------------- +output "s3_bucket_id_defaults" { + description = "The ID of the anyscale resource." + value = module.s3_bucket_defaults.s3_bucket_id +} + +output "s3_bucket_custom_policy_id" { + description = "The ID of the anyscasle resource." + value = module.s3_bucket_custom_policy.s3_bucket_id +} + +# ------------------ +# Kitchen Sink Test +# ------------------ + + +# ----------------- +# No resource test +# ----------------- +# output "test_no_resources" { +# description = "The outputs of the no_resource resource - should all be empty" +# value = module.test_no_resources +# } diff --git a/modules/aws-anyscale-s3-policy/examples/variables.tf b/modules/aws-anyscale-s3-policy/examples/variables.tf new file mode 100644 index 0000000..67961ab --- /dev/null +++ b/modules/aws-anyscale-s3-policy/examples/variables.tf @@ -0,0 +1,57 @@ +# --------------------------------------------------------------------------------------------------------------------- +# ENVIRONMENT VARIABLES +# Define these secrets as environment variables +# --------------------------------------------------------------------------------------------------------------------- + +# AWS_ACCESS_KEY_ID +# AWS_SECRET_ACCESS_KEY + +# --------------------------------------------------------------------------------------------------------------------- +# REQUIRED VARIABLES +# These variables must be set when using this module. +# --------------------------------------------------------------------------------------------------------------------- + +variable "aws_region" { + description = "The AWS region in which all resources will be created." + type = string + default = "us-east-2" +} + +variable "anyscale_deploy_env" { + description = "(Required) Anyscale deploy environment. Used in resource names and tags." + type = string + validation { + condition = ( + var.anyscale_deploy_env == "production" || var.anyscale_deploy_env == "development" || var.anyscale_deploy_env == "test" + ) + error_message = "The anyscale_deploy_env only allows `production`, `test`, or `development`" + } +} + +# ------------------------------------------------------------------------------ +# OPTIONAL PARAMETERS +# These variables have defaults, but may be overridden. +# ------------------------------------------------------------------------------ +variable "anyscale_cloud_id" { + description = "(Optional) Anyscale Cloud ID" + type = string + default = null + validation { + condition = ( + var.anyscale_cloud_id == null ? true : ( + length(var.anyscale_cloud_id) > 4 && + substr(var.anyscale_cloud_id, 0, 4) == "cld_" + ) + ) + error_message = "The anyscale_cloud_id value must start with \"cld_\"." + } +} + +variable "tags" { + description = "(Optional) A map of tags to all resources that accept tags." + type = map(string) + default = { + "test" : true, + "environment" : "test" + } +} diff --git a/modules/aws-anyscale-s3-policy/examples/versions.tf b/modules/aws-anyscale-s3-policy/examples/versions.tf new file mode 100644 index 0000000..df08979 --- /dev/null +++ b/modules/aws-anyscale-s3-policy/examples/versions.tf @@ -0,0 +1,13 @@ +terraform { + required_version = ">= 1.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.0" + } + } +} + +provider "aws" { + region = var.aws_region +} diff --git a/modules/aws-anyscale-s3-policy/test/anyscale-test/main.tf b/modules/aws-anyscale-s3-policy/test/anyscale-test/main.tf index 1048247..c754c43 100644 --- a/modules/aws-anyscale-s3-policy/test/anyscale-test/main.tf +++ b/modules/aws-anyscale-s3-policy/test/anyscale-test/main.tf @@ -50,7 +50,7 @@ module "all_defaults" { # Create an S3 bucket policy with a custom JSON policy # --------------------------------------------------------------------------------------------------------------------- module "kitchen_sink" { - source = "../.." + source = "../../" anyscale_bucket_name = module.s3_bucket_custom_policy.s3_bucket_id anyscale_iam_access_role_arn = null anyscale_iam_cluster_node_role_arn = null diff --git a/modules/aws-anyscale-s3/variables.tf b/modules/aws-anyscale-s3/variables.tf index 5944d29..f68e3f5 100644 --- a/modules/aws-anyscale-s3/variables.tf +++ b/modules/aws-anyscale-s3/variables.tf @@ -69,7 +69,11 @@ variable "acl" { # } variable "force_destroy" { - description = "(Optional) Set to true to delete all objects from the bucket so that the bucket can be destroyed without error. These objects are not recoverable. Default is `false`." + description = <<-EOT + (Optional) Set to true to delete all objects from the bucket so that the bucket can be destroyed without error. + These objects are not recoverable. + Default is `false`. With this default, you need to empty the bucket if there are objects before `terraform destroy` can be completed. + EOT type = bool default = false } @@ -84,7 +88,12 @@ variable "force_destroy" { # max_age_seconds = 3000 # } variable "cors_rule" { - description = "(Optional) Object containing a rule of Cross-Origin Resource Sharing. Default allows console.anyscale.com" + description = <<-EOT + (Optional) + Object containing a rule of Cross-Origin Resource Sharing. + The default allows GET access for the purpose of viewing logs + from Anyscale Clusters from the Anyscale Web UI (console.anyscale.com). + EOT type = any default = { allowed_headers = ["*"] diff --git a/modules/aws-anyscale-vpc/README.md b/modules/aws-anyscale-vpc/README.md index 39cbc85..6d2e368 100644 --- a/modules/aws-anyscale-vpc/README.md +++ b/modules/aws-anyscale-vpc/README.md @@ -19,7 +19,7 @@ This builds a minimal VPC configuration. If you need more complex VPC configurat | Name | Version | |------|---------| -| [aws](#provider\_aws) | 4.49.0 | +| [aws](#provider\_aws) | 4.54.0 | | [time](#provider\_time) | 0.9.1 | ## Modules @@ -42,6 +42,7 @@ No modules. | [aws_route.public_route_igw](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route) | resource | | [aws_route_table.private](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table) | resource | | [aws_route_table.public](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table) | resource | +| [aws_route_table_association.existing_one_route_table](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table_association) | resource | | [aws_route_table_association.private](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table_association) | resource | | [aws_route_table_association.public](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table_association) | resource | | [aws_subnet.private](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet) | resource | @@ -69,15 +70,18 @@ No modules. | [create\_flow\_log\_cloudwatch\_iam\_role](#input\_create\_flow\_log\_cloudwatch\_iam\_role) | (Optional) Determines whether to create IAM role for VPC Flow Logs. Default is `false`. | `bool` | `false` | no | | [create\_flow\_log\_cloudwatch\_log\_group](#input\_create\_flow\_log\_cloudwatch\_log\_group) | (Optional) Determines whether to create CloudWatch log group for VPC Flow Logs. Default is `false`. | `bool` | `false` | no | | [create\_igw](#input\_create\_igw) | (Optional) Determines if an Internet Gateway is created for public subnets. Requires public\_subnets list to be provided. Default is `true`. | `bool` | `true` | no | -| [create\_nat\_gateway](#input\_create\_nat\_gateway) | (Optional) Determines if a NAT Gateway should be created for private networks. Depends on Public/Private Subnets being created. Default is `true`. | `bool` | `true` | no | +| [create\_ngw](#input\_create\_ngw) | (Optional) Determines if a NAT Gateway should be created for private networks. Depends on Public/Private Subnets being created. Default is `true`. | `bool` | `true` | no | | [enable\_vpc\_dns\_hostnames](#input\_enable\_vpc\_dns\_hostnames) | (Optional) Determines if DNS hostnames are enabled on the VPC. Default is `true` | `bool` | `true` | no | | [enable\_vpc\_dns\_support](#input\_enable\_vpc\_dns\_support) | (Optional) Determines if DNS support is enabled on the VPC. Default is `true`. | `bool` | `true` | no | | [enable\_vpc\_flow\_logs](#input\_enable\_vpc\_flow\_logs) | (Optional) Determines if VPC Flow Logs should be enabled. Default is `false`. | `bool` | `false` | no | +| [existing\_private\_subnet\_ids](#input\_existing\_private\_subnet\_ids) | (Optional)
A list of existing private subnets.
If this variable and var.existing\_vpc\_id are both provided, the aws-anyscale-vpc sub-module will not create a VPC or Subnets.
It will only create VPC Endpoints if the gateway\_vpc\_endpoints variable is defined.

Default is an empty list. | `list(string)` | `[]` | no | +| [existing\_route\_table\_ids](#input\_existing\_route\_table\_ids) | (Optional)
A list of existing Route Tables.
If you are creating new private subnets in an existing VPC, this will provide the mapping from
subnet to route table. If only 1 is provided, all new subnets will be associated with that one.
If more than one, please make sure that you provide the same number of route tables as subnets.

Default is an empty list. | `list(string)` | `[]` | no | +| [existing\_vpc\_id](#input\_existing\_vpc\_id) | (Optional)
An existing VPC ID. If provided, this will skip creating an Anyscale VPC.
If no existing Subnet IDs are provided (`existing_subnet_ids`), but `existing_vpc_id` is provided, then new subnets will be created in this VPC.
Default is `null`. | `string` | `null` | no | | [flow\_log\_cloudwatch\_log\_group\_kms\_key\_id](#input\_flow\_log\_cloudwatch\_log\_group\_kms\_key\_id) | (Optional) The ARN of the KMS Key to use when encrypting log data for VPC flow logs. Default is `null`. | `string` | `null` | no | | [flow\_log\_cloudwatch\_log\_group\_name\_prefix](#input\_flow\_log\_cloudwatch\_log\_group\_name\_prefix) | (Optional) Specifies the name prefix of CloudWatch Log Group for VPC flow logs. Default is `/aws/vpc-flow-log/` | `string` | `"/aws/vpc-flow-log/"` | no | | [flow\_log\_cloudwatch\_log\_group\_name\_suffix](#input\_flow\_log\_cloudwatch\_log\_group\_name\_suffix) | (Optional) Specifies the name suffix of CloudWatch Log Group for VPC flow logs. If none is provided, will append the VPC Name. Default is `null` | `string` | `null` | no | | [flow\_log\_cloudwatch\_log\_group\_retention\_in\_days](#input\_flow\_log\_cloudwatch\_log\_group\_retention\_in\_days) | (Optional) Specifies the number of days you want to retain log events in the specified log group for VPC flow logs. Default is `null` which is unlimited. | `number` | `null` | no | -| [gateway\_vpc\_endpoints](#input\_gateway\_vpc\_endpoints) | A map of Gateway VPC Endpoints to provision into the VPC. This is a map of objects with the following attributes:
- `name`: Short service name (either "s3" or "dynamodb")
- `policy` = A policy (as JSON string) to attach to the endpoint that controls access to the service. May be `null` for full access.
Default is S3 with an empty (full access) policy. |
map(object({
name = string
policy = string
}))
|
{
"s3": {
"name": "s3",
"policy": null
}
}
| no | +| [gateway\_vpc\_endpoints](#input\_gateway\_vpc\_endpoints) | A map of Gateway VPC Endpoints to provision into the VPC. This is a map of objects with the following attributes:
- `name`: Short service name (either "s3" or "dynamodb")
- `policy` = A policy (as JSON string) to attach to the endpoint that controls access to the service. May be `null` for full access.
Set to an empty map `{}` to skip creating VPC Endpoints.
Default is S3 with an empty (full access) policy. |
map(object({
name = string
policy = string
}))
|
{
"s3": {
"name": "s3",
"policy": null
}
}
| no | | [ipv4\_ipam\_pool\_id](#input\_ipv4\_ipam\_pool\_id) | (Optional) The ID of an IPv4 IPAM pool you want to use for allocating this VPC's CIDR. Default is `null`. | `string` | `null` | no | | [ipv4\_netmask\_length](#input\_ipv4\_netmask\_length) | (Optional) The netmask length of the IPv4 CIDR you want to allocate to this VPC. Requires specifying a ipv4\_ipam\_pool\_id. Default is `null`. | `number` | `null` | no | | [map\_public\_ip\_on\_launch](#input\_map\_public\_ip\_on\_launch) | (Optional) Determines if public subnets should auto-assign public IPs on launch. Defualt is `true`. | `bool` | `true` | no | @@ -87,10 +91,10 @@ No modules. | [nat\_gateway\_destination\_cidr\_block](#input\_nat\_gateway\_destination\_cidr\_block) | (Optional) Defines a custom destination route for NAT Gateway(s). Default is `0.0.0.0/0`. | `string` | `"0.0.0.0/0"` | no | | [private\_subnet\_names](#input\_private\_subnet\_names) | (Optional) Explicit values to use in the Name tag on private subnets. If empty, Name tags are generated. Default is an empty list. | `list(string)` | `[]` | no | | [private\_subnet\_suffix](#input\_private\_subnet\_suffix) | (Optional) Suffix to append to private subnets name. Default is `private`. | `string` | `"private"` | no | -| [private\_subnets](#input\_private\_subnets) | (Optional) A list of private subnets inside the VPC. Default is an empty list. | `list(string)` | `[]` | no | +| [private\_subnets](#input\_private\_subnets) | (Optional)
A list of private subnets inside a VPC.
If you are creating subnets in an existing VPC (using existing\_vpc\_id),
please make sure that the number of subnets in the list is less than or
equal to the number of AZ's in the region.

Default is an empty list. | `list(string)` | `[]` | no | | [public\_subnet\_names](#input\_public\_subnet\_names) | (Optional) Explicit values to use in the Name tag on public subnets. If empty, Name tags are generated. Default is an empty list. | `list(string)` | `[]` | no | | [public\_subnet\_suffix](#input\_public\_subnet\_suffix) | (Optional) Suffix to append to public subnets name. Default is `public` | `string` | `"public"` | no | -| [public\_subnets](#input\_public\_subnets) | (Optional) A list of public subnets inside the VPC. Default is an empty list. | `list(string)` | `[]` | no | +| [public\_subnets](#input\_public\_subnets) | (Optional)
A list of public subnets inside the VPC.
If you are creating subnets in an existing VPC (using existing\_vpc\_id),
please make sure that the number of subnets in the list is less than or
equal to the number of AZ's in the region.

Default is an empty list. | `list(string)` | `[]` | no | | [secondary\_cidr\_blocks](#input\_secondary\_cidr\_blocks) | (Optional) List of secondary CIDR blocks to associate with the VPC to extend the IP Address pool. Default is an empty list. | `list(string)` | `[]` | no | | [tags](#input\_tags) | (Optional) A map of tags to add to all resources. Default is none. | `map(string)` | `{}` | no | | [use\_ipam\_pool](#input\_use\_ipam\_pool) | (Optional) Determines whether IPAM pool is used for CIDR allocation. Default is `false` | `bool` | `false` | no | diff --git a/modules/aws-anyscale-vpc/main.tf b/modules/aws-anyscale-vpc/main.tf index f2662f0..36785d9 100644 --- a/modules/aws-anyscale-vpc/main.tf +++ b/modules/aws-anyscale-vpc/main.tf @@ -3,7 +3,9 @@ locals { vpc_name = coalesce(var.anyscale_vpc_name, local.vpc_name_cloud_id, "vpc-anyscale") # Use `local.vpc_id` to let Terraform know that subnets should be deleted before secondary CIDR blocks can be released. - vpc_id = try(aws_vpc_ipv4_cidr_block_association.anyscale_vpc[0].vpc_id, aws_vpc.anyscale_vpc[0].id, "") + new_vpc_id = try(aws_vpc_ipv4_cidr_block_association.anyscale_vpc[0].vpc_id, aws_vpc.anyscale_vpc[0].id, "") + vpc_id = var.existing_vpc_id == null ? local.new_vpc_id : var.existing_vpc_id + create_vpc = var.existing_vpc_id == null && var.module_enabled ? true : false # -------------------------------------------------------------------- # Determine the set of availability zones in which to deploy subnets @@ -45,7 +47,7 @@ locals { subnet_az_count = var.module_enabled ? length(local.subnet_availability_zones) : 0 - all_route_table_ids = concat(local.private_route_table_ids, local.public_route_table_ids, []) + all_route_table_ids = concat(local.private_route_table_ids, local.public_route_table_ids, var.existing_route_table_ids, []) module_tags = tomap({ tf_sub_module = "aws-anyscale-vpc" @@ -60,7 +62,7 @@ locals { resource "aws_vpc" "anyscale_vpc" { #checkov:skip=CKV2_AWS_12:Not managing the default security group in this module #checkov:skip=CKV2_AWS_11:Flow logs can be enabled via a boolean variable. Ignoring this alert. - count = var.module_enabled ? 1 : 0 + count = local.create_vpc ? 1 : 0 cidr_block = var.use_ipam_pool ? null : var.cidr_block ipv4_ipam_pool_id = var.ipv4_ipam_pool_id diff --git a/modules/aws-anyscale-vpc/nat-gateway.tf b/modules/aws-anyscale-vpc/nat-gateway.tf index ef4b7eb..3000172 100644 --- a/modules/aws-anyscale-vpc/nat-gateway.tf +++ b/modules/aws-anyscale-vpc/nat-gateway.tf @@ -2,7 +2,7 @@ # NAT Gateway Creation # --------------------- locals { - nat_gateway_count = var.create_nat_gateway && local.private_subnet_count > 0 ? min(local.subnet_az_count, var.max_nat_gateway_count) : 0 + nat_gateway_count = var.create_ngw && local.private_subnet_count > 0 ? min(local.subnet_az_count, var.max_nat_gateway_count) : 0 } # -------------------- diff --git a/modules/aws-anyscale-vpc/outputs.tf b/modules/aws-anyscale-vpc/outputs.tf index 305b518..e824824 100644 --- a/modules/aws-anyscale-vpc/outputs.tf +++ b/modules/aws-anyscale-vpc/outputs.tf @@ -37,7 +37,7 @@ output "public_route_table_ids" { # Private Subnets and related resources output "private_subnet_ids" { description = "IDs of the private subnets" - value = try(aws_subnet.private[*].id, []) + value = try(aws_subnet.private[*].id, var.existing_private_subnet_ids, []) } output "private_subnet_cidrs" { description = "IPv4 CIDR blocks for the private subnets" diff --git a/modules/aws-anyscale-vpc/subnets-private.tf b/modules/aws-anyscale-vpc/subnets-private.tf index 260b637..ed64c52 100644 --- a/modules/aws-anyscale-vpc/subnets-private.tf +++ b/modules/aws-anyscale-vpc/subnets-private.tf @@ -3,15 +3,17 @@ # ---------------- locals { - private_subnet_count = length(var.private_subnets) > 0 ? length(var.private_subnets) : 0 - private_route_table_ids = local.private_subnet_count > 0 ? aws_route_table.private[*].id : [] + private_subnet_count = length(var.private_subnets) > 0 && length(var.existing_private_subnet_ids) == 0 ? length(var.private_subnets) : 0 + existing_prv_rt_count = length(var.existing_route_table_ids) > 0 ? length(var.existing_route_table_ids) : 0 + + private_route_table_ids = local.existing_prv_rt_count > 0 ? var.existing_route_table_ids : local.private_subnet_count > 0 ? aws_route_table.private[*].id : [] } # ---------------- # Subnets # ---------------- resource "aws_subnet" "private" { - count = var.module_enabled && length(var.private_subnets) > 0 ? length(var.private_subnets) : 0 + count = var.module_enabled && local.private_subnet_count > 0 ? local.private_subnet_count : 0 vpc_id = local.vpc_id cidr_block = var.private_subnets[count.index] @@ -34,8 +36,9 @@ resource "aws_subnet" "private" { # --------------------- # There are as many routing tables as the number of NAT gateways +# Only create route tables if the existing route tables var is empty resource "aws_route_table" "private" { - count = var.module_enabled && local.private_subnet_count > 0 ? local.private_subnet_count : 0 + count = var.module_enabled && local.private_subnet_count > 0 && local.existing_prv_rt_count == 0 ? local.private_subnet_count : 0 vpc_id = local.vpc_id @@ -55,8 +58,15 @@ resource "aws_route_table" "private" { # Route table associations # ------------------------- resource "aws_route_table_association" "private" { - count = var.module_enabled && local.private_subnet_count > 0 ? local.private_subnet_count : 0 + count = var.module_enabled && local.private_subnet_count > 0 ? local.private_subnet_count : var.module_enabled && local.private_subnet_count > 0 && local.existing_prv_rt_count > 1 ? local.existing_prv_rt_count : 0 subnet_id = element(aws_subnet.private[*].id, count.index) route_table_id = element(local.private_route_table_ids, count.index) } + +resource "aws_route_table_association" "existing_one_route_table" { + count = var.module_enabled && local.private_subnet_count > 0 && local.existing_prv_rt_count == 1 ? local.private_subnet_count : 0 + + subnet_id = element(aws_subnet.private[*].id, count.index) + route_table_id = element(local.private_route_table_ids, 0) +} diff --git a/modules/aws-anyscale-vpc/test/anyscale-test/main.tf b/modules/aws-anyscale-vpc/test/anyscale-test/main.tf index 172710e..94d4899 100644 --- a/modules/aws-anyscale-vpc/test/anyscale-test/main.tf +++ b/modules/aws-anyscale-vpc/test/anyscale-test/main.tf @@ -31,7 +31,7 @@ module "all_defaults" { # Should be executed in us-east-2 # --------------------------------------------------------------------------------------------------------------------- module "minimum_anyscale_vpc_requirements" { - source = "../.." + source = "../../" anyscale_vpc_name = "tftest-minimum_anyscale_vpc" cidr_block = "172.21.0.0/16" @@ -47,7 +47,7 @@ module "minimum_anyscale_vpc_requirements" { # Should be executed in us-east-2 # --------------------------------------------------------------------------------------------------------------------- module "public_private_vpc" { - source = "../.." + source = "../../" anyscale_vpc_name = "tftest-publicprivate_anyscale_vpc" cidr_block = "172.22.0.0/16" @@ -58,6 +58,46 @@ module "public_private_vpc" { tags = local.full_tags } +# --------------------------------------------------------------------------------------------------------------------- +# Create new Subnets within an existing VPC +# CIDR blocks do not already exist in this VPC +# Using existing private route table - tested with both one and two route tables +# Do not create a new VPC Endpoint and related resources +# --------------------------------------------------------------------------------------------------------------------- +module "existing_vpc_new_subnets" { + source = "../../" + + existing_vpc_id = "vpc-086408b268f481027" + + private_subnets = ["10.0.20.0/24", "10.0.21.0/24"] + existing_route_table_ids = ["rtb-02d75c4d4bf4c6dd1"] + + create_igw = false # We will assume this is already there + create_ngw = false # We will assume this is already there + + gateway_vpc_endpoints = {} + + module_enabled = true + tags = local.full_tags +} + +# --------------------------------------------------------------------------------------------------------------------- +# Create just the Gateway Endpoints within an existing VPC and existing Subnets +# Create a new VPC Endpoint and related resources +# --------------------------------------------------------------------------------------------------------------------- +module "existing_vpc_create_endpoints" { + source = "../../" + + existing_vpc_id = "vpc-01e570eea1c7258ae" + existing_route_table_ids = ["rtb-0745f6378288c2836"] + + create_igw = false # We will assume this is already there + create_ngw = false # We will assume this is already there + + module_enabled = true + tags = local.full_tags +} + # --------------------------------------------------------------------------------------------------------------------- # Use all params and build a VPC # --------------------------------------------------------------------------------------------------------------------- @@ -78,8 +118,8 @@ module "kitchen_sink" { availability_zones = ["us-east-2a", "us-east-2b", "us-east-2c"] - create_nat_gateway = true - create_igw = true + create_ngw = true + create_igw = true enable_vpc_flow_logs = true create_flow_log_cloudwatch_log_group = true diff --git a/modules/aws-anyscale-vpc/test/anyscale-test/outputs.tf b/modules/aws-anyscale-vpc/test/anyscale-test/outputs.tf index 9739151..0d4f06a 100644 --- a/modules/aws-anyscale-vpc/test/anyscale-test/outputs.tf +++ b/modules/aws-anyscale-vpc/test/anyscale-test/outputs.tf @@ -72,6 +72,18 @@ output "public_private_nat_gateway_ids" { value = module.public_private_vpc.nat_gateway_ids } +# -------------------------------- +# New Subnets - Existing VPC Test +# -------------------------------- +output "new_subnets_existing_vpc_vpc_id" { + description = "The ID of the anyscale resource." + value = module.existing_vpc_new_subnets.vpc_id +} +output "new_subnets_existing_vpc_subnet_cidrs" { + description = "The private subnet cidrs of the anyscale new subnets existing vpc test" + value = module.kitchen_sink.private_subnet_cidrs +} + # ------------------ # Kitchen Sink Test # ------------------ diff --git a/modules/aws-anyscale-vpc/variables.tf b/modules/aws-anyscale-vpc/variables.tf index 99ef713..602263b 100644 --- a/modules/aws-anyscale-vpc/variables.tf +++ b/modules/aws-anyscale-vpc/variables.tf @@ -44,6 +44,17 @@ variable "tags" { #-------------- # VPC Resource #-------------- +variable "existing_vpc_id" { + description = <<-EOT + (Optional) + An existing VPC ID. If provided, this will skip creating an Anyscale VPC. + If no existing Subnet IDs are provided (`existing_subnet_ids`), but `existing_vpc_id` is provided, then new subnets will be created in this VPC. + Default is `null`. + EOT + type = string + default = null +} + variable "cidr_block" { description = "(Optional) The IPv4 CIDR block for the VPC. CIDR can be explicitly set or it can be derived from IPAM using `ipv4_netmask_length` & `ipv4_ipam_pool_id`. Default is `10.0.0.0/16`" type = string @@ -102,7 +113,15 @@ variable "ipv4_netmask_length" { # ex: # public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"] variable "public_subnets" { - description = "(Optional) A list of public subnets inside the VPC. Default is an empty list." + description = <<-EOT + (Optional) + A list of public subnets inside the VPC. + If you are creating subnets in an existing VPC (using existing_vpc_id), + please make sure that the number of subnets in the list is less than or + equal to the number of AZ's in the region. + + Default is an empty list. + EOT type = list(string) default = [] } @@ -126,7 +145,15 @@ variable "map_public_ip_on_launch" { # ex: # private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"] variable "private_subnets" { - description = "(Optional) A list of private subnets inside the VPC. Default is an empty list." + description = <<-EOT + (Optional) + A list of private subnets inside a VPC. + If you are creating subnets in an existing VPC (using existing_vpc_id), + please make sure that the number of subnets in the list is less than or + equal to the number of AZ's in the region. + + Default is an empty list. + EOT type = list(string) default = [] } @@ -140,6 +167,32 @@ variable "private_subnet_names" { type = list(string) default = [] } +variable "existing_route_table_ids" { + description = <<-EOT + (Optional) + A list of existing Route Tables. + If you are creating new private subnets in an existing VPC, this will provide the mapping from + subnet to route table. If only 1 is provided, all new subnets will be associated with that one. + If more than one, please make sure that you provide the same number of route tables as subnets. + + Default is an empty list. + EOT + type = list(string) + default = [] +} + +variable "existing_private_subnet_ids" { + description = <<-EOT + (Optional) + A list of existing private subnets. + If this variable and var.existing_vpc_id are both provided, the aws-anyscale-vpc sub-module will not create a VPC or Subnets. + It will only create VPC Endpoints if the gateway_vpc_endpoints variable is defined. + + Default is an empty list. + EOT + type = list(string) + default = [] +} # Availability Zones variable "availability_zones" { @@ -161,7 +214,7 @@ variable "max_az_count" { # ------------------- # NAT Gateways (NGW) # ------------------- -variable "create_nat_gateway" { +variable "create_ngw" { description = "(Optional) Determines if a NAT Gateway should be created for private networks. Depends on Public/Private Subnets being created. Default is `true`." type = bool default = true @@ -269,6 +322,7 @@ variable "gateway_vpc_endpoints" { A map of Gateway VPC Endpoints to provision into the VPC. This is a map of objects with the following attributes: - `name`: Short service name (either "s3" or "dynamodb") - `policy` = A policy (as JSON string) to attach to the endpoint that controls access to the service. May be `null` for full access. + Set to an empty map `{}` to skip creating VPC Endpoints. Default is S3 with an empty (full access) policy. EOD default = { diff --git a/modules/aws-anyscale-vpc/vpc-endpoints.tf b/modules/aws-anyscale-vpc/vpc-endpoints.tf index eed7ad5..eb0f5c7 100644 --- a/modules/aws-anyscale-vpc/vpc-endpoints.tf +++ b/modules/aws-anyscale-vpc/vpc-endpoints.tf @@ -1,5 +1,5 @@ locals { - gateway_endpoints_enabled = var.module_enabled && length(var.gateway_vpc_endpoints) > 0 && (local.public_subnet_count > 0 || local.private_subnet_count > 0) ? true : false + gateway_endpoints_enabled = var.module_enabled && length(var.gateway_vpc_endpoints) > 0 && (local.public_subnet_count > 0 || local.private_subnet_count > 0 || length(var.existing_route_table_ids) > 0) ? true : false route_table_associations_list = flatten([for k, v in var.gateway_vpc_endpoints : [ for i, route_id in local.all_route_table_ids : { key = "${k}[${i}]" diff --git a/test/README.md b/test/README.md index 132cfc0..af0152a 100644 --- a/test/README.md +++ b/test/README.md @@ -6,6 +6,47 @@ Requirements: More info can be found [here](https://terratest.gruntwork.io/docs/getting-started/quick-start/) +## Tests Breakdown + +### anyscale-v1-test + +This will create two sets of resources for an Anyscale v1.0 Stack. + +The first includes as many defaults as possible including: + - IAM Roles + - S3 Bucket + - VPC with publicly routed subnets (no internal) + - VPC Security Group allowing public from Anyscale and 0.0.0.0/0 + - EFS + +The second utilizes an existing VPC and creates: + - IAM Roles + - S3 Bucket + - VPC Security Group allowing public from Anyscale and 0.0.0.0/0 + - EFS + +### anyscale-v2-test - NOT DONE + +This will create three sets of resources for Anyscale v2.0 Stacks. + +The first includes as many defaults as possible and duplicates the v1 Stack resources above minus the Anyscale Public Ingress: + - IAM Roles + - S3 Bucket + - VPC with publicly routed subnets (no internal) + - VPC Security Group allowing access from a customer defined public IP + - EFS + +The second utilizes an existing VPC and is meant to be testing the v2 Customer Defined Networking solution with no public IPs and locked down ingress in the security group configuration. It creates: + - IAM Roles + - S3 Bucket + - VPC Security Group that is locked down with no public access and no access from Anyscale IPs + - EFS + +The third creates resources for an Anyscale v2.0 Stack with an existing VPC and an existing S3 bucket. This is still utilizing an existing VPC and is meant to be testing v2 Customer Defined Networking, an existing S3, etc. It creates: + - IAM Roles + - VPC Security Group that is locked down with no public access and no access from Anyscale IPs + - EFS + #### Manual execution Manully running the go tests can save time during initial development. Requires active aws credentials. ``` diff --git a/test/anyscale-v1-test/main.tf b/test/anyscale-v1-test/main.tf new file mode 100644 index 0000000..6cb0999 --- /dev/null +++ b/test/anyscale-v1-test/main.tf @@ -0,0 +1,72 @@ +# --------------------------------------------------------------------------------------------------------------------- +# Create core Anyscale v1 Stack resources with minimal parameters +# Should be executed in us-east-2 +# Creates a v1 stack including +# - IAM Roles +# - S3 Bucket +# - VPC with publicly routed subnets (no internal) +# - VPC Security Groups allowing public from Anyscale +# - EFS +# --------------------------------------------------------------------------------------------------------------------- + +locals { + full_tags = merge(tomap({ + anyscale-cloud-id = var.anyscale_cloud_id, + anyscale-deploy-environment = var.anyscale_deploy_env + }), + var.tags + ) + cidr_block = "172.24.0.0/16" + public_subnets = ["172.24.101.0/24", "172.24.102.0/24", "172.24.103.0/24"] +} + +module "aws_anyscale_v1" { + source = "../../" + tags = local.full_tags + + anyscale_deploy_env = var.anyscale_deploy_env + anyscale_cloud_id = var.anyscale_cloud_id + + # VPC Related + anyscale_vpc_cidr_block = local.cidr_block + anyscale_vpc_public_subnets = local.public_subnets + + # Security Group Related + security_group_create_anyscale_public_ingress = true + security_group_ingress_allow_access_from_cidr_range = var.customer_ingress_cidr_ranges +} + +# --------------------------------------------------------------------------------------------------------------------- +# Create core Anyscale v1 Stack with existing VPC +# Creates a v1 stack including +# - IAM Roles +# - S3 Bucket +# - VPC Security Groups allowing public from Anyscale +# - EFS +# --------------------------------------------------------------------------------------------------------------------- +locals { + existing_vpc_id = "vpc-086408b268f481027" + existing_subnet_ids = ["subnet-06154a164989c0f8d", "subnet-05f678cbbba3d9a1d", "subnet-0f7b63788905e3eb2"] +} + +module "aws_anyscale_v1_existing_vpc" { + source = "../../" + tags = local.full_tags + + anyscale_deploy_env = var.anyscale_deploy_env + anyscale_cloud_id = var.anyscale_cloud_id + + # VPC Related + existing_vpc_id = local.existing_vpc_id + existing_vpc_subnet_ids = local.existing_subnet_ids + + # Security Group Related + security_group_create_anyscale_public_ingress = true + security_group_ingress_allow_access_from_cidr_range = var.customer_ingress_cidr_ranges + + # S3 Bucket Related + anyscale_s3_tags = { + "resource_tag_test" : true, + "s3_tagging" : var.existing_vpc_s3_tag_value + } +} diff --git a/test/anyscale-v1-test/outputs.tf b/test/anyscale-v1-test/outputs.tf new file mode 100644 index 0000000..60836ff --- /dev/null +++ b/test/anyscale-v1-test/outputs.tf @@ -0,0 +1,79 @@ +# --------------------------------------------------------------------------------------------------------------------- +# Anyscale v1 Stack resources with minimal parameters +# --------------------------------------------------------------------------------------------------------------------- +output "anyscale_v1_vpc_id" { + description = "Anyscale VPC ID. If there was not one created, return the one that was used during other resource creation." + value = try(module.aws_anyscale_v1.anyscale_vpc_id, "") +} + +output "anyscale_v1_vpc_public_subnet_ids" { + description = "Anyscale VPC Public Subnet IDs. If there were none created, return an empty string." + value = try(module.aws_anyscale_v1.anyscale_vpc_public_subnet_ids, []) +} +output "anyscale_v1_vpc_private_subnet_ids" { + description = "Anyscale VPC Private Subnet IDs. If there were none created, return an empty string." + value = try(module.aws_anyscale_v1.anyscale_vpc_private_subnet_ids, []) +} + +output "anyscale_v1_s3_bucket_id" { + description = "Anyscale S3 Bucket ID. If a bucket was not created, return an empty string." + value = try(module.aws_anyscale_v1.anyscale_s3_bucket_id, "") +} + +output "anyscale_v1_security_group_id" { + description = "Anyscale Security Group ID. If a security group was not created, return an empty string." + value = try(module.aws_anyscale_v1.anyscale_security_group_id, "") +} + +output "anyscale_v1_iam_role_arn" { + description = "Anyscale IAM access role arn." + value = try(module.aws_anyscale_v1.anyscale_iam_role_arn, "") +} + +output "anyscale_v1_iam_instance_role_arn" { + description = "Anyscale IAM instance role arn." + value = try(module.aws_anyscale_v1.anyscale_iam_role_cluster_node_arn, "") +} + +output "anyscale_v1_efs_id" { + description = "Anyscale Elastic File System ID." + value = try(module.aws_anyscale_v1.anyscale_efs_id, "") +} + +# output "anyscale_v1_efs_mount_target_ids" { +# description = "Anyscale Elastic File System mount target IDs. If EFS mount targets were not created, return an empty list." +# value = try(module.aws_anyscale_v1.anyscale_efs_mount_target_ids, []) +# } + +# --------------------------------------------------------------------------------------------------------------------- +# Anyscale v1 Stack with existing VPC +# --------------------------------------------------------------------------------------------------------------------- +output "anyscale_v1_existing_vpc_s3_bucket_id" { + description = "Anyscale S3 Bucket ID. If a bucket was not created, return an empty string." + value = try(module.aws_anyscale_v1_existing_vpc.anyscale_s3_bucket_id, "") +} + +output "anyscale_v1_existing_vpc_security_group_id" { + description = "Anyscale Security Group ID. If a security group was not created, return an empty string." + value = try(module.aws_anyscale_v1_existing_vpc.anyscale_security_group_id, "") +} + +output "anyscale_v1_existing_vpc_iam_role_arn" { + description = "Anyscale IAM access role arn." + value = try(module.aws_anyscale_v1_existing_vpc.anyscale_iam_role_arn, "") +} + +output "anyscale_v1_existing_vpc_iam_instance_role_arn" { + description = "Anyscale IAM instance role arn." + value = try(module.aws_anyscale_v1_existing_vpc.anyscale_iam_role_cluster_node_arn, "") +} + +output "anyscale_v1_existing_vpc_efs_id" { + description = "Anyscale Elastic File System ID." + value = try(module.aws_anyscale_v1_existing_vpc.anyscale_efs_id, "") +} + +# output "anyscale_v1_existing_vpc_efs_mount_target_ids" { +# description = "Anyscale Elastic File System mount target IDs. If EFS mount targets were not created, return an empty list." +# value = try(module.aws_anyscale_v1_existing_vpc.anyscale_efs_mount_target_ids, []) +# } diff --git a/test/anyscale-v1-test/variables.tf b/test/anyscale-v1-test/variables.tf new file mode 100644 index 0000000..2a781b6 --- /dev/null +++ b/test/anyscale-v1-test/variables.tf @@ -0,0 +1,73 @@ +# --------------------------------------------------------------------------------------------------------------------- +# ENVIRONMENT VARIABLES +# Define these secrets as environment variables +# --------------------------------------------------------------------------------------------------------------------- + +# AWS_ACCESS_KEY_ID +# AWS_SECRET_ACCESS_KEY + +# --------------------------------------------------------------------------------------------------------------------- +# REQUIRED VARIABLES +# These variables must be set when using this module. +# --------------------------------------------------------------------------------------------------------------------- + +variable "aws_region" { + description = "The AWS region in which all resources will be created." + type = string +} + +variable "anyscale_deploy_env" { + description = "(Required) Anyscale deploy environment. Used in resource names and tags." + type = string + validation { + condition = ( + var.anyscale_deploy_env == "production" || var.anyscale_deploy_env == "development" || var.anyscale_deploy_env == "test" + ) + error_message = "The anyscale_deploy_env only allows `production`, `test`, or `development`" + } +} + +# ------------------------------------------------------------------------------ +# OPTIONAL PARAMETERS +# These variables have defaults, but may be overridden. +# ------------------------------------------------------------------------------ +variable "anyscale_cloud_id" { + description = "(Optional) Anyscale Cloud ID. Default is `null`." + type = string + default = null + validation { + condition = ( + var.anyscale_cloud_id == null ? true : ( + length(var.anyscale_cloud_id) > 4 && + substr(var.anyscale_cloud_id, 0, 4) == "cld_" + ) + ) + error_message = "The anyscale_cloud_id value must start with \"cld_\"." + } +} + +variable "tags" { + description = "(Optional) A map of tags to all resources that accept tags." + type = map(string) + default = { + "test" : true, + "environment" : "test" + } +} + +variable "customer_ingress_cidr_ranges" { + description = <<-EOT + The IPv4 CIDR block that is allowed to access the clusters. + This provides the ability to lock down the v1 stack to just the public IPs of a corporate network. + This is added to the security group and allows port 443 (https) and 22 (ssh) access. + ex: `52.1.1.23/32,10.1.0.0/16' + Default is `0.0.0.0/0` + EOT + type = string + default = "0.0.0.0/0" +} + +variable "existing_vpc_s3_tag_value" { + description = "This is used to set the S3 tag value for testing purposes" + type = string +} diff --git a/test/anyscale-v1-test/versions.tf b/test/anyscale-v1-test/versions.tf new file mode 100644 index 0000000..df08979 --- /dev/null +++ b/test/anyscale-v1-test/versions.tf @@ -0,0 +1,13 @@ +terraform { + required_version = ">= 1.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.0" + } + } +} + +provider "aws" { + region = var.aws_region +} diff --git a/test/anyscale-v2-test/main.tf b/test/anyscale-v2-test/main.tf new file mode 100644 index 0000000..36febf3 --- /dev/null +++ b/test/anyscale-v2-test/main.tf @@ -0,0 +1,142 @@ +# --------------------------------------------------------------------------------------------------------------------- +# Create core Anyscale v2 Stack resources with minimal parameters +# Should be executed in us-east-2 +# Creates a v2 stack including +# - IAM Roles +# - S3 Bucket +# - VPC with publicly routed subnets (no private subnets) +# - VPC Security Groups +# - EFS +# --------------------------------------------------------------------------------------------------------------------- + +locals { + full_tags = merge(tomap({ + anyscale-cloud-id = var.anyscale_cloud_id, + anyscale-deploy-environment = var.anyscale_deploy_env + }), + var.tags + ) + minimal_param_cidr_block = "172.24.0.0/16" + minimal_param_public_subnets = ["172.24.101.0/24", "172.24.102.0/24", "172.24.103.0/24"] +} + +module "aws_anyscale_v2" { + source = "../.." + tags = local.full_tags + + anyscale_deploy_env = var.anyscale_deploy_env + anyscale_cloud_id = var.anyscale_cloud_id + + # VPC Related + anyscale_vpc_cidr_block = local.minimal_param_cidr_block + anyscale_vpc_public_subnets = local.minimal_param_public_subnets + + # Security Group Related + security_group_ingress_allow_access_from_cidr_range = var.customer_ingress_cidr_ranges +} + +# --------------------------------------------------------------------------------------------------------------------- +# Create core Anyscale v2 Stack with existing VPC (Public Subnets) +# Creates a v2 stack including +# - IAM Roles +# - S3 Bucket +# - VPC Security Groups +# - EFS +# --------------------------------------------------------------------------------------------------------------------- +locals { + existing_vpc_id = "vpc-086408b268f481027" + existing_public_subnet_ids = ["subnet-06154a164989c0f8d", "subnet-05f678cbbba3d9a1d", "subnet-0f7b63788905e3eb2"] +} + +module "aws_anyscale_v2_existing_vpc" { + source = "../../" + tags = local.full_tags + + anyscale_deploy_env = var.anyscale_deploy_env + anyscale_cloud_id = var.anyscale_cloud_id + + # VPC Related + existing_vpc_id = local.existing_vpc_id + existing_vpc_subnet_ids = local.existing_public_subnet_ids + + # Security Group Related + security_group_ingress_allow_access_from_cidr_range = var.customer_ingress_cidr_ranges +} + + +# --------------------------------------------------------------------------------------------------------------------- +# Create core Anyscale v2 Stack with existing VPC and S3 Bucket +# Creates a v2 stack including +# - IAM Roles +# - VPC Security Groups +# - EFS +# - VPC Gateway Endpoint for S3 (not needed in this VPC but for testing purposes) +# --------------------------------------------------------------------------------------------------------------------- + +# module "aws_anyscale_v2_existing_vpc_existing_s3" { +# source = "../../" +# tags = local.full_tags + +# anyscale_deploy_env = var.anyscale_deploy_env +# anyscale_cloud_id = var.anyscale_cloud_id + +# # VPC Related +# existing_vpc_id = local.existing_vpc_id +# existing_vpc_subnet_ids = local.existing_subnet_ids + +# # Security Group Related +# security_group_ingress_allow_access_from_cidr_range = var.customer_ingress_cidr_ranges +# } + +# --------------------------------------------------------------------------------------------------------------------- +# Create core Anyscale v2 Stack resources with Private VPC +# Should be executed in us-east-2 +# Creates a v2 stack including +# - IAM Roles +# - S3 Bucket +# - VPC with publicly routed subnets (no internal) +# - VPC Security Groups +# - EFS +# --------------------------------------------------------------------------------------------------------------------- +locals { + private_vpc_cidr_block = "172.24.0.0/16" + private_vpc_public_subnets = ["172.24.21.0/24", "172.24.22.0/24", "172.24.23.0/24"] + private_vpc_private_subnets = ["172.24.101.0/24", "172.24.102.0/24", "172.24.103.0/24"] +} + +module "aws_anyscale_v2_private_vpc" { + source = "../../" + tags = local.full_tags + general_prefix = "private-vpc-" + + anyscale_deploy_env = var.anyscale_deploy_env + anyscale_cloud_id = var.anyscale_cloud_id + + # VPC Related + anyscale_vpc_cidr_block = local.private_vpc_cidr_block + anyscale_vpc_public_subnets = local.private_vpc_public_subnets + anyscale_vpc_private_subnets = local.private_vpc_private_subnets + anyscale_vpc_tags = { + "vpc_tag_test" : "private_vpc" + } + + # EFS Related + anyscale_efs_tags = { + "efs_tag_test" : "private_vpc" + } + # S3 Related + anyscale_s3_tags = { + "s3_tag_test" : "private_vpc" + } + + # IAM Related + anyscale_iam_tags = { + "iam_tag_test" : "private_vpc" + } + + # Security Group Related + security_group_ingress_allow_access_from_cidr_range = "172.24.0.0/16" + anyscale_securitygroup_tags = { + "sg_tag_test" = "private_vpc" + } +} diff --git a/test/anyscale-v2-test/outputs.tf b/test/anyscale-v2-test/outputs.tf new file mode 100644 index 0000000..65352c6 --- /dev/null +++ b/test/anyscale-v2-test/outputs.tf @@ -0,0 +1,135 @@ +# --------------------------------------------------------------------------------------------------------------------- +# Anyscale v2 Stack resources with minimal parameters +# --------------------------------------------------------------------------------------------------------------------- +output "anyscale_v2_vpc_id" { + description = "Anyscale VPC ID. If there was not one created, return the one that was used during other resource creation." + value = try(module.aws_anyscale_v2.anyscale_vpc_id, "") +} + +output "anyscale_v2_vpc_public_subnet_ids" { + description = "Anyscale VPC Public Subnet IDs. If there were none created, return an empty string." + value = try(module.aws_anyscale_v2.anyscale_vpc_public_subnet_ids, []) +} +output "anyscale_v2_vpc_private_subnet_ids" { + description = "Anyscale VPC Private Subnet IDs. If there were none created, return an empty string." + value = try(module.aws_anyscale_v2.anyscale_vpc_private_subnet_ids, []) +} + +output "anyscale_v2_s3_bucket_id" { + description = "Anyscale S3 Bucket ID. If a bucket was not created, return an empty string." + value = try(module.aws_anyscale_v2.anyscale_s3_bucket_id, "") +} + +output "anyscale_v2_security_group_id" { + description = "Anyscale Security Group ID. If a security group was not created, return an empty string." + value = try(module.aws_anyscale_v2.anyscale_security_group_id, "") +} + +output "anyscale_v2_iam_role_arn" { + description = "Anyscale IAM access role arn." + value = try(module.aws_anyscale_v2.anyscale_iam_role_arn, "") +} + +output "anyscale_v2_iam_instance_role_arn" { + description = "Anyscale IAM instance role arn." + value = try(module.aws_anyscale_v2.anyscale_iam_role_cluster_node_arn, "") +} + +output "anyscale_v2_efs_id" { + description = "Anyscale Elastic File System ID." + value = try(module.aws_anyscale_v2.anyscale_efs_id, "") +} + +# --------------------------------------------------------------------------------------------------------------------- +# Anyscale v2 Stack with existing VPC +# --------------------------------------------------------------------------------------------------------------------- +output "anyscale_v2_existing_vpc_s3_bucket_id" { + description = "Anyscale S3 Bucket ID. If a bucket was not created, return an empty string." + value = try(module.aws_anyscale_v2_existing_vpc.anyscale_s3_bucket_id, "") +} + +output "anyscale_v2_existing_vpc_security_group_id" { + description = "Anyscale Security Group ID. If a security group was not created, return an empty string." + value = try(module.aws_anyscale_v2_existing_vpc.anyscale_security_group_id, "") +} + +output "anyscale_v2_existing_vpc_iam_role_arn" { + description = "Anyscale IAM access role arn." + value = try(module.aws_anyscale_v2_existing_vpc.anyscale_iam_role_arn, "") +} + +output "anyscale_v2_existing_vpc_iam_instance_role_arn" { + description = "Anyscale IAM instance role arn." + value = try(module.aws_anyscale_v2_existing_vpc.anyscale_iam_role_cluster_node_arn, "") +} + +output "anyscale_v2_existing_vpc_efs_id" { + description = "Anyscale Elastic File System ID." + value = try(module.aws_anyscale_v2_existing_vpc.anyscale_efs_id, "") +} + + +# --------------------------------------------------------------------------------------------------------------------- +# Anyscale v2 Stack with existing VPC and existing S3 Bucket +# --------------------------------------------------------------------------------------------------------------------- +# output "anyscale_v2_existing_vpc_existing_s3_security_group_id" { +# description = "Anyscale Security Group ID. If a security group was not created, return an empty string." +# value = try(module.aws_anyscale_v2_existing_vpc_existing_s3.anyscale_security_group_id, "") +# } + +# output "anyscale_v2_existing_existing_s3_vpc_iam_role_arn" { +# description = "Anyscale IAM access role arn." +# value = try(module.aws_anyscale_v2_existing_vpc_existing_s3.anyscale_iam_role_arn, "") +# } + +# output "anyscale_v2_existing_vpc_existing_s3_iam_instance_role_arn" { +# description = "Anyscale IAM instance role arn." +# value = try(module.aws_anyscale_v2_existing_vpc_existing_s3.anyscale_iam_role_cluster_node_arn, "") +# } + +# output "anyscale_v2_existing_vpc_existing_s3_efs_id" { +# description = "Anyscale Elastic File System ID." +# value = try(module.aws_anyscale_v2_existing_vpc_existing_s3.anyscale_efs_id, "") +# } + +# --------------------------------------------------------------------------------------------------------------------- +# Anyscale v2 Stack with private VPC +# --------------------------------------------------------------------------------------------------------------------- +output "anyscale_v2_private_vpc_id" { + description = "Anyscale VPC ID. If there was not one created, return the one that was used during other resource creation." + value = try(module.aws_anyscale_v2_private_vpc.anyscale_vpc_id, "") +} + +output "anyscale_v2_private_vpc_public_subnet_ids" { + description = "Anyscale VPC Public Subnet IDs. If there were none created, return an empty string." + value = try(module.aws_anyscale_v2_private_vpc.anyscale_vpc_public_subnet_ids, []) +} +output "anyscale_v2_private_vpc_private_subnet_ids" { + description = "Anyscale VPC Private Subnet IDs. If there were none created, return an empty string." + value = try(module.aws_anyscale_v2_private_vpc.anyscale_vpc_private_subnet_ids, []) +} + +output "anyscale_v2_private_vpc_s3_bucket_id" { + description = "Anyscale S3 Bucket ID. If a bucket was not created, return an empty string." + value = try(module.aws_anyscale_v2_private_vpc.anyscale_s3_bucket_id, "") +} + +output "anyscale_v2_private_vpc_security_group_id" { + description = "Anyscale Security Group ID. If a security group was not created, return an empty string." + value = try(module.aws_anyscale_v2_private_vpc.anyscale_security_group_id, "") +} + +output "anyscale_v2_private_vpc_iam_role_arn" { + description = "Anyscale IAM access role arn." + value = try(module.aws_anyscale_v2_private_vpc.anyscale_iam_role_arn, "") +} + +output "anyscale_v2_private_vpc_iam_instance_role_arn" { + description = "Anyscale IAM instance role arn." + value = try(module.aws_anyscale_v2_private_vpc.anyscale_iam_role_cluster_node_arn, "") +} + +output "anyscale_v2_private_vpc_efs_id" { + description = "Anyscale Elastic File System ID." + value = try(module.aws_anyscale_v2_private_vpc.anyscale_efs_id, "") +} diff --git a/test/anyscale-v2-test/variables.tf b/test/anyscale-v2-test/variables.tf new file mode 100644 index 0000000..d736901 --- /dev/null +++ b/test/anyscale-v2-test/variables.tf @@ -0,0 +1,66 @@ +# --------------------------------------------------------------------------------------------------------------------- +# ENVIRONMENT VARIABLES +# Define these secrets as environment variables +# --------------------------------------------------------------------------------------------------------------------- + +# AWS_ACCESS_KEY_ID +# AWS_SECRET_ACCESS_KEY + +# --------------------------------------------------------------------------------------------------------------------- +# REQUIRED VARIABLES +# These variables must be set when using this module. +# --------------------------------------------------------------------------------------------------------------------- + +variable "aws_region" { + description = "The AWS region in which all resources will be created." + type = string +} + +variable "anyscale_deploy_env" { + description = "(Required) Anyscale deploy environment. Used in resource names and tags." + type = string + validation { + condition = ( + var.anyscale_deploy_env == "production" || var.anyscale_deploy_env == "development" || var.anyscale_deploy_env == "test" + ) + error_message = "The anyscale_deploy_env only allows `production`, `test`, or `development`" + } +} + +# ------------------------------------------------------------------------------ +# OPTIONAL PARAMETERS +# These variables have defaults, but may be overridden. +# ------------------------------------------------------------------------------ +variable "anyscale_cloud_id" { + description = "(Optional) Anyscale Cloud ID. Default is `null`." + type = string + default = null + validation { + condition = ( + var.anyscale_cloud_id == null ? true : ( + length(var.anyscale_cloud_id) > 4 && + substr(var.anyscale_cloud_id, 0, 4) == "cld_" + ) + ) + error_message = "The anyscale_cloud_id value must start with \"cld_\"." + } +} + +variable "tags" { + description = "(Optional) A map of tags to all resources that accept tags." + type = map(string) + default = { + "test" : true, + "environment" : "test" + } +} + +variable "customer_ingress_cidr_ranges" { + description = <<-EOT + The IPv4 CIDR block that is allowed to access the clusters. + This provides the ability to lock down the v1 stack to just the public IPs of a corporate network. + This is added to the security group and allows port 443 (https) and 22 (ssh) access. + ex: `52.1.1.23/32,10.1.0.0/16` + EOT + type = string +} diff --git a/test/anyscale-v2-test/versions.tf b/test/anyscale-v2-test/versions.tf new file mode 100644 index 0000000..df08979 --- /dev/null +++ b/test/anyscale-v2-test/versions.tf @@ -0,0 +1,13 @@ +terraform { + required_version = ">= 1.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.0" + } + } +} + +provider "aws" { + region = var.aws_region +} diff --git a/test/go.mod b/test/go.mod index df410fc..bad7ec1 100644 --- a/test/go.mod +++ b/test/go.mod @@ -1,68 +1,67 @@ -module aws-anyscale-efs +module aws-anyscale-root go 1.19 require ( - github.com/gruntwork-io/terratest v0.41.7 + github.com/gruntwork-io/terratest v0.41.10 github.com/stretchr/testify v1.8.1 ) require ( - cloud.google.com/go v0.108.0 // indirect - cloud.google.com/go/compute v1.15.1 // indirect - cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/iam v0.10.0 // indirect - cloud.google.com/go/storage v1.28.1 // indirect + cloud.google.com/go v0.83.0 // indirect + cloud.google.com/go/storage v1.10.0 // indirect github.com/agext/levenshtein v1.2.3 // indirect github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect - github.com/aws/aws-sdk-go v1.44.177 // indirect + github.com/aws/aws-sdk-go v1.40.56 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect - github.com/boombuler/barcode v1.0.1 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect + github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/go-errors/errors v1.4.2 // indirect - github.com/go-sql-driver/mysql v1.7.0 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/go-errors/errors v1.0.2-0.20180813162953-d98b870cc4e0 // indirect + github.com/go-sql-driver/mysql v1.4.1 // indirect + github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect github.com/golang/protobuf v1.5.2 // indirect - github.com/google/go-cmp v0.5.9 // indirect - github.com/google/uuid v1.3.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.2.1 // indirect - github.com/googleapis/gax-go/v2 v2.7.0 // indirect - github.com/gruntwork-io/go-commons v0.14.0 // indirect - github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/golang/snappy v0.0.3 // indirect + github.com/google/uuid v1.2.0 // indirect + github.com/googleapis/gax-go/v2 v2.0.5 // indirect + github.com/gruntwork-io/go-commons v0.8.0 // indirect + github.com/hashicorp/errwrap v1.0.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-getter v1.6.2 // indirect - github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/go-getter v1.6.1 // indirect + github.com/hashicorp/go-multierror v1.1.0 // indirect github.com/hashicorp/go-safetemp v1.0.0 // indirect - github.com/hashicorp/go-version v1.6.0 // indirect - github.com/hashicorp/hcl/v2 v2.15.0 // indirect - github.com/hashicorp/terraform-json v0.14.0 // indirect - github.com/jinzhu/copier v0.3.5 // indirect + github.com/hashicorp/go-version v1.3.0 // indirect + github.com/hashicorp/hcl/v2 v2.9.1 // indirect + github.com/hashicorp/terraform-json v0.13.0 // indirect + github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/klauspost/compress v1.15.14 // indirect - github.com/mattn/go-zglob v0.0.4 // indirect + github.com/jstemmer/go-junit-report v0.9.1 // indirect + github.com/klauspost/compress v1.13.0 // indirect + github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/go-testing-interface v1.14.1 // indirect + github.com/mitchellh/go-testing-interface v1.0.0 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/pquerna/otp v1.4.0 // indirect + github.com/pquerna/otp v1.2.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/tmccombs/hcl2json v0.3.6 // indirect - github.com/ulikunitz/xz v0.5.11 // indirect - github.com/urfave/cli/v2 v2.23.7 // indirect - github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect - github.com/zclconf/go-cty v1.12.1 // indirect - go.opencensus.io v0.24.0 // indirect - golang.org/x/crypto v0.5.0 // indirect - golang.org/x/net v0.5.0 // indirect - golang.org/x/oauth2 v0.4.0 // indirect - golang.org/x/sys v0.4.0 // indirect - golang.org/x/text v0.6.0 // indirect - golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect - google.golang.org/api v0.106.0 // indirect + github.com/tmccombs/hcl2json v0.3.3 // indirect + github.com/ulikunitz/xz v0.5.8 // indirect + github.com/urfave/cli v1.22.2 // indirect + github.com/zclconf/go-cty v1.9.1 // indirect + go.opencensus.io v0.23.0 // indirect + golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a // indirect + golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect + golang.org/x/mod v0.4.2 // indirect + golang.org/x/net v0.0.0-20210614182718-04defd469f4e // indirect + golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c // indirect + golang.org/x/sys v0.0.0-20220517195934-5e4e11fc645e // indirect + golang.org/x/text v0.3.6 // indirect + golang.org/x/tools v0.1.2 // indirect + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + google.golang.org/api v0.47.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect - google.golang.org/grpc v1.51.0 // indirect - google.golang.org/protobuf v1.28.1 // indirect + google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect + google.golang.org/grpc v1.38.0 // indirect + google.golang.org/protobuf v1.26.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/test/go.sum b/test/go.sum index e402983..8899bd7 100644 --- a/test/go.sum +++ b/test/go.sum @@ -4,47 +4,70 @@ cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSR cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.108.0 h1:xntQwnfn8oHGX0crLVinvHM+AhXvi3QHQIEcX/2hiWk= -cloud.google.com/go v0.108.0/go.mod h1:lNUfQqusBJp0bgAg6qrHgYFYbTB+dOiob1itwnlD33Q= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go v0.83.0 h1:bAMqZidYkmIsUqe6PtkEPT7Q+vfizScn+jfNA6jwK9c= +cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/compute v1.15.0 h1:PiKE4V948A1BRvhuwA2hOxL8imyvwuRgrOiytC+NlXo= -cloud.google.com/go/compute v1.15.0/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA= -cloud.google.com/go/compute v1.15.1 h1:7UGq3QknM33pw5xATlpzeoomNxsacIVvTqTTvbfajmE= -cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA= -cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= -cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/iam v0.10.0 h1:fpP/gByFs6US1ma53v7VxhvbJpO2Aapng6wabJ99MuI= -cloud.google.com/go/iam v0.10.0/go.mod h1:nXAECrMt2qHpF6RZUZseteD6QyanL68reN4OXPw0UWM= -cloud.google.com/go/longrunning v0.3.0 h1:NjljC+FYPV3uh5/OwWT6pVU+doBqMg2x/rZlE+CamDs= -cloud.google.com/go/storage v1.28.1 h1:F5QDG5ChchaAVQhINh24U99OWHURqrW8OmQcGKXcbgI= -cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0 h1:STgFzyU5/8miMl0//zKh2aQeTyeaUH3WN9bSUiJ09bA= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= -github.com/apparentlymart/go-textseg v1.0.0 h1:rRmlIsPEEhUTIKQb7T++Nz/A5Q6C9IuX2wFoYVvnCs0= github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw= github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= github.com/aws/aws-sdk-go v1.15.78/go.mod h1:E3/ieXAlvM0XWO57iftYVDLLvQ824smPP3ATZkfNZeM= -github.com/aws/aws-sdk-go v1.44.175 h1:c0NzHHnPXV5kJoTUFQxFN5cUPpX1SxO635XnwL5/oIY= -github.com/aws/aws-sdk-go v1.44.175/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= -github.com/aws/aws-sdk-go v1.44.177 h1:ckMJhU5Gj+4Rta+bJIUiUd7jvHom84aim3zkGPblq0s= -github.com/aws/aws-sdk-go v1.44.177/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.40.56 h1:FM2yjR0UUYFzDTMx+mH9Vyw1k1EUUxsAFzk+BjkzANA= +github.com/aws/aws-sdk-go v1.40.56/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI= github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= -github.com/boombuler/barcode v1.0.1 h1:NDBbPmhS+EqABEs5Kg3n/5ZNjy73Pz7SIV+KCeqyXcs= -github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -52,99 +75,137 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= -github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= -github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= -github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/go-errors/errors v1.0.2-0.20180813162953-d98b870cc4e0 h1:skJKxRtNmevLqnayafdLe2AsenqRupVmzZSqrvb5caU= +github.com/go-errors/errors v1.0.2-0.20180813162953-d98b870cc4e0/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA= +github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-test/deep v1.0.7 h1:/VSMRlnY/JSyqxQUzQLKVMAskpY/NZKFA5j2P+0pP2M= github.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.2.1 h1:d8MncMlErDFTwQGBK1xhv026j9kqhvw1Qv9IbWT1VLQ= +github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.2.1 h1:RY7tHKZcRlk788d5WSo/e83gOyyy742E8GSs771ySpg= -github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ= -github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= -github.com/gruntwork-io/go-commons v0.14.0 h1:Ry+PgcUNOD9403J7HJwsRoGmP67kmn/n3BvlaRZ4GCA= -github.com/gruntwork-io/go-commons v0.14.0/go.mod h1:AlYVzB6p6d8IYakGPNq/pspRjI7da7FeAIffISO9878= -github.com/gruntwork-io/terratest v0.41.7 h1:Vc0hb7ajWHutGA++gu/a9FSkuf+IuQuGDRymiWdrA04= -github.com/gruntwork-io/terratest v0.41.7/go.mod h1:qH1xkPTTGx30XkMHw8jAVIbzqheSjIa5IyiTwSV2vKI= +github.com/gruntwork-io/go-commons v0.8.0 h1:k/yypwrPqSeYHevLlEDmvmgQzcyTwrlZGRaxEM6G0ro= +github.com/gruntwork-io/go-commons v0.8.0/go.mod h1:gtp0yTtIBExIZp7vyIV9I0XQkVwiQZze678hvDXof78= +github.com/gruntwork-io/terratest v0.41.10 h1:yb6O5iZjwDFMyoDeWb+SKPzGaNlLddb5ip2wJHo1m8g= +github.com/gruntwork-io/terratest v0.41.10/go.mod h1:qH1xkPTTGx30XkMHw8jAVIbzqheSjIa5IyiTwSV2vKI= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= -github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-getter v1.6.2 h1:7jX7xcB+uVCliddZgeKyNxv0xoT7qL5KDtH7rU4IqIk= -github.com/hashicorp/go-getter v1.6.2/go.mod h1:IZCrswsZPeWv9IkVnLElzRU/gz/QPi6pZHn4tv6vbwA= -github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-getter v1.6.1 h1:NASsgP4q6tL94WH6nJxKWj8As2H/2kop/bB1d8JMyRY= +github.com/hashicorp/go-getter v1.6.1/go.mod h1:IZCrswsZPeWv9IkVnLElzRU/gz/QPi6pZHn4tv6vbwA= +github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= +github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.5.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= -github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.3.0 h1:McDWVJIU/y+u1BRV06dPaLfLCaT7fUTJLp5r04x7iNw= +github.com/hashicorp/go-version v1.3.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl/v2 v2.15.0 h1:CPDXO6+uORPjKflkWCCwoWc9uRp+zSIPcCQ+BrxV7m8= -github.com/hashicorp/hcl/v2 v2.15.0/go.mod h1:JRmR89jycNkrrqnMmvPDMd56n1rQJ2Q6KocSLCMCXng= -github.com/hashicorp/terraform-json v0.14.0 h1:sh9iZ1Y8IFJLx+xQiKHGud6/TSUCM0N8e17dKDpqV7s= -github.com/hashicorp/terraform-json v0.14.0/go.mod h1:5A9HIWPkk4e5aeeXIBbkcOvaZbIYnAIkEyqP2pNSckM= -github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg= -github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= +github.com/hashicorp/hcl/v2 v2.9.1 h1:eOy4gREY0/ZQHNItlfuEZqtcQbXIxzojlP301hDpnac= +github.com/hashicorp/hcl/v2 v2.9.1/go.mod h1:FwWsfWEjyV/CMj8s/gqAuiviY72rJ1/oayI9WftqcKg= +github.com/hashicorp/terraform-json v0.13.0 h1:Li9L+lKD1FO5RVFRM1mMMIBDoUHslOniyEi5CM+FWGY= +github.com/hashicorp/terraform-json v0.13.0/go.mod h1:y5OdLBCT+rxbwnpxZs9kGL7R9ExU76+cpdY8zHwoazk= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a h1:zPPuIq2jAWWPTrGt70eK/BSch+gFAGrNzecsoENgu2o= +github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a/go.mod h1:yL958EeXv8Ylng6IfnvG4oflryUi3vgA3xPs9hmII1s= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.11.2/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.15.14 h1:i7WCKDToww0wA+9qrUZ1xOjp218vfFo3nTU6UHp+gOc= -github.com/klauspost/compress v1.15.14/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= +github.com/klauspost/compress v1.13.0 h1:2T7tUoQrQT+fQWdaY5rjWztFGAFwbGD04iPJg90ZiOs= +github.com/klauspost/compress v1.13.0/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -156,17 +217,20 @@ github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LE github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-zglob v0.0.4 h1:LQi2iOm0/fGgu80AioIJ/1j9w9Oh+9DZ39J4VAGzHQM= -github.com/mattn/go-zglob v0.0.4/go.mod h1:MxxjyoXXnMxfIpxTK2GAkw1w8glPsQILx3N5wrKakiY= +github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= +github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326 h1:ofNAzWCcyTALn2Zv40+8XitdzCgXY6e9qvXwN9W0YXg= +github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= -github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= @@ -174,62 +238,104 @@ github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pquerna/otp v1.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg= -github.com/pquerna/otp v1.4.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= +github.com/pquerna/otp v1.2.0 h1:/A3+Jn+cagqayeR3iHs/L62m5ue7710D35zl1zJ1kok= +github.com/pquerna/otp v1.2.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sebdah/goldie v1.0.0/go.mod h1:jXP4hmWywNEwZzhMuv2ccnqTSFpuq8iyQhtQdkkZBH4= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/tmccombs/hcl2json v0.3.6 h1:QVZ1FKXXk9LBpaWTUvJXgdhsllpDmWnfr4/4FP+vBRQ= -github.com/tmccombs/hcl2json v0.3.6/go.mod h1:vRUcMTGRHWMSqa/T1yDk3Jft2Ct9MFDxoS422aASPdo= +github.com/tmccombs/hcl2json v0.3.3 h1:+DLNYqpWE0CsOQiEZu+OZm5ZBImake3wtITYxQ8uLFQ= +github.com/tmccombs/hcl2json v0.3.3/go.mod h1:Y2chtz2x9bAeRTvSibVRVgbLJhLJXKlUeIvjeVdnm4w= +github.com/ulikunitz/xz v0.5.8 h1:ERv8V6GKqVi23rgu5cj9pVfVzJbOqAY2Ntl88O6c2nQ= github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= -github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/urfave/cli/v2 v2.23.7 h1:YHDQ46s3VghFHFf1DdF+Sh7H4RqhcM+t0TmZRJx4oJY= -github.com/urfave/cli/v2 v2.23.7/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= +github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo= +github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= -github.com/zclconf/go-cty v1.10.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= -github.com/zclconf/go-cty v1.12.1 h1:PcupnljUm9EIvbgSHQnHhUr3fO6oFmkOrvs2BAFNXXY= -github.com/zclconf/go-cty v1.12.1/go.mod h1:s9IfD1LK5ccNMSWCVFCE2rJfHiZgi7JijgeWIMfhLvA= +github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= +github.com/zclconf/go-cty v1.8.1/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= +github.com/zclconf/go-cty v1.9.1 h1:viqrgQwFl5UpSxc046qblj78wZXVDFnSOufaOTER+cc= +github.com/zclconf/go-cty v1.9.1/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220517005047-85d78b3ac167/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= -golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= +golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc= +golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -241,59 +347,116 @@ golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q= +golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.4.0 h1:NF0gk8LVPg1Ml7SSbGyySuoxdsXitj7TvgvuRxIMc/M= -golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c h1:pkQiBZBvdos9qq4wBAHqlzuZHEXo07pqV06ef90u1WI= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220517195934-5e4e11fc645e h1:w36l2Uw3dRan1K3TyXriXvY+6T56GNmlKGcqiQUJDfM= golang.org/x/sys v0.0.0-20220517195934-5e4e11fc645e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.4.0 h1:O7UWfv5+A2qiuulQk30kVinPoMtoIPeVaKLEgLpVkvg= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -304,25 +467,79 @@ golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.2 h1:kRBLX7v7Af8W7Gdbbc908OJcdgtK8bOz9Uaj8/F1ACA= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.106.0 h1:ffmW0faWCwKkpbbtvlY/K/8fUl+JKvNS5CVzRoyfCv8= -google.golang.org/api v0.106.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.47.0 h1:sQLWZQvP6jPGIP4JGPkJu4zHswrv81iobiyszr3b/0I= +google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -332,20 +549,64 @@ google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20230109162033-3c3c17ce83e6 h1:uUn6GsgKK2eCI0bWeRMgRCcqDaQXYDuB+5tXA5Xeg/8= -google.golang.org/genproto v0.0.0-20230109162033-3c3c17ce83e6/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w= -google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c h1:wtujag7C+4D6KMoulW9YauvK2lgdvCMS260jsqqBXr0= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U= -google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -354,15 +615,17 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -372,4 +635,9 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/test/tf_aws_anyscale_test.go b/test/tf_aws_anyscale_test.go index 07a1907..2c374a4 100644 --- a/test/tf_aws_anyscale_test.go +++ b/test/tf_aws_anyscale_test.go @@ -4,22 +4,54 @@ import ( "testing" "github.com/gruntwork-io/terratest/modules/aws" + "github.com/gruntwork-io/terratest/modules/random" "github.com/gruntwork-io/terratest/modules/terraform" "github.com/stretchr/testify/assert" + + "encoding/json" + "fmt" + "io" + "net/http" ) -func TestAnyscaleResources(t *testing.T) { +type IP struct { + Query string +} + +func getip2() string { + req, err := http.Get("http://ip-api.com/json/") + if err != nil { + return err.Error() + } + defer req.Body.Close() + + body, err := io.ReadAll(req.Body) + if err != nil { + return err.Error() + } + + var ip IP + json.Unmarshal(body, &ip) + + return ip.Query +} + +func TestAnyscaleV1Resources(t *testing.T) { t.Parallel() - awsRegion := aws.GetRandomStableRegion(t, nil, nil) + // awsRegion := aws.GetRandomStableRegion(t, nil, nil) + awsRegion := "us-east-2" + expectedS3TagValue := fmt.Sprintf("tag-%s", random.UniqueId()) + // expectedS3Name := fmt.Sprintf("ex-%s", strings.ToLower(random.UniqueId())) terraformOptions := &terraform.Options{ // The path to where your Terraform code is located - TerraformDir: "../examples/anyscale-test", + TerraformDir: "./anyscale-v1-test", Vars: map[string]interface{}{ - "aws_region": awsRegion, - "anyscale_cloud_id": "cld_automated_terraform_test", - "anyscale_deploy_env": "test", + "aws_region": awsRegion, + "anyscale_cloud_id": "cld_automated_terraform_test", + "anyscale_deploy_env": "test", + "existing_vpc_s3_tag_value": expectedS3TagValue, }, Upgrade: true, } @@ -31,20 +63,77 @@ func TestAnyscaleResources(t *testing.T) { terraform.InitAndApply(t, terraformOptions) // Run `terraform output` to get the value of an output variable. If it's not available, fail the test. - allDefaultsAnyscaleArnOutput := terraform.OutputRequired(t, terraformOptions, "all_defaults_arn") - assert.Contains(t, allDefaultsAnyscaleArnOutput, "arn:aws:elasticfilesystem") - assert.Contains(t, allDefaultsAnyscaleArnOutput, awsRegion) - assert.Contains(t, allDefaultsAnyscaleArnOutput, "fs-") - - allDefaultsAnyscaleIdOutput := terraform.OutputRequired(t, terraformOptions, "all_defaults_id") - assert.Contains(t, allDefaultsAnyscaleIdOutput, "fs-") - - // Kitchen Sink Output Tests - kitchenSinkArnOutput := terraform.OutputRequired(t, terraformOptions, "kitchen_sink_arn") - assert.Contains(t, kitchenSinkArnOutput, "arn:aws:elasticfilesystem") - assert.Contains(t, kitchenSinkArnOutput, awsRegion) - assert.Contains(t, kitchenSinkArnOutput, "fs-") - - kitchenSinkIdOutput := terraform.OutputRequired(t, terraformOptions, "kitchen_sink_id") - assert.Contains(t, kitchenSinkIdOutput, "fs-") + // Anyscale v1 Stack resources with minimal parameters + anyscale_v1_vpc_id := terraform.OutputRequired(t, terraformOptions, "anyscale_v1_vpc_id") + assert.Contains(t, anyscale_v1_vpc_id, "vpc-") + + anyscale_v1_vpc_public_subnet_ids := terraform.OutputRequired(t, terraformOptions, "anyscale_v1_vpc_public_subnet_ids") + assert.Contains(t, anyscale_v1_vpc_public_subnet_ids, "subnet-") + + anyscale_v1_s3_bucket_id := terraform.OutputRequired(t, terraformOptions, "anyscale_v1_s3_bucket_id") + assert.Contains(t, anyscale_v1_s3_bucket_id, "anyscale-") + + anyscale_v1_security_group_id := terraform.OutputRequired(t, terraformOptions, "anyscale_v1_security_group_id") + assert.Contains(t, anyscale_v1_security_group_id, "sg-") + + anyscale_v1_iam_role_arn := terraform.OutputRequired(t, terraformOptions, "anyscale_v1_iam_role_arn") + assert.Contains(t, anyscale_v1_iam_role_arn, "arn:aws:iam::") + assert.Contains(t, anyscale_v1_iam_role_arn, "anyscale-iam-role-") + + anyscale_v1_iam_instance_role_arn := terraform.OutputRequired(t, terraformOptions, "anyscale_v1_iam_instance_role_arn") + assert.Contains(t, anyscale_v1_iam_instance_role_arn, "arn:aws:iam::") + assert.Contains(t, anyscale_v1_iam_instance_role_arn, "anyscale-cluster-node-") + + anyscale_v1_efs_id := terraform.OutputRequired(t, terraformOptions, "anyscale_v1_efs_id") + assert.Contains(t, anyscale_v1_efs_id, "fs-") + + // Anyscale v1 Stack with existing VPC + anyscale_v1_existing_vpc_s3_bucket_id := terraform.OutputRequired(t, terraformOptions, "anyscale_v1_existing_vpc_s3_bucket_id") + assert.Contains(t, anyscale_v1_existing_vpc_s3_bucket_id, "anyscale-") + // Verify that tag was applied. + anyscale_v1_existing_vpc_s3_bucket_tag_id := aws.FindS3BucketWithTag(t, awsRegion, "s3_tagging", expectedS3TagValue) + assert.Contains(t, anyscale_v1_existing_vpc_s3_bucket_tag_id, anyscale_v1_existing_vpc_s3_bucket_id) + + anyscale_v1_existing_vpc_security_group_id := terraform.OutputRequired(t, terraformOptions, "anyscale_v1_existing_vpc_security_group_id") + assert.Contains(t, anyscale_v1_existing_vpc_security_group_id, "sg-") + + anyscale_v1_existing_vpc_iam_role_arn := terraform.OutputRequired(t, terraformOptions, "anyscale_v1_existing_vpc_iam_role_arn") + assert.Contains(t, anyscale_v1_existing_vpc_iam_role_arn, "arn:aws:iam::") + assert.Contains(t, anyscale_v1_existing_vpc_iam_role_arn, "anyscale-iam-role-") + + anyscale_v1_existing_vpc_iam_instance_role_arn := terraform.OutputRequired(t, terraformOptions, "anyscale_v1_existing_vpc_iam_instance_role_arn") + assert.Contains(t, anyscale_v1_existing_vpc_iam_instance_role_arn, "arn:aws:iam::") + assert.Contains(t, anyscale_v1_existing_vpc_iam_instance_role_arn, "anyscale-cluster-node-") + + anyscale_v1_existing_vpc_efs_id := terraform.OutputRequired(t, terraformOptions, "anyscale_v1_existing_vpc_efs_id") + assert.Contains(t, anyscale_v1_existing_vpc_efs_id, "fs-") +} + +func TestAnyscaleV2Resources(t *testing.T) { + t.Parallel() + + myPublicIp := getip2() + // awsRegion := aws.GetRandomStableRegion(t, nil, nil) + awsRegion := "us-east-2" + expectedS3TagValue := fmt.Sprintf("tag-%s", random.UniqueId()) + // expectedS3Name := fmt.Sprintf("ex-%s", strings.ToLower(random.UniqueId())) + + terraformOptions := &terraform.Options{ + // The path to where your Terraform code is located + TerraformDir: "./anyscale-v2-test", + Vars: map[string]interface{}{ + "aws_region": awsRegion, + "anyscale_cloud_id": "cld_automated_terraform_test", + "anyscale_deploy_env": "test", + "existing_vpc_s3_tag_value": expectedS3TagValue, + "customer_ingress_cidr_ranges": myPublicIp + "/32", + }, + Upgrade: true, + } + + // At the end of the test, run `terraform destroy` to clean up any resources that were created + defer terraform.Destroy(t, terraformOptions) + + // This will run `terraform init` and `terraform apply` and fail the test if there are any errors + terraform.InitAndApply(t, terraformOptions) } diff --git a/variables.tf b/variables.tf index 76e8123..fcf489a 100644 --- a/variables.tf +++ b/variables.tf @@ -13,18 +13,6 @@ variable "anyscale_deploy_env" { } } -variable "cloud_provider" { - description = "(Required) Which cloud provider would you like to run this module on? Valid options are `aws` or `gcp`. Default is `aws`." - type = string - default = "aws" - validation { - condition = ( - var.cloud_provider == "aws" || var.cloud_provider == "gcp" - ) - error_message = "The cloud_provider variable only allows `aws` or `gcp`" - } -} - variable "security_group_ingress_allow_access_from_cidr_range" { description = <<-EOT (Required) Comma delimited string of IPv4 CIDR range to allow access to anyscale resources. @@ -56,11 +44,35 @@ variable "anyscale_cloud_id" { } variable "tags" { - description = "(Optional) A map of tags to all resources that accept tags." + description = <<-EOT + (Optional) + A map of default tags to be added to all resources that accept tags. + Resource dependent tags will be appended to this list. + ex: + tags = { + application = "Anyscale", + environment = "prod" + } + Default is an empty map. + EOT type = map(string) default = {} } +variable "general_prefix" { + description = <<-EOT + (Optional) + A general prefix to add to resources created (where prefixes are allowed). This applies to: + - S3 Buckets + - IAM Resources + - Security Groups + Resource specific prefixes override this variable. + Default is `null` + EOT + type = string + default = null +} + #-------------------------------------------- # VPC Variables #-------------------------------------------- @@ -69,32 +81,83 @@ variable "existing_vpc_id" { type = string default = null } -variable "existing_subnet_ids" { +variable "existing_vpc_subnet_ids" { description = "(Optional) Existing subnet IDs to create Anyscale resources in. If provided, this will skip creating resources with the Anyscale VPC module. VPC ID is also required is this is provided. Default is an empty list." type = list(string) default = [] } +variable "existing_vpc_route_table_ids" { + description = <<-EOT + (Optional) + Existing VPC Route Table IDs. + If provided, this will map new subnets to these route table IDs. If no new subnets are created, these route tables will be used to create VPC Endpoint(s). + EOT + type = list(string) + default = [] +} + variable "anyscale_vpc_name" { description = "(Optional) VPC name. Will default to `vpc_`." type = string default = null } + variable "anyscale_vpc_cidr_block" { description = "(Optional) The IPv4 CIDR block for the VPC. CIDR can be explicitly set or it can be derived from IPAM using `ipv4_netmask_length` & `ipv4_ipam_pool_id`. Default is `10.0.0.0/16`" type = string default = "10.0.0.0/16" } + variable "anyscale_vpc_public_subnets" { description = "(Optional) A list of public subnets inside the VPC. Default is an empty list." type = list(string) default = [] } + variable "anyscale_vpc_private_subnets" { description = "(Optional) A list of private subnets inside the VPC. Default is an empty list." type = list(string) default = [] } +variable "anyscale_vpc_tags" { + description = <<-EOT + (Optional) + A map of tags for VPC resources. + Duplicate tags found in the "tags" variable will get duplicated on the resource. + ex: + anyscale_vpc_tags = { + "purpose" : "networking", + "criticality" : "critical" + } + Default is an empty map. + EOT + type = map(string) + default = {} +} + +variable "anyscale_gateway_vpc_endpoints" { + description = <<-EOT + A map of Gateway VPC Endpoints to provision into the VPC. This is a map of objects with the following attributes: + - `name`: Short service name (either "s3" or "dynamodb") + - `policy` = A policy (as JSON string) to attach to the endpoint that controls access to the service. May be `null` for full access. + See the submodule variable for a full example. + It is Anyscale's recommendation to have an S3 VPC Endpoint to minimize S3 costs and maximize S3 performance. + Set to an empty map `{}` to skip creating VPC Endpoints. + Default is S3 with an empty (full access) policy. + EOT + type = map(object({ + name = string + policy = string + })) + default = { + "s3" = { + name = "s3" + policy = null + } + } +} + #-------------------------------------------- # IAM Variables #-------------------------------------------- @@ -114,11 +177,35 @@ variable "anyscale_iam_access_role_name_prefix" { description = <<-EOT (Optional, forces creation of new resource) The prefix for the Anyscale IAM access role. - The variable, anyscale_iam_access_role_name, will override this variable. - Default is `anyscale-iam-role-`. + If `anyscale_iam_access_role_name_prefix` is provided, it will override this variable. + The variable `general_prefix` is a fall-back prefix if this is not provided. + Default is `null` but is set to `anyscale-iam-role-` in a local variable. + EOT + type = string + default = null +} + +variable "anyscale_access_steadystate_policy_name" { + description = <<-EOT + (Optional) + Name for the Anyscale default steady state IAM policy. + If left `null`, will default to `anyscale_access_steadystate_policy_prefix` + If provided, overrides the `anyscale_access_steadystate_policy_prefix` variable. + Default is `null`. EOT type = string - default = "anyscale-iam-role-" + default = null +} +variable "anyscale_access_steadystate_policy_prefix" { + description = <<-EOT + (Optional) + Name prefix for the Anyscale default steady state IAM policy. + If `anyscale_access_steadystate_policy_name` is provided, it will override this variable. + The variable `general_prefix` is a fall-back prefix if this is not provided. + Default is `null` but is set to `anyscale-steady_state-` in a local variable. + EOT + type = string + default = null } variable "anyscale_iam_cluster_node_role_name" { @@ -135,11 +222,28 @@ variable "anyscale_iam_cluster_node_role_name_prefix" { description = <<-EOT (Optional, forces creation of new resource) The prefix of the Anyscale Cluster Node IAM role. - The variable, anyscale_iam_cluster_node_role_name, will override this variable. - Default is `anyscale-cluster-node-`. + If `anyscale_iam_cluster_node_role_name` is provided, it will override this variable. + The variable `general_prefix` is a fall-back prefix if this is not provided. + Default is `null` but is set to `anyscale-cluster-node-` in a local variable. EOT type = string - default = "anyscale-cluster-node-" + default = null +} + +variable "anyscale_iam_tags" { + description = <<-EOT + (Optional) + A map of tags for IAM resources. + Duplicate tags found in the "tags" variable will get duplicated on the resource. + ex: + anyscale_iam_tags = { + "purpose" : "iam", + "criticality" : "critical" + } + Default is an empty map. + EOT + type = map(string) + default = {} } #-------------------------------------------- @@ -155,9 +259,16 @@ variable "security_group_name" { } variable "security_group_name_prefix" { - description = "(Optional) The name prefix for the security group. Conflicts with security_group_name. Default is `anyscale-security-group-`." + description = <<-EOT + (Optional) + The name prefix for the security group. + If `security_group_name` is provided, it will override this variable. + The variable `general_prefix` is a fall-back prefix if this is not provided. + + Default is `null` but is set to `anyscale-security-group-` in a local variable. + EOT type = string - default = "anyscale-security-group-" + default = null } variable "security_group_create_anyscale_public_ingress" { type = bool @@ -212,6 +323,22 @@ variable "security_group_override_ingress_from_cidr_map" { default = [] } +variable "anyscale_securitygroup_tags" { + description = <<-EOT + (Optional) + A map of tags for Security Group resources. + Duplicate tags found in the "tags" variable will get duplicated on the resource. + ex: + anyscale_iam_tags = { + "purpose" : "security", + "criticality" : "critical" + } + Default is an empty map. + EOT + type = map(string) + default = {} +} + #-------------------------------------------- # EFS Variables #-------------------------------------------- @@ -266,7 +393,39 @@ variable "efs_lifecycle_transition_to_primary_storage_class" { } } +variable "anyscale_efs_tags" { + description = <<-EOT + (Optional) + A map of tags for EFS resources. + Duplicate tags found in the "tags" variable will get duplicated on the resource. + ex: + anyscale_iam_tags = { + "purpose" : "storage", + "criticality" : "critical" + } + Default is an empty map. + EOT + type = map(string) + default = {} +} + +#-------------------------------------------- # S3 Variables +#-------------------------------------------- +variable "existing_s3_bucket_arn" { + description = <<-EOT + (Optional) + The name of an existing S3 bucket that you'd like to use. + Please make sure that it meets the minimum requirements for Anyscale including: + - Bucket Policy + - CORS Policy + - Encryption configuration + Default is `null` + EOT + type = string + default = null +} + variable "anyscale_s3_bucket_name" { description = <<-EOT (Optional - forces new resource) @@ -284,8 +443,86 @@ variable "anyscale_s3_bucket_prefix" { (Optional - forces new resource) Creates a unique bucket name beginning with the specified prefix. If `anyscale_s3_bucket_name` is provided, it will override this variable. - Default is `anyscale-`. + The variable `general_prefix` is a fall-back prefix if this is not provided. + Default is `null` but is set to `anyscale-` in a local variable. EOT type = string - default = "anyscale-" + default = null +} + +variable "anyscale_s3_server_side_encryption" { + description = <<-EOT + (Optional) + Configuration to enforce server side encryption (KMS or AES256). + If you are using KMS, you must proivde the KMS Key ID. + ex using kms: + apply_server_side_encryption_by_default = { + kms_master_key_id = "1234abcd-12ab-34cd-56ef-1234567890ab" + sse_algorithm = "aws:kms" + } + Default is `{ sse_algorithm = "AES256" }` + EOT + type = map(string) + default = { + sse_algorithm = "AES256" + } +} + +variable "anyscale_s3_force_destroy" { + description = <<-EOT + (Optional) + Set to true to delete all objects from the bucket so that the bucket can be destroyed without error. + If set to true and bucket is destroyed, objects are not recoverable. + Default is `false`. + Note: With this default, you need to empty the bucket if there are objects before `terraform destroy` can be completed succesfully. + EOT + type = bool + default = false +} + +# S3 Bucket Policy Variables +# ex policy: +# data "aws_iam_policy_document" "bucket_policy" { +# statement { +# principals { +# type = "AWS" +# identifiers = [aws_iam_role.this.arn] +# } +# +# actions = [ +# "s3:ListBucket", +# ] +# +# resources = [ +# "module.aws_anyscale_s3.s3_bucket_arn, +# ] +# } +# } +# anyscale_custom_s3_policy = data.aws_iam_policy_document.bucket_policy.json +variable "anyscale_custom_s3_policy" { + description = <<-EOT + (Optional) + A valid bucket policy in JSON. This will be an additional S3 bucket policy to the required Anyscale policy. + For more information about building AWS IAM policy documents with Terraform, see the AWS IAM Policy Document Guide. + And for more additional examples, please look at the s3-policy sub-module examples folder. + Default is `null`. + EOT + type = string + default = null +} + +variable "anyscale_s3_tags" { + description = <<-EOT + (Optional) + A map of tags for S3 resources. + Duplicate tags found in the "tags" variable will get duplicated on the resource. + ex: + anyscale_iam_tags = { + "purpose" : "storage", + "criticality" : "critical" + } + Default is an empty map. + EOT + type = map(string) + default = {} }