├── .gitignore ├── .gitmodules ├── aws ├── custom-remote-state-bucket │ └── main.tf ├── ec2-redash │ ├── README.md │ ├── ec2.tf │ ├── elastic-ip.tf │ ├── key_pair.tf │ ├── outputs.tf │ ├── providers.tf │ ├── random.tf │ ├── sample.png │ ├── security_group.tf │ ├── variables.tf │ └── vpc.tf ├── ec2-simple │ └── main.tf ├── github-ee │ ├── dns.tf │ ├── main.tf │ ├── security-group.tf │ └── variables.tf ├── hello-world │ ├── README.md │ ├── env0.yml │ ├── index.template.html │ ├── main.tf │ ├── output.tf │ ├── s3.tf │ └── sample.png ├── iam │ └── env0-cost-estimation-role │ │ ├── README.md │ │ ├── data.tf │ │ ├── env0-cost.tf │ │ ├── outputs.tf │ │ ├── provider.tf │ │ ├── variables.tf │ │ └── versions.tf ├── k8s │ ├── agent.tf │ ├── cluster.tf │ ├── providers.tf │ ├── variables.tf │ └── versions.tf ├── opa-example │ ├── .gitignore │ ├── README.md │ ├── env0.yml │ ├── main.tf │ ├── tf-lib.rego │ └── validation.rego ├── profile │ ├── README.md │ ├── env0.yml │ └── main.tf ├── s3-bucket │ ├── index.html │ ├── s3 │ │ ├── output.tf │ │ └── s3.tf │ ├── tf-0-13 │ │ └── main.tf │ └── tf-1-0 │ │ └── main.tf ├── security-group │ ├── README.md │ ├── provider.tf │ └── security-group.tf └── vault-server-on-eks │ ├── README.md │ ├── env0.yml │ ├── get-vault-address.sh │ ├── main.tf │ ├── providers.tf │ ├── variables.tf │ └── vault-config.yaml ├── azure ├── README.md ├── demo │ ├── README.md │ └── main.tf └── resource-group │ └── main.tf ├── cloudformation └── hello-world │ ├── README.md │ ├── env0.yml │ ├── index.template.html │ ├── sample.png │ └── stack.yaml ├── community-providers └── pingdom │ ├── README.md │ ├── env0.yml │ └── main.tf ├── custom-flows ├── external-script.yaml ├── opa-polices │ └── null-resource.rego ├── opa.yaml └── scripts │ └── script.sh ├── gcp ├── bq-dataset │ ├── README.md │ └── main.tf ├── container-cluster │ └── main.tf └── service-account-key │ ├── README.md │ ├── mainf.tf │ └── variables.tf ├── helm └── dummy │ ├── .helmignore │ ├── Chart.yaml │ ├── README.md │ ├── templates │ ├── NOTES.txt │ ├── _helpers.tpl │ ├── deployment.yaml │ ├── hpa.yaml │ ├── ingress.yaml │ ├── service.yaml │ ├── serviceaccount.yaml │ └── tests │ │ └── test-connection.yaml │ └── values.yaml ├── ibm └── bare-metal │ └── main.tf ├── kubernetes ├── hello-world │ ├── README.md │ ├── env0.yml │ └── namespace.yaml ├── squid-proxy │ ├── README.md │ ├── env0.yml │ ├── network-policy.yaml │ └── squid-proxy.yaml ├── using-pulumi │ ├── Pulumi.yaml │ ├── README.md │ ├── env0.yml │ ├── index.ts │ ├── package.json │ └── tsconfig.json └── using-terraform │ ├── README.md │ └── main.tf ├── misc ├── ansible │ └── playbook.yml ├── azure-vault-sensitive-var │ ├── README.md │ ├── env0.yml │ ├── main.tf │ └── validate.sh ├── clone-with-commit-integ-test │ ├── env0.yml │ └── main.tf ├── custom-flow-tf-vars │ ├── README.md │ ├── env0.yml │ └── main.tf ├── custom-flows-environment-variables │ ├── README.md │ ├── env0.yml │ ├── export-user-id.sh │ ├── main.tf │ ├── print-user-id.sh │ └── var-file.json ├── decode-oidc │ ├── decode-oidc-token.sh │ ├── env0.yml │ └── main.tf ├── drift-detection │ ├── env0.yml │ └── main.tf ├── ensure-permissions-on-tools-and-folders-for-user-node │ ├── ensure-permissions.sh │ ├── env0.yml │ └── main.tf ├── environment-outputs │ ├── inputs │ │ ├── env0.yml │ │ ├── main.tf │ │ └── validate.sh │ └── outputs │ │ └── main.tf ├── environment-variables │ ├── README.md │ ├── env0.yml │ └── main.tf ├── git-submodules │ ├── https │ │ └── README.md │ └── relative │ │ └── README.md ├── local-sub-module │ ├── child │ │ └── main.tf │ └── parent │ │ └── main.tf ├── null-fail-by-variable │ ├── README.md │ ├── env0.yml │ └── main.tf ├── null-resource-with-tf-version-constraints │ └── main.tf ├── null-resource-workflow-environment │ ├── README.md │ └── env0.workflow.yml ├── null-resource │ └── main.tf ├── null-sleep │ ├── env0.yml │ └── main.tf ├── remote-backend-on-s3 │ ├── env0.yml │ └── main.tf ├── remote-backend │ ├── env0.yml │ ├── main.tf │ └── validate-remote.sh ├── single-environment-workflow │ ├── README.md │ └── env0.workflow.yml ├── slack-notification │ ├── README.md │ ├── env0.yml │ ├── main.tf │ ├── on-approve.sh │ ├── on-fail.sh │ ├── on-plan.sh │ ├── on-start.sh │ ├── on-store-state.sh │ ├── on-success.sh │ └── slack.sh ├── ssm-sensitive-var │ ├── README.md │ ├── env0.yml │ ├── main.tf │ └── validate.sh ├── terraform-validate-workspace │ └── main.tf ├── validate-assume-role │ ├── README.md │ ├── env0.yml │ ├── main.tf │ └── validate.sh ├── validate-state │ ├── env0.yml │ ├── main.tf │ └── validate.sh ├── vault-integration │ ├── README.md │ ├── configure-vault.sh │ ├── env0.yml │ ├── main.tf │ └── test-vault.sh ├── workflow-environment-basic-dependencies-2 │ ├── README.md │ └── env0.workflow.yml ├── workflow-environment-basic-dependencies │ ├── README.md │ └── env0.workflow.yml ├── workflow-environment-basic │ ├── README.md │ └── env0.workflow.yml ├── workflow-environment │ ├── README.md │ └── env0.workflow.yml ├── workflows-with-no-templates │ └── three-nodes │ │ └── env0.workflow.yml └── workflows │ ├── _init-via-provider_ │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ └── variables.tf │ ├── environment-alias-validation │ ├── README.md │ └── env0.workflow.yml │ ├── environment-outputs │ └── env0.workflow.yml │ ├── graph-with-leaf-dependant-on-two-branches │ ├── README.md │ └── env0.workflow.yml │ └── workflow-with-failures │ ├── README.md │ └── env0.workflow.yml ├── plugins ├── checkov │ ├── env0.yml │ └── main.tf ├── tflint │ ├── env0.yml │ └── main.tf ├── tfsec │ ├── env0.yml │ └── main.tf ├── trivy │ ├── env0.yml │ └── main.tf └── v2-spec-file │ ├── env0.yml │ └── main.tf ├── pulumi ├── aws │ └── hello-world │ │ ├── .gitignore │ │ ├── Pulumi.dev.yaml │ │ ├── Pulumi.yaml │ │ ├── README.md │ │ ├── env0.yml │ │ ├── index.template.html │ │ ├── index.ts │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── sample.png │ │ ├── tsconfig.json │ │ └── www │ │ └── index.html └── dummy-resource │ ├── Pulumi.yaml │ ├── env0.yaml │ ├── index.ts │ ├── package-lock.json │ ├── package.json │ └── tsconfig.json ├── root-folder-terraform.tf ├── terragrunt ├── __inputs │ ├── temp.hcl │ └── temp2.hcl ├── misc │ ├── ensure-permissions-on-tools-and-folders-for-user-node │ │ ├── env0.yml │ │ ├── main.tf │ │ └── terragrunt.hcl │ ├── module-resource │ │ ├── README.md │ │ ├── module │ │ │ └── null-module │ │ │ │ └── main.tf │ │ ├── simple │ │ │ └── terragrunt.hcl │ │ ├── terragrunt.hcl │ │ └── with-env-yaml │ │ │ ├── env0.yml │ │ │ └── terragrunt.hcl │ ├── null-resource │ │ ├── .gitignore │ │ ├── README.md │ │ ├── dev │ │ │ ├── main.tf │ │ │ └── terragrunt.hcl │ │ ├── prod │ │ │ ├── main.tf │ │ │ └── terragrunt.hcl │ │ └── terragrunt.hcl │ └── source-resource │ │ ├── README.md │ │ ├── module │ │ └── null-module │ │ │ └── main.tf │ │ ├── simple │ │ └── terragrunt.hcl │ │ ├── terragrunt.hcl │ │ └── with-env-yaml │ │ ├── env0.yml │ │ └── terragrunt.hcl ├── run-all │ └── dependencies │ │ ├── .gitignore │ │ ├── backend-app │ │ ├── main.tf │ │ └── terragrunt.hcl │ │ └── vpc │ │ ├── main.tf │ │ └── terragrunt.hcl └── terragrunt.hcl └── vsphere └── vm-http-server ├── README.md ├── data.tf ├── env0.yml ├── http_server.py ├── main.tf ├── outputs.tf └── variables.tf /.gitignore: -------------------------------------------------------------------------------- 1 | ### IDE 2 | # Jetbrains 3 | .idea/ 4 | 5 | ### macOS template 6 | # General 7 | .DS_Store 8 | .AppleDouble 9 | .LSOverride 10 | 11 | # Thumbnails 12 | ._* 13 | 14 | .terraform 15 | *.tfstate 16 | *.tfstate.backup 17 | 18 | node_modules/ 19 | 20 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "misc/git-submodules/https/child"] 2 | path = misc/git-submodules/https/child 3 | url = https://github.com/env0/templates-git-submodule 4 | [submodule "misc/git-submodules/relative/child"] 5 | path = misc/git-submodules/relative/child 6 | url = ../templates-git-submodule 7 | -------------------------------------------------------------------------------- /aws/custom-remote-state-bucket/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0" 3 | } 4 | 5 | module "remote_state_bucket" { 6 | source = "github.com/env0/remote-state-bucket-module/aws" 7 | 8 | # Module-specific inputs 9 | external_id = "64922d09-2a1f-4f5b-b978-4f5e18f5e3b6" 10 | state_bucket_name = "custom-rbe-bucket-integration-tests-states-bucket" 11 | region = "us-west-2" 12 | env0_aws_role_name = "arn:aws:iam::170412844252:role/remote-backend-bors" 13 | } 14 | 15 | output "bucket_name" { 16 | value = module.remote_state_bucket.bucket_name 17 | } 18 | 19 | output "role_arn" { 20 | value = module.remote_state_bucket.role_arn 21 | } 22 | 23 | output "external_id" { 24 | value = module.remote_state_bucket.external_id 25 | } 26 | 27 | output "region" { 28 | value = module.remote_state_bucket.region 29 | } 30 | -------------------------------------------------------------------------------- /aws/ec2-redash/README.md: -------------------------------------------------------------------------------- 1 | # Redash instance on AWS EC2 2 | A Terraform 12 example of how to deploy an application onto an EC2 on AWS. 3 | In this example, we will deploy [Redash](https://redash.io/) 4 | 5 | ![](sample.png) 6 | 7 | ## Configuration 8 | - `AWS_ACCESS_KEY_ID` - Your AWS Secret Key ID 9 | - `AWS_SECRET_ACCESS_KEY` - You AWS Secret key. **Tick the "Secret" checkbox on env0 when setting this one** 10 | 11 | ### Environment Variables 12 | None 13 | 14 | ### Terraform Variables 15 | - `instance_type` - The [ec2 instance type](https://aws.amazon.com/ec2/instance-types/) (Defaults to `t2.small`) 16 | 17 | ### Output 18 | - `tls_private_key`: The private key to be used in order to ssh to the ec2 instance 19 | - `instance_public_ip`: The public IP of your Redash instance - Click on the URL on the Outputs tab of env0 to check it out! 20 | -------------------------------------------------------------------------------- /aws/ec2-redash/ec2.tf: -------------------------------------------------------------------------------- 1 | resource "aws_instance" "redash-instance" { 2 | ami = "ami-0c654c3ab463d22f6" 3 | instance_type = var.instance_type 4 | subnet_id = aws_subnet.redash-subnet.*.id[0] 5 | vpc_security_group_ids = [aws_security_group.redash-sg.id] 6 | key_name = aws_key_pair.redash-key-pair.key_name 7 | } 8 | -------------------------------------------------------------------------------- /aws/ec2-redash/elastic-ip.tf: -------------------------------------------------------------------------------- 1 | resource "aws_eip" "redash-elastic-ip" { 2 | instance = aws_instance.redash-instance.id 3 | vpc = true 4 | } 5 | -------------------------------------------------------------------------------- /aws/ec2-redash/key_pair.tf: -------------------------------------------------------------------------------- 1 | resource "tls_private_key" "private_key" { 2 | algorithm = "RSA" 3 | rsa_bits = 4096 4 | } 5 | 6 | resource "aws_key_pair" "redash-key-pair" { 7 | key_name = "redash-key-${random_uuid.uuid.result}" 8 | public_key = tls_private_key.private_key.public_key_openssh 9 | } 10 | -------------------------------------------------------------------------------- /aws/ec2-redash/outputs.tf: -------------------------------------------------------------------------------- 1 | output "tls_private_key" { 2 | value = tls_private_key.private_key.private_key_pem 3 | description = "The private key to be used in order to ssh to the ec2 instance" 4 | sensitive = true 5 | } 6 | 7 | output "instance_public_ip" { 8 | value = aws_eip.redash-elastic-ip.public_ip 9 | description = "The public IP of your Redash instance" 10 | } 11 | 12 | -------------------------------------------------------------------------------- /aws/ec2-redash/providers.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = var.aws_default_region 3 | } 4 | 5 | # Using these data sources allows the configuration to be 6 | # generic for any region. 7 | data "aws_region" "current" {} 8 | 9 | data "aws_availability_zones" "available" {} 10 | -------------------------------------------------------------------------------- /aws/ec2-redash/random.tf: -------------------------------------------------------------------------------- 1 | resource "random_uuid" "uuid" { } 2 | -------------------------------------------------------------------------------- /aws/ec2-redash/sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/env0/templates/80e65be109ec494bd2b4d5feefc20eb586d0b581/aws/ec2-redash/sample.png -------------------------------------------------------------------------------- /aws/ec2-redash/security_group.tf: -------------------------------------------------------------------------------- 1 | resource "aws_security_group" "redash-sg" { 2 | name = "redash-sg" 3 | description = "Redash Seciurity group" 4 | vpc_id = aws_vpc.redash-vpc.id 5 | 6 | egress { 7 | from_port = 0 8 | to_port = 0 9 | protocol = "-1" 10 | cidr_blocks = ["0.0.0.0/0"] 11 | } 12 | 13 | tags = { 14 | "Name" = "redash-sg" 15 | "CreatedBy" = "env0" 16 | } 17 | } 18 | 19 | resource "aws_security_group_rule" "redash-group-rule-for-https" { 20 | description = "Allow HTTPS connection to the redash instance" 21 | from_port = 443 22 | protocol = "tcp" 23 | security_group_id = aws_security_group.redash-sg.id 24 | to_port = 443 25 | type = "ingress" 26 | cidr_blocks = ["0.0.0.0/0"] 27 | } 28 | 29 | resource "aws_security_group_rule" "redash-group-rule-for-http" { 30 | description = "Allow HTTP connection to the redash instance" 31 | from_port = 80 32 | protocol = "tcp" 33 | security_group_id = aws_security_group.redash-sg.id 34 | to_port = 80 35 | type = "ingress" 36 | cidr_blocks = ["0.0.0.0/0"] 37 | } 38 | 39 | resource "aws_security_group_rule" "redash-group-rule-for-ssh" { 40 | description = "Allow SSH connection to the redash instance" 41 | from_port = 22 42 | protocol = "tcp" 43 | security_group_id = aws_security_group.redash-sg.id 44 | to_port = 22 45 | type = "ingress" 46 | cidr_blocks = ["0.0.0.0/0"] 47 | } 48 | -------------------------------------------------------------------------------- /aws/ec2-redash/variables.tf: -------------------------------------------------------------------------------- 1 | variable "aws_default_region" { default = "us-east-1"} 2 | variable "instance_type" { default = "t2.small"} 3 | -------------------------------------------------------------------------------- /aws/ec2-redash/vpc.tf: -------------------------------------------------------------------------------- 1 | # 2 | # VPC Resources 3 | # * VPC 4 | # * Subnets 5 | # * Internet Gateway 6 | # * Route Table 7 | # 8 | 9 | resource "aws_vpc" "redash-vpc" { 10 | cidr_block = "10.0.0.0/16" 11 | enable_dns_hostnames = true 12 | enable_dns_support = true 13 | } 14 | 15 | resource "aws_subnet" "redash-subnet" { 16 | count = 1 17 | availability_zone = data.aws_availability_zones.available.names[count.index] 18 | cidr_block = "10.0.${count.index}.0/24" 19 | vpc_id = aws_vpc.redash-vpc.id 20 | } 21 | 22 | resource "aws_internet_gateway" "redash-ig" { 23 | vpc_id = aws_vpc.redash-vpc.id 24 | } 25 | 26 | resource "aws_route_table" "redash-rt" { 27 | vpc_id = aws_vpc.redash-vpc.id 28 | 29 | route { 30 | cidr_block = "0.0.0.0/0" 31 | gateway_id = aws_internet_gateway.redash-ig.id 32 | } 33 | } 34 | 35 | resource "aws_route_table_association" "redash-rt-association" { 36 | count = 1 37 | subnet_id = aws_subnet.redash-subnet.*.id[count.index] 38 | route_table_id = aws_route_table.redash-rt.id 39 | } 40 | -------------------------------------------------------------------------------- /aws/ec2-simple/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "us-east-1" 3 | } 4 | 5 | data "aws_ami" "ubuntu" { 6 | most_recent = true 7 | 8 | filter { 9 | name = "name" 10 | values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"] 11 | } 12 | 13 | filter { 14 | name = "virtualization-type" 15 | values = ["hvm"] 16 | } 17 | 18 | owners = ["099720109477"] # Canonical 19 | } 20 | 21 | resource "aws_instance" "web" { 22 | ami = data.aws_ami.ubuntu.id 23 | instance_type = "t3.micro" 24 | 25 | tags = { 26 | Name = "EC2-Micro" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /aws/github-ee/dns.tf: -------------------------------------------------------------------------------- 1 | resource "aws_route53_record" "github-ee-record" { 2 | name = var.dns_name 3 | type = "A" 4 | zone_id = var.aws_route53_zone_id 5 | ttl = "300" 6 | records = [aws_instance.github_ee.public_ip] 7 | } 8 | -------------------------------------------------------------------------------- /aws/github-ee/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_subnet" "github_ee" { 2 | vpc_id = var.vpc_id 3 | cidr_block = var.cidr_block 4 | map_public_ip_on_launch = true 5 | availability_zone = var.availability_zone 6 | 7 | tags = { 8 | Name = "GithubEE-${var.gh_ee_version}" 9 | } 10 | } 11 | 12 | resource "aws_instance" "github_ee" { 13 | ami = var.github_ami 14 | key_name = aws_key_pair.github_ee_key.key_name 15 | instance_type = var.instance_type 16 | vpc_security_group_ids = [aws_security_group.github_ee_security_group.id] 17 | subnet_id = aws_subnet.github_ee.id 18 | associate_public_ip_address = true 19 | availability_zone = var.availability_zone 20 | 21 | ebs_block_device { 22 | device_name = "/dev/xvdf" 23 | volume_size = 150 24 | } 25 | 26 | root_block_device { 27 | volume_size = 200 28 | } 29 | 30 | tags = { 31 | Name = "GithubEE-${var.gh_ee_version}" 32 | } 33 | } 34 | 35 | 36 | 37 | resource "aws_key_pair" "github_ee_key" { 38 | key_name = "github-ee-${var.gh_ee_version}-ssh" 39 | public_key = tls_private_key.github_ee.public_key_openssh 40 | } 41 | 42 | resource "tls_private_key" "github_ee" { 43 | algorithm = "RSA" 44 | rsa_bits = 4096 45 | } 46 | -------------------------------------------------------------------------------- /aws/github-ee/security-group.tf: -------------------------------------------------------------------------------- 1 | data "aws_ip_ranges" "ec2_instance_connect_ips" { 2 | services = ["ec2_instance_connect"] 3 | } 4 | 5 | resource "aws_security_group" "github_ee_security_group" { 6 | name = "github-ee-${var.gh_ee_version}-sg" 7 | vpc_id = var.vpc_id 8 | 9 | ingress { 10 | description = "Git over SSH access. Clone, fetch, and push operations to public/private repositories supported." 11 | protocol = "tcp" 12 | from_port = 22 13 | to_port = 22 14 | cidr_blocks = ["0.0.0.0/0"] 15 | } 16 | 17 | ingress { 18 | description = "Simple Git protocol port. Clone and fetch operations to public repositories only" 19 | protocol = "tcp" 20 | from_port = 9418 21 | to_port = 9418 22 | cidr_blocks = ["0.0.0.0/0"] 23 | } 24 | 25 | ingress { 26 | description = "Web application and Git over HTTP access." 27 | protocol = "tcp" 28 | from_port = 80 29 | to_port = 80 30 | cidr_blocks = ["0.0.0.0/0"] 31 | } 32 | 33 | ingress { 34 | description = "Web application and Git over HTTPS access." 35 | protocol = "tcp" 36 | from_port = 443 37 | to_port = 443 38 | cidr_blocks = ["0.0.0.0/0"] 39 | } 40 | 41 | ingress { 42 | description = "Plain-text web based Management Console. Not required unless SSL is disabled manually." 43 | protocol = "tcp" 44 | from_port = 8080 45 | to_port = 8080 46 | cidr_blocks = ["0.0.0.0/0"] 47 | } 48 | 49 | ingress { 50 | description = "Secure web based Management Console. Required for basic installation and configuration." 51 | protocol = "tcp" 52 | from_port = 8443 53 | to_port = 8443 54 | cidr_blocks = ["0.0.0.0/0"] 55 | } 56 | 57 | // This is for enabling ec2_instance_connect for this instance 58 | // We are taking the IPs from AWS to allow them to access SSH on port 22 59 | ingress { 60 | protocol = "tcp" 61 | from_port = 122 62 | to_port = 122 63 | cidr_blocks = data.aws_ip_ranges.ec2_instance_connect_ips.cidr_blocks 64 | } 65 | 66 | ingress { 67 | protocol = "tcp" 68 | from_port = 122 69 | to_port = 122 70 | cidr_blocks = ["0.0.0.0/0"] 71 | } 72 | 73 | egress { 74 | protocol = -1 75 | from_port = 0 76 | to_port = 0 77 | cidr_blocks = ["0.0.0.0/0"] 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /aws/github-ee/variables.tf: -------------------------------------------------------------------------------- 1 | variable "aws_default_region" { 2 | default = "us-east-1" 3 | } 4 | 5 | variable "github_ami" { 6 | description = "The AMI of the github instance" 7 | } 8 | 9 | variable "instance_type" { 10 | description = "EC2 machine type" 11 | default = "r3.large" 12 | } 13 | 14 | variable "vpc_id" { 15 | description = "The vpc id for this instance" 16 | } 17 | 18 | variable "aws_route53_zone_id" { 19 | description = "Zone id for route 53 defaults to dev's" 20 | } 21 | 22 | variable "dns_name" { 23 | description = "dns for github ee" 24 | } 25 | 26 | variable "cidr_block" { 27 | description = "VPC subnet for github ee" 28 | } 29 | 30 | variable "availability_zone" { 31 | description = "Availability zone for ec2" 32 | default = "us-east-1a" 33 | } 34 | 35 | variable "gh_ee_version" { 36 | description = "prefix" 37 | } 38 | -------------------------------------------------------------------------------- /aws/hello-world/README.md: -------------------------------------------------------------------------------- 1 | # Hello World on AWS 2 | A static website S3 bucket serving an HTML greeting the user with his own custom cat imag 3 | ![](sample.png) 4 | 5 | ## Configuration 6 | 7 | ### Environment Variables 8 | - `USER` - sets the user name to greet on the html generated from `index.template.html` 9 | 10 | ### Terraform Variables 11 | None 12 | -------------------------------------------------------------------------------- /aws/hello-world/env0.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | 3 | deploy: 4 | steps: 5 | terraformInit: 6 | before: 7 | - echo Replacing !!!USER!!! with $USER in index.html 8 | - sed 's/!!!USER!!!/'"$USER"'/g' index.template.html > index.html 9 | -------------------------------------------------------------------------------- /aws/hello-world/index.template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello from env0! 6 | 7 | 8 | 37 | 38 | 39 | 40 |
41 |

Welcome to your own environment !!!USER!!!

42 | 43 | hello 44 |
45 | Powered by   46 | 47 | 49 | 50 |
51 |
52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /aws/hello-world/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | version = "~> 4.0" 3 | region = "us-east-1" 4 | } 5 | 6 | terraform { 7 | required_version = ">= 0.13" 8 | } 9 | -------------------------------------------------------------------------------- /aws/hello-world/output.tf: -------------------------------------------------------------------------------- 1 | output "url" { 2 | value = aws_s3_bucket_website_configuration.website_config.website_endpoint 3 | } 4 | -------------------------------------------------------------------------------- /aws/hello-world/s3.tf: -------------------------------------------------------------------------------- 1 | provider "random" {} 2 | 3 | resource "random_string" "random" { 4 | length = 16 5 | special = false 6 | min_lower = 16 7 | } 8 | 9 | resource "aws_s3_bucket" "website_bucket" { 10 | bucket = "hello-env0-${random_string.random.result}" 11 | force_destroy = true 12 | } 13 | 14 | resource "aws_s3_bucket_website_configuration" "website_config" { 15 | bucket = aws_s3_bucket.website_bucket.id 16 | 17 | index_document { 18 | suffix = "index.html" 19 | } 20 | 21 | error_document { 22 | key = "index.html" 23 | } 24 | } 25 | 26 | resource "aws_s3_bucket_ownership_controls" "bucket_ownership" { 27 | bucket = aws_s3_bucket.website_bucket.id 28 | rule { 29 | object_ownership = "BucketOwnerPreferred" 30 | } 31 | } 32 | 33 | resource "aws_s3_bucket_public_access_block" "bucket_public_access_block" { 34 | bucket = aws_s3_bucket.website_bucket.id 35 | 36 | block_public_acls = false 37 | block_public_policy = false 38 | ignore_public_acls = false 39 | restrict_public_buckets = false 40 | } 41 | 42 | # Adding delay because PutBucketPolicy API below can fail due to race condition with the removal of public access block 43 | # This is a recommendation by AWS support :( 44 | resource "null_resource" "delay" { 45 | depends_on = [ 46 | aws_s3_bucket_ownership_controls.bucket_ownership, 47 | aws_s3_bucket_public_access_block.bucket_public_access_block 48 | ] 49 | 50 | provisioner "local-exec" { 51 | command = "sleep 5" 52 | } 53 | } 54 | 55 | resource "aws_s3_bucket_policy" "website_bucket_policy" { 56 | bucket = aws_s3_bucket.website_bucket.id 57 | depends_on = [ 58 | null_resource.delay 59 | ] 60 | 61 | policy = jsonencode({ 62 | Version = "2012-10-17" 63 | Statement = [ 64 | { 65 | Sid = "Allow-Public-Access-To-Bucket" 66 | Effect = "Allow" 67 | Principal = "*" 68 | Action = "s3:GetObject" 69 | Resource = [ 70 | "arn:aws:s3:::${aws_s3_bucket.website_bucket.bucket}/*" 71 | ] 72 | }, 73 | ] 74 | }) 75 | } 76 | 77 | resource "aws_s3_object" "object" { 78 | bucket = aws_s3_bucket.website_bucket.bucket 79 | key = "index.html" 80 | source = "index.html" 81 | content_type = "text/html" 82 | } 83 | -------------------------------------------------------------------------------- /aws/hello-world/sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/env0/templates/80e65be109ec494bd2b4d5feefc20eb586d0b581/aws/hello-world/sample.png -------------------------------------------------------------------------------- /aws/iam/env0-cost-estimation-role/README.md: -------------------------------------------------------------------------------- 1 | # env0 Cost Estimation IAM Role Template 2 | 3 | This template creates the IAM role and policy as described in the [How to Setup AWS Costs with env0](https://docs.env0.com/docs/aws-costs) documentation. 4 | The outputs include the role ARN and External Id for use in configuring the credential in env0. 5 | 6 | ## Setup 7 | 8 | Once you've completed the [Getting Started with env0](https://docs.env0.com/docs/getting-started) onboarding process, having connected your VCS and AWS, you can either set this up as a [template](https://docs.env0.com/docs/create-your-first-template) (recommended) to simplify launching new projects (Eg. Dev, Stag, Prod) in the future, or launch it in a [new environment](https://docs.env0.com/docs/setting-up-a-new-environment) (Stack). 9 | (Please env0, correct your terminology to align with the tech industry... Docs are so hard.) 10 | 11 | Once the stack has completed, view the outputs to access the IAM Role ARN and External Id when [adding a new Cost Credential](https://docs.env0.com/docs/aws-costs#add-credentials-to-your-organization) in env0. 12 | 13 | -------------------------------------------------------------------------------- /aws/iam/env0-cost-estimation-role/data.tf: -------------------------------------------------------------------------------- 1 | data "aws_caller_identity" "current" {} 2 | -------------------------------------------------------------------------------- /aws/iam/env0-cost-estimation-role/env0-cost.tf: -------------------------------------------------------------------------------- 1 | resource "random_string" "external_id" { 2 | length = 32 3 | upper = true 4 | min_upper = 1 5 | lower = true 6 | min_lower = 1 7 | numeric = true 8 | min_numeric = 1 9 | special = false 10 | } 11 | 12 | 13 | resource "aws_iam_policy" "env0_cost" { 14 | name = "env0_cost" 15 | path = "/" 16 | description = "env0_cost" 17 | 18 | policy = < tf-plan.json 12 | - ./opa eval --fail-defined "data.terraform.validation.violations[msg]" --input tf-plan.json --data ./tf-lib.rego --data ./validation.rego --format values 1>&2 13 | 14 | -------------------------------------------------------------------------------- /aws/opa-example/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.12" 3 | } 4 | 5 | provider "aws" { 6 | version = "~> 2.8" 7 | region = "us-east-1" 8 | } 9 | 10 | variable "ssh_cidr_block" { 11 | default = "0.0.0.0/0" 12 | } 13 | 14 | resource "aws_security_group" "allow_ssh" { 15 | name = "my_security_group" 16 | description = "Allow SSH Trafic" 17 | 18 | ingress { 19 | description = "Incoming ssh" 20 | from_port = 22 21 | to_port = 22 22 | protocol = "tcp" 23 | cidr_blocks = [var.ssh_cidr_block] 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /aws/opa-example/tf-lib.rego: -------------------------------------------------------------------------------- 1 | package terraform.library 2 | 3 | # Rego utils to work with Terraform 4 | # Copied from https://www.openpolicyagent.org/docs/latest/terraform/#working-with-modules 5 | 6 | resources := { r | 7 | some path, value 8 | 9 | # Walk over the JSON tree and check if the node we are 10 | # currently on is a module (either root or child) resources 11 | # value. 12 | walk(input.planned_values, [path, value]) 13 | 14 | # Look for resources in the current value based on path 15 | rs := module_resources(path, value) 16 | 17 | # Aggregate them into `resources` 18 | r := rs[_] 19 | } 20 | 21 | # Variant to match root_module resources 22 | module_resources(path, value) = rs { 23 | 24 | # Expect something like: 25 | # 26 | # { 27 | # "root_module": { 28 | # "resources": [...], 29 | # ... 30 | # } 31 | # ... 32 | # } 33 | # 34 | # Where the path is [..., "root_module", "resources"] 35 | 36 | reverse_index(path, 1) == "resources" 37 | reverse_index(path, 2) == "root_module" 38 | rs := value 39 | } 40 | 41 | # Variant to match child_modules resources 42 | module_resources(path, value) = rs { 43 | 44 | # Expect something like: 45 | # 46 | # { 47 | # ... 48 | # "child_modules": [ 49 | # { 50 | # "resources": [...], 51 | # ... 52 | # }, 53 | # ... 54 | # ] 55 | # ... 56 | # } 57 | # 58 | # Where the path is [..., "child_modules", 0, "resources"] 59 | # Note that there will always be an index int between `child_modules` 60 | # and `resources`. We know that walk will only visit each one once, 61 | # so we shouldn't need to keep track of what the index is. 62 | 63 | reverse_index(path, 1) == "resources" 64 | reverse_index(path, 3) == "child_modules" 65 | rs := value 66 | } 67 | 68 | reverse_index(path, idx) = value { 69 | value := path[count(path) - idx] 70 | } 71 | 72 | list_contains_value(list, item) { 73 | list_item = list[_] 74 | list_item == item 75 | } 76 | -------------------------------------------------------------------------------- /aws/opa-example/validation.rego: -------------------------------------------------------------------------------- 1 | package terraform.validation 2 | 3 | import data.terraform.library as lib 4 | 5 | default allow = false 6 | 7 | violations[msg] { 8 | no_open_cidr_blocks[msg] 9 | } 10 | 11 | no_open_cidr_blocks[msg] { 12 | open_cidr := "0.0.0.0/0" 13 | cidr_blocks := lib.resources[r].values.ingress[x].cidr_blocks 14 | lib.list_contains_value(cidr_blocks, open_cidr) 15 | msg = sprintf("No security groups should be open to all IP addresses. Resource in violation: %v",[r.address]) 16 | } 17 | 18 | allow { 19 | count(violations) == 0 20 | } 21 | -------------------------------------------------------------------------------- /aws/profile/README.md: -------------------------------------------------------------------------------- 1 | # Description 2 | 3 | This template demonstrates how to use custom profiles for a remote backend, and have the terraform plan and apply run with different credentials. 4 | [Profile is ignored when using AWS_ACCESS_KEY_ID](https://github.com/hashicorp/terraform-provider-aws/issues/10698). Also, using `AWS_PROFILE` is impossible before actually defining the profile. 5 | Therefore, the nicest way to accomplish this would be to dynamically define two profiles: 6 | 1. custom-profile - the profile that will run the backend 7 | 2. default - the profile that will run the plans and applies 8 | 9 | # Prerequisites 10 | 11 | 1. Make sure the backend bucket already exists in the custom profile's account 12 | 2. Replace `PROFILE_AWS_REGION`, `PROFILE_AWS_KEY`, `PROFILE_AWS_SECRET` with the credentials for the custom profile. 13 | 3. Replace `DEFAULT_AWS_REGION`, `DEFAULT_AWS_KEY`, `DEFAULT_AWS_SECRET` with the credentials that should run the plan and apply. -------------------------------------------------------------------------------- /aws/profile/env0.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | 3 | deploy: 4 | steps: 5 | setupVariables: 6 | after: 7 | # The custom-profile will be used for the remote backend 8 | - aws configure set region $PROFILE_AWS_REGION --profile custom-profile 9 | - aws configure set aws_access_key_id $PROFILE_AWS_KEY --profile custom-profile 10 | - aws configure set aws_secret_access_key $PROFILE_AWS_SECRET --profile custom-profile 11 | # We create a default profile so that it could be used for the terraform plan/apply 12 | - aws configure set region $DEFAULT_AWS_REGION --profile default 13 | - aws configure set aws_access_key_id $DEFAULT_AWS_KEY --profile default 14 | - aws configure set aws_secret_access_key $DEFAULT_AWS_SECRET --profile default 15 | -------------------------------------------------------------------------------- /aws/profile/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | backend "s3" { 3 | bucket = "bucket-in-custom-profile" 4 | key = "profile-state" 5 | region = "us-east-1" 6 | profile = "custom-profile" 7 | } 8 | } 9 | 10 | resource "aws_s3_bucket" "bucket" { 11 | bucket = "bucket-in-default-profile" 12 | acl = "private" 13 | } 14 | -------------------------------------------------------------------------------- /aws/s3-bucket/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello from env0! 6 | 7 | 8 | 37 | 38 | 39 | 40 |
41 |

Welcome to your own environment

42 | 43 | S3 44 |
45 | Powered by   46 | 47 | 49 | 50 |
51 |
52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /aws/s3-bucket/s3/output.tf: -------------------------------------------------------------------------------- 1 | output "url" { 2 | value = "${aws_s3_bucket.website_bucket.bucket_domain_name}" 3 | } 4 | -------------------------------------------------------------------------------- /aws/s3-bucket/s3/s3.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | version = "~> 4.0" 3 | region = "us-east-1" 4 | } 5 | 6 | provider "random" {} 7 | 8 | resource "random_string" "random" { 9 | length = "16" 10 | special = "false" 11 | min_lower = "16" 12 | } 13 | 14 | resource "aws_s3_bucket" "website_bucket" { 15 | bucket = "env0-s3-${random_string.random.result}" 16 | force_destroy = true 17 | } 18 | 19 | resource "aws_s3_bucket_ownership_controls" "bucket_ownership" { 20 | bucket = aws_s3_bucket.website_bucket.id 21 | rule { 22 | object_ownership = "BucketOwnerPreferred" 23 | } 24 | } 25 | 26 | resource "aws_s3_bucket_public_access_block" "bucket_public_access_block" { 27 | bucket = aws_s3_bucket.website_bucket.id 28 | 29 | block_public_acls = false 30 | block_public_policy = false 31 | ignore_public_acls = false 32 | restrict_public_buckets = false 33 | } 34 | 35 | # Delay before PutBucketPolicy due to API race condition 36 | resource "null_resource" "delay" { 37 | depends_on = [ 38 | aws_s3_bucket_ownership_controls.bucket_ownership, 39 | aws_s3_bucket_public_access_block.bucket_public_access_block 40 | ] 41 | 42 | provisioner "local-exec" { 43 | command = "sleep 5" 44 | } 45 | } 46 | 47 | resource "aws_s3_bucket_policy" "bucket_policy" { 48 | bucket = aws_s3_bucket.website_bucket.id 49 | depends_on = [null_resource.delay] 50 | 51 | policy = <&2 && exit 1; fi 8 | onSuccess: 9 | - echo Replacing !!!USER!!! with $USER in index.html 10 | - sed 's/!!!USER!!!/'"$USER"'/g' index.template.html > index.html 11 | - awsv2 s3 cp index.html s3://$(aws cloudformation describe-stacks --output text --query "Stacks[].Outputs[?OutputKey=='BucketName'].OutputValue" --stack-name ${ENV0_WORKSPACE_NAME})/ 12 | - 'echo "Site is available at: $(aws cloudformation describe-stacks --output text --query "Stacks[].Outputs[?OutputKey==''BucketUrl''].OutputValue" --stack-name ${ENV0_WORKSPACE_NAME})"' 13 | 14 | destroy: 15 | steps: 16 | setupVariables: 17 | after: 18 | - if [ -z "$AWS_DEFAULT_REGION" ]; then echo "AWS_DEFAULT_REGION must be provided" 1>&2 && exit 1; fi 19 | - echo emptying out the bucket before deleting the stack 20 | - awsv2 s3 rm s3://$(aws cloudformation describe-stacks --output text --query "Stacks[].Outputs[?OutputKey=='BucketName'].OutputValue" --stack-name ${ENV0_WORKSPACE_NAME})/ --recursive 21 | -------------------------------------------------------------------------------- /cloudformation/hello-world/index.template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello from env0! 6 | 7 | 8 | 37 | 38 | 39 | 40 |
41 |

Welcome to your own environment !!!USER!!!

42 | 43 | hello 44 |
45 | Powered by   46 | 47 | 49 | 50 |
51 |
52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /cloudformation/hello-world/sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/env0/templates/80e65be109ec494bd2b4d5feefc20eb586d0b581/cloudformation/hello-world/sample.png -------------------------------------------------------------------------------- /cloudformation/hello-world/stack.yaml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: '2010-09-09' 2 | Resources: 3 | WebsiteBucket: 4 | Type: 'AWS::S3::Bucket' 5 | Properties: 6 | BucketName: !Join ['', ['website-bucket-cf-', !Select [2, !Split ['/', !Ref AWS::StackId]]]] 7 | PublicAccessBlockConfiguration: 8 | BlockPublicAcls: false 9 | BlockPublicPolicy: false 10 | IgnorePublicAcls: false 11 | RestrictPublicBuckets: false 12 | OwnershipControls: 13 | Rules: 14 | - ObjectOwnership: BucketOwnerPreferred 15 | WebsiteConfiguration: 16 | IndexDocument: index.html 17 | ErrorDocument: index.html 18 | WebsiteBucketPolicy: 19 | Type: 'AWS::S3::BucketPolicy' 20 | Properties: 21 | Bucket: !Ref WebsiteBucket 22 | PolicyDocument: 23 | Version: '2012-10-17' 24 | Statement: 25 | - Sid: Allow-Public-Access-To-Bucket 26 | Effect: Allow 27 | Principal: 28 | AWS: '*' 29 | Action: 30 | - s3:GetObject 31 | Resource: 32 | - !Join ['', ['arn:aws:s3:::', !Ref WebsiteBucket, '/*']] 33 | Outputs: 34 | BucketName: 35 | Value: !Ref WebsiteBucket 36 | Description: 'The name of the S3 bucket' 37 | BucketUrl: 38 | Value: !GetAtt WebsiteBucket.WebsiteURL 39 | Description: 'URL of the S3 bucket' 40 | -------------------------------------------------------------------------------- /community-providers/pingdom/README.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | This is a simple example on how to fetch `pingdom` terraform community provider using [env0 Custom Flows](https://docs.env0.com/docs/custom-flows) on **terraform v11 or v12**. 3 | > Note: For terraform v13 please refer to [terraform's official documentation](https://www.terraform.io/upgrade-guides/0-13.html#explicit-provider-source-locations) on how to specify community providers. 4 | 5 | ## Steps 6 | What we basically do in `env0.yml` file is: 7 | 1. Create the relevant `terraform.d` folder under the user's home folder (env0's runtime uses a dockerized `alpine` image, hence `os_arch` is `linux_amd64`). 8 | 2. Download the static artifact file of the `pingdom` community provider from github. 9 | 3. Allow execution permissions for the file so `terraform` can use it. 10 | 11 | > Note: Please pay attention that custom flow needs to be done before `terraform init` and in both `deploy` and `destroy` actions. 12 | -------------------------------------------------------------------------------- /community-providers/pingdom/env0.yml: -------------------------------------------------------------------------------- 1 | deploy: 2 | steps: 3 | terraformInit: 4 | before: 5 | - mkdir -p $HOME/.terraform.d/plugins/linux_amd64 6 | - wget https://github.com/russellcardullo/terraform-provider-pingdom/releases/download/v1.1.1/terraform-provider-pingdom_v1.1.1_linux_amd64_static -O $HOME/.terraform.d/plugins/linux_amd64/terraform-provider-pingdom_v1.1.1 7 | - chmod +x $HOME/.terraform.d/plugins/linux_amd64/terraform-provider-pingdom_v1.1.1 8 | destroy: 9 | steps: 10 | terraformInit: 11 | before: 12 | - mkdir -p $HOME/.terraform.d/plugins/linux_amd64 13 | - wget https://github.com/russellcardullo/terraform-provider-pingdom/releases/download/v1.1.1/terraform-provider-pingdom_v1.1.1_linux_amd64_static -O $HOME/.terraform.d/plugins/linux_amd64/terraform-provider-pingdom_v1.1.1 14 | - chmod +x $HOME/.terraform.d/plugins/linux_amd64/terraform-provider-pingdom_v1.1.1 15 | -------------------------------------------------------------------------------- /community-providers/pingdom/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.11.0" 3 | } 4 | 5 | provider "pingdom" { 6 | user = "user" 7 | password = "password" 8 | api_key = "dummy" 9 | } 10 | 11 | resource "pingdom_team" "rd" { 12 | name = "R&D" 13 | } 14 | 15 | resource "pingdom_user" "manager" { 16 | username = "Manager Cohen" 17 | } 18 | 19 | resource "pingdom_contact" "manager_contact" { 20 | user_id = pingdom_user.manager.id 21 | email = "john@doe.com" 22 | severity_level = "HIGH" 23 | } 24 | -------------------------------------------------------------------------------- /custom-flows/external-script.yaml: -------------------------------------------------------------------------------- 1 | version: 1 2 | 3 | deploy: 4 | steps: 5 | setupVariables: 6 | after: 7 | - git clone https://$ENV0_VCS_ACCESS_TOKEN@github.com/env0/templates.git external-repo 8 | 9 | terraformPlan: 10 | before: 11 | - ./external-repo/custom-flows/scripts/script.sh 12 | -------------------------------------------------------------------------------- /custom-flows/opa-polices/null-resource.rego: -------------------------------------------------------------------------------- 1 | package resource.limit 2 | 3 | import input as tfplan 4 | 5 | default allow := false 6 | 7 | allow := true { 8 | score < 2 9 | } 10 | 11 | # Consider exactly these resource types in calculations 12 | resource_types := {"null_resource"} 13 | 14 | score := s { 15 | all := [ x | 16 | some resource_type 17 | new := num_creates[resource_type]; 18 | mod := num_modifies[resource_type]; 19 | x := new + mod 20 | ] 21 | s := sum(all) 22 | } 23 | 24 | #################### 25 | # Terraform Library 26 | #################### 27 | 28 | # list of all resources of a given type 29 | resources[resource_type] := all { 30 | some resource_type 31 | resource_types[resource_type] 32 | all := [name | 33 | name:= tfplan.resource_changes[_] 34 | name.type == resource_type 35 | ] 36 | } 37 | 38 | # number of creations of resources of a given type 39 | num_creates[resource_type] := num { 40 | some resource_type 41 | resource_types[resource_type] 42 | all := resources[resource_type] 43 | creates := [res | res:= all[_]; res.change.actions[_] == "create"] 44 | num := count(creates) 45 | } 46 | 47 | # number of modifications to resources of a given type 48 | num_modifies[resource_type] := num { 49 | some resource_type 50 | resource_types[resource_type] 51 | all := resources[resource_type] 52 | modifies := [res | res:= all[_]; res.change.actions[_] == "update"] 53 | num := count(modifies) 54 | } 55 | -------------------------------------------------------------------------------- /custom-flows/opa.yaml: -------------------------------------------------------------------------------- 1 | version: 1 2 | 3 | deploy: 4 | steps: 5 | setupVariables: 6 | after: 7 | - curl -L -o opa https://openpolicyagent.org/downloads/v0.46.1/opa_linux_amd64_static 8 | - chmod 755 ./opa 9 | - git clone https://$ENV0_VCS_ACCESS_TOKEN@github.com/env0/templates.git external-repo 10 | 11 | terraformPlan: 12 | after: 13 | - terraform show -json .tf-plan >> tfplan.json 14 | - ./opa eval --format pretty -i tfplan.json -d ./external-repo/custom-flows/opa-polices/null-resource.rego --fail "data.resource.limit.allow = true" 15 | -------------------------------------------------------------------------------- /custom-flows/scripts/script.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo Hello! Hi I am a script from another world 4 | ls -al . 5 | -------------------------------------------------------------------------------- /gcp/bq-dataset/README.md: -------------------------------------------------------------------------------- 1 | This TF needs two Environment variables 2 | 3 | - `GOOGLE_CREDENTIALS` - You need to download a JSON [service-account key](https://cloud.google.com/iam/docs/creating-managing-service-account-keys#creating_service_account_keys), and copy paste that 4 | - `GOOGLE_PROJECT` - The name of the GCP project. 5 | -------------------------------------------------------------------------------- /gcp/bq-dataset/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = "=0.14.11" 3 | } 4 | 5 | resource "random_id" "id" { 6 | byte_length = 8 7 | } 8 | 9 | resource "google_bigquery_dataset" "dataset" { 10 | dataset_id = "env0_test_${random_id.id.dec}" 11 | } 12 | -------------------------------------------------------------------------------- /gcp/container-cluster/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | backend "gcs" { 3 | bucket = "env0-gcp-backend-state-bucket" 4 | prefix = "container_cluster_states" 5 | } 6 | } 7 | 8 | # Copied from https://www.terraform.io/docs/providers/google/r/container_node_pool.html 9 | 10 | resource "google_container_cluster" "primary" { 11 | name = "my-gke-cluster" 12 | location = "us-central1" 13 | 14 | # We can't create a cluster with no node pool defined, but we want to only use 15 | # separately managed node pools. So we create the smallest possible default 16 | # node pool and immediately delete it. 17 | remove_default_node_pool = true 18 | initial_node_count = 1 19 | 20 | resource_labels = { 21 | my_label_1 = "label-1" 22 | my_label_1a = "label-1a" 23 | } 24 | } 25 | 26 | resource "google_container_node_pool" "primary_preemptible_nodes" { 27 | name = "my-node-pool" 28 | location = "us-central1" 29 | cluster = google_container_cluster.primary.name 30 | node_count = 1 31 | 32 | node_config { 33 | preemptible = true 34 | machine_type = "n1-standard-1" 35 | 36 | oauth_scopes = [ 37 | "https://www.googleapis.com/auth/logging.write", 38 | "https://www.googleapis.com/auth/monitoring", 39 | ] 40 | 41 | labels = { 42 | my_label_2 = "label-2" 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /gcp/service-account-key/README.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | This terraform template creates a GCP [service account](https://cloud.google.com/iam/docs/service-accounts#what_are_service_accounts) under your project and configures & exports a JSON key for that account 3 | 4 | ## Required environment variables: 5 | 6 | - `GOOGLE_CREDENTIALS` - You need to download a JSON [service-account key](https://cloud.google.com/iam/docs/creating-managing-service-account-keys#creating_service_account_keys), and copy paste that 7 | - `GOOGLE_PROJECT` - The name of the GCP project. 8 | 9 | ## Relevant Outputs: 10 | - `public key` - The public key, base64 encoded 11 | - `private_key` - The private key in JSON format, base64 encoded. 12 | 13 | 14 | For additional info, please visit terraform's [official docs](https://www.terraform.io/docs/providers/google/r/google_service_account_key.html). -------------------------------------------------------------------------------- /gcp/service-account-key/mainf.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">=0.12.3" 3 | } 4 | 5 | provider "google" { 6 | version = ">=3.0.0" 7 | project = var.project 8 | } 9 | 10 | resource "google_service_account" "account" { 11 | account_id = var.account_id 12 | display_name = var.account_display_name 13 | } 14 | 15 | resource "google_service_account_key" "key" { 16 | service_account_id = google_service_account.account.name 17 | public_key_type = "TYPE_X509_PEM_FILE" 18 | } -------------------------------------------------------------------------------- /gcp/service-account-key/variables.tf: -------------------------------------------------------------------------------- 1 | variable "account_id" { 2 | type = string 3 | description = "The id of the service account that will be created" 4 | } 5 | 6 | variable "account_display_name" { 7 | type = string 8 | description = "The display name of the service account that will be created" 9 | } 10 | 11 | variable "project" { 12 | type = string 13 | description = "The GCP project id" 14 | } -------------------------------------------------------------------------------- /helm/dummy/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /helm/dummy/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: dummy 3 | description: A Helm chart for Kubernetes 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "1.16.0" 25 | -------------------------------------------------------------------------------- /helm/dummy/README.md: -------------------------------------------------------------------------------- 1 | # Helm Dummy Chart 2 | 3 | This dummy chart contains the k8s resources that requires for creating a working Nginx web server. 4 | 5 | ### Connect to your K8s cluster in env0 6 | 7 | In order to apply this chart as an env0 [Helm template](https://docs.env0.com/docs/helm), you'll have to first connect to your cluster in env0. 8 | It can be easily done by following our [Kubernetes integration guide](https://docs.env0.com/docs/connect-your-cloud-account#kubernetes). -------------------------------------------------------------------------------- /helm/dummy/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | 1. Get the application URL by running these commands: 2 | {{- if .Values.ingress.enabled }} 3 | {{- range $host := .Values.ingress.hosts }} 4 | {{- range .paths }} 5 | http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} 6 | {{- end }} 7 | {{- end }} 8 | {{- else if contains "NodePort" .Values.service.type }} 9 | export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "dummy.fullname" . }}) 10 | export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") 11 | echo http://$NODE_IP:$NODE_PORT 12 | {{- else if contains "LoadBalancer" .Values.service.type }} 13 | NOTE: It may take a few minutes for the LoadBalancer IP to be available. 14 | You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "dummy.fullname" . }}' 15 | export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "dummy.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") 16 | echo http://$SERVICE_IP:{{ .Values.service.port }} 17 | {{- else if contains "ClusterIP" .Values.service.type }} 18 | export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "dummy.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") 19 | export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") 20 | echo "Visit http://127.0.0.1:8080 to use your application" 21 | kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT 22 | {{- end }} 23 | -------------------------------------------------------------------------------- /helm/dummy/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Expand the name of the chart. 3 | */}} 4 | {{- define "dummy.name" -}} 5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 6 | {{- end }} 7 | 8 | {{/* 9 | Create a default fully qualified app name. 10 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 11 | If release name contains chart name it will be used as a full name. 12 | */}} 13 | {{- define "dummy.fullname" -}} 14 | {{- if .Values.fullnameOverride }} 15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 16 | {{- else }} 17 | {{- $name := default .Chart.Name .Values.nameOverride }} 18 | {{- if contains $name .Release.Name }} 19 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 20 | {{- else }} 21 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 22 | {{- end }} 23 | {{- end }} 24 | {{- end }} 25 | 26 | {{/* 27 | Create chart name and version as used by the chart label. 28 | */}} 29 | {{- define "dummy.chart" -}} 30 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 31 | {{- end }} 32 | 33 | {{/* 34 | Common labels 35 | */}} 36 | {{- define "dummy.labels" -}} 37 | helm.sh/chart: {{ include "dummy.chart" . }} 38 | {{ include "dummy.selectorLabels" . }} 39 | {{- if .Chart.AppVersion }} 40 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 41 | {{- end }} 42 | app.kubernetes.io/managed-by: {{ .Release.Service }} 43 | {{- end }} 44 | 45 | {{/* 46 | Selector labels 47 | */}} 48 | {{- define "dummy.selectorLabels" -}} 49 | app.kubernetes.io/name: {{ include "dummy.name" . }} 50 | app.kubernetes.io/instance: {{ .Release.Name }} 51 | {{- end }} 52 | 53 | {{/* 54 | Create the name of the service account to use 55 | */}} 56 | {{- define "dummy.serviceAccountName" -}} 57 | {{- if .Values.serviceAccount.create }} 58 | {{- default (include "dummy.fullname" .) .Values.serviceAccount.name }} 59 | {{- else }} 60 | {{- default "default" .Values.serviceAccount.name }} 61 | {{- end }} 62 | {{- end }} 63 | -------------------------------------------------------------------------------- /helm/dummy/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ include "dummy.fullname" . }} 5 | labels: 6 | {{- include "dummy.labels" . | nindent 4 }} 7 | spec: 8 | {{- if not .Values.autoscaling.enabled }} 9 | replicas: {{ .Values.replicaCount }} 10 | {{- end }} 11 | selector: 12 | matchLabels: 13 | {{- include "dummy.selectorLabels" . | nindent 6 }} 14 | template: 15 | metadata: 16 | {{- with .Values.podAnnotations }} 17 | annotations: 18 | {{- toYaml . | nindent 8 }} 19 | {{- end }} 20 | labels: 21 | {{- include "dummy.selectorLabels" . | nindent 8 }} 22 | spec: 23 | {{- with .Values.imagePullSecrets }} 24 | imagePullSecrets: 25 | {{- toYaml . | nindent 8 }} 26 | {{- end }} 27 | serviceAccountName: {{ include "dummy.serviceAccountName" . }} 28 | securityContext: 29 | {{- toYaml .Values.podSecurityContext | nindent 8 }} 30 | containers: 31 | - name: {{ .Chart.Name }} 32 | securityContext: 33 | {{- toYaml .Values.securityContext | nindent 12 }} 34 | image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" 35 | imagePullPolicy: {{ .Values.image.pullPolicy }} 36 | ports: 37 | - name: http 38 | containerPort: 80 39 | protocol: TCP 40 | livenessProbe: 41 | httpGet: 42 | path: / 43 | port: http 44 | readinessProbe: 45 | httpGet: 46 | path: / 47 | port: http 48 | resources: 49 | {{- toYaml .Values.resources | nindent 12 }} 50 | {{- with .Values.nodeSelector }} 51 | nodeSelector: 52 | {{- toYaml . | nindent 8 }} 53 | {{- end }} 54 | {{- with .Values.affinity }} 55 | affinity: 56 | {{- toYaml . | nindent 8 }} 57 | {{- end }} 58 | {{- with .Values.tolerations }} 59 | tolerations: 60 | {{- toYaml . | nindent 8 }} 61 | {{- end }} 62 | -------------------------------------------------------------------------------- /helm/dummy/templates/hpa.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.autoscaling.enabled }} 2 | apiVersion: autoscaling/v2beta1 3 | kind: HorizontalPodAutoscaler 4 | metadata: 5 | name: {{ include "dummy.fullname" . }} 6 | labels: 7 | {{- include "dummy.labels" . | nindent 4 }} 8 | spec: 9 | scaleTargetRef: 10 | apiVersion: apps/v1 11 | kind: Deployment 12 | name: {{ include "dummy.fullname" . }} 13 | minReplicas: {{ .Values.autoscaling.minReplicas }} 14 | maxReplicas: {{ .Values.autoscaling.maxReplicas }} 15 | metrics: 16 | {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} 17 | - type: Resource 18 | resource: 19 | name: cpu 20 | targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} 21 | {{- end }} 22 | {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} 23 | - type: Resource 24 | resource: 25 | name: memory 26 | targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} 27 | {{- end }} 28 | {{- end }} 29 | -------------------------------------------------------------------------------- /helm/dummy/templates/ingress.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.ingress.enabled -}} 2 | {{- $fullName := include "dummy.fullname" . -}} 3 | {{- $svcPort := .Values.service.port -}} 4 | {{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} 5 | {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} 6 | {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} 7 | {{- end }} 8 | {{- end }} 9 | {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} 10 | apiVersion: networking.k8s.io/v1 11 | {{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} 12 | apiVersion: networking.k8s.io/v1beta1 13 | {{- else -}} 14 | apiVersion: extensions/v1beta1 15 | {{- end }} 16 | kind: Ingress 17 | metadata: 18 | name: {{ $fullName }} 19 | labels: 20 | {{- include "dummy.labels" . | nindent 4 }} 21 | {{- with .Values.ingress.annotations }} 22 | annotations: 23 | {{- toYaml . | nindent 4 }} 24 | {{- end }} 25 | spec: 26 | {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} 27 | ingressClassName: {{ .Values.ingress.className }} 28 | {{- end }} 29 | {{- if .Values.ingress.tls }} 30 | tls: 31 | {{- range .Values.ingress.tls }} 32 | - hosts: 33 | {{- range .hosts }} 34 | - {{ . | quote }} 35 | {{- end }} 36 | secretName: {{ .secretName }} 37 | {{- end }} 38 | {{- end }} 39 | rules: 40 | {{- range .Values.ingress.hosts }} 41 | - host: {{ .host | quote }} 42 | http: 43 | paths: 44 | {{- range .paths }} 45 | - path: {{ .path }} 46 | {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} 47 | pathType: {{ .pathType }} 48 | {{- end }} 49 | backend: 50 | {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} 51 | service: 52 | name: {{ $fullName }} 53 | port: 54 | number: {{ $svcPort }} 55 | {{- else }} 56 | serviceName: {{ $fullName }} 57 | servicePort: {{ $svcPort }} 58 | {{- end }} 59 | {{- end }} 60 | {{- end }} 61 | {{- end }} 62 | -------------------------------------------------------------------------------- /helm/dummy/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "dummy.fullname" . }} 5 | labels: 6 | {{- include "dummy.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: {{ .Values.service.port }} 11 | targetPort: http 12 | protocol: TCP 13 | name: http 14 | selector: 15 | {{- include "dummy.selectorLabels" . | nindent 4 }} 16 | -------------------------------------------------------------------------------- /helm/dummy/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "dummy.serviceAccountName" . }} 6 | labels: 7 | {{- include "dummy.labels" . | nindent 4 }} 8 | {{- with .Values.serviceAccount.annotations }} 9 | annotations: 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | {{- end }} 13 | -------------------------------------------------------------------------------- /helm/dummy/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "dummy.fullname" . }}-test-connection" 5 | labels: 6 | {{- include "dummy.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test 9 | spec: 10 | containers: 11 | - name: wget 12 | image: busybox 13 | command: ['wget'] 14 | args: ['{{ include "dummy.fullname" . }}:{{ .Values.service.port }}'] 15 | restartPolicy: Never 16 | -------------------------------------------------------------------------------- /helm/dummy/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for dummy. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | 5 | replicaCount: 1 6 | 7 | image: 8 | repository: nginx 9 | pullPolicy: IfNotPresent 10 | # Overrides the image tag whose default is the chart appVersion. 11 | tag: "" 12 | 13 | imagePullSecrets: [] 14 | nameOverride: "dummy" 15 | fullnameOverride: "dummy-chart" 16 | 17 | serviceAccount: 18 | # Specifies whether a service account should be created 19 | create: true 20 | # Annotations to add to the service account 21 | annotations: {} 22 | # The name of the service account to use. 23 | # If not set and create is true, a name is generated using the fullname template 24 | name: "" 25 | 26 | podAnnotations: {} 27 | 28 | podSecurityContext: {} 29 | # fsGroup: 2000 30 | 31 | securityContext: {} 32 | # capabilities: 33 | # drop: 34 | # - ALL 35 | # readOnlyRootFilesystem: true 36 | # runAsNonRoot: true 37 | # runAsUser: 1000 38 | 39 | service: 40 | type: ClusterIP 41 | port: 80 42 | 43 | ingress: 44 | enabled: false 45 | className: "" 46 | annotations: {} 47 | # kubernetes.io/ingress.class: nginx 48 | # kubernetes.io/tls-acme: "true" 49 | hosts: 50 | - host: chart-example.local 51 | paths: 52 | - path: / 53 | pathType: ImplementationSpecific 54 | tls: [] 55 | # - secretName: chart-example-tls 56 | # hosts: 57 | # - chart-example.local 58 | 59 | resources: {} 60 | # We usually recommend not to specify default resources and to leave this as a conscious 61 | # choice for the user. This also increases chances charts run on environments with little 62 | # resources, such as Minikube. If you do want to specify resources, uncomment the following 63 | # lines, adjust them as necessary, and remove the curly braces after 'resources:'. 64 | # limits: 65 | # cpu: 100m 66 | # memory: 128Mi 67 | # requests: 68 | # cpu: 100m 69 | # memory: 128Mi 70 | 71 | autoscaling: 72 | enabled: false 73 | minReplicas: 1 74 | maxReplicas: 100 75 | targetCPUUtilizationPercentage: 80 76 | # targetMemoryUtilizationPercentage: 80 77 | 78 | nodeSelector: {} 79 | 80 | tolerations: [] 81 | 82 | affinity: {} 83 | -------------------------------------------------------------------------------- /ibm/bare-metal/main.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/env0/templates/80e65be109ec494bd2b4d5feefc20eb586d0b581/ibm/bare-metal/main.tf -------------------------------------------------------------------------------- /kubernetes/hello-world/README.md: -------------------------------------------------------------------------------- 1 | # Kubernetes Hello World 2 | 3 | Create a simple k8s namespace resource with a dynamic name using [env0 custom flow](https://docs.env0.com/docs/custom-flows). 4 | 5 | ### Connect to your K8s cluster in env0 6 | In order to apply this resource as an env0 [K8s template](https://docs.env0.com/docs/k8s), you'll have to first connect to your cluster in env0. 7 | It can be easily done by following our [Kubernetes integration guide](https://docs.env0.com/docs/connect-your-cloud-account#kubernetes). 8 | 9 | ### Getting the namespace name from env0 10 | The name of the created namespace will be taken from the env0 environment variable $ENV0_K8S_NAMESPACE. You can set it in the `Namespace` input when creating an environment. -------------------------------------------------------------------------------- /kubernetes/hello-world/env0.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | 3 | deploy: 4 | steps: 5 | setupVariables: 6 | after: &set-namespace-name 7 | - echo "$(sed 's/!!!NAMESPACE!!!/'"$ENV0_K8S_NAMESPACE"'/g' namespace.yaml)" > namespace.yaml; 8 | - cat namespace.yaml 9 | 10 | destroy: 11 | steps: 12 | setupVariables: 13 | after: *set-namespace-name 14 | -------------------------------------------------------------------------------- /kubernetes/hello-world/namespace.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: !!!NAMESPACE!!! 5 | -------------------------------------------------------------------------------- /kubernetes/squid-proxy/README.md: -------------------------------------------------------------------------------- 1 | # Squid Proxy k8s installation 2 | 3 | This will setup a [squid proxy](http://www.squid-cache.org/) on a k8s server, 4 | used to 'simulate' hardened setups in which the env0 agent is behind a proxy server. 5 | All outgoing traffic from the agent must go through the proxy. 6 | 7 | ### Installing squid-proxy 8 | 9 | - Apply the `squid-proxy.yaml` file. 10 | 11 | ### Network Policy 12 | 13 | - The `network-policy.yaml` create a K8S network policy that will limit all traffic in a given namespace to go through the proxy. 14 | - Requires [calico](https://docs.aws.amazon.com/eks/latest/userguide/calico.html) to be installed - the vanilla k8s cluster doesn't enforce network policies. 15 | - Don't install without a specific namespace, it might affect core k8s services. 16 | 17 | ### Testing 18 | 19 | - `curl https://google.com` should not work 20 | - `curl https://google.com -x {proxy ip}:3128` should work 21 | 22 | ### Updating the agent 23 | 24 | - The agent should be installed with these values 25 | 26 | ``` 27 | "httpProxy": "http://squid-proxy-service.squid-proxy.svc.cluster.local:80" 28 | "httpsProxy": "http://squid-proxy-service.squid-proxy.svc.cluster.local:80" 29 | "noProxy": "{K8S ApiService IP/DNS}" 30 | ``` 31 | -------------------------------------------------------------------------------- /kubernetes/squid-proxy/env0.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | 3 | deploy: 4 | steps: 5 | setupVariables: 6 | after: &login-k8s 7 | - aws eks --region=$AWS_DEFAULT_REGION update-kubeconfig --name $CLUSTER_NAME 8 | 9 | destroy: 10 | steps: 11 | setupVariables: 12 | after: *login-k8s 13 | -------------------------------------------------------------------------------- /kubernetes/squid-proxy/network-policy.yaml: -------------------------------------------------------------------------------- 1 | # this will block all network egress except to the proxy 2 | 3 | apiVersion: networking.k8s.io/v1 4 | kind: NetworkPolicy 5 | metadata: 6 | name: default-deny-egress 7 | namespace: env0-agent-kushield # change this for the namespace you are working on - only requests to the proxy will be allowed 8 | spec: 9 | podSelector: {} 10 | policyTypes: 11 | - Egress 12 | egress: 13 | - to: # kube-dns 14 | - namespaceSelector: 15 | matchLabels: 16 | kubernetes.io/metadata.name: kube-system 17 | ports: 18 | - protocol: UDP 19 | port: 53 20 | 21 | - to: # proxy 22 | - podSelector: 23 | matchLabels: 24 | app: squid 25 | namespaceSelector: 26 | matchLabels: 27 | app: squid 28 | ports: 29 | - protocol: TCP 30 | port: 3128 31 | -------------------------------------------------------------------------------- /kubernetes/squid-proxy/squid-proxy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: squid-proxy 5 | labels: 6 | app: squid 7 | 8 | --- 9 | # Configuration for Squid-proxy 10 | # This config is VERY permissive - all traffic can go through the proxy transparently 11 | # Missing - user/pass authentication, SSL "bumping" (w/ self signed cert) 12 | kind: ConfigMap 13 | apiVersion: v1 14 | metadata: 15 | name: proxy-configmap 16 | namespace: squid-proxy 17 | data: 18 | squid.conf: | 19 | http_port 3128 20 | 21 | acl SSL_ports port 443 22 | acl CONNECT method CONNECT 23 | 24 | # allow all requests 25 | http_access allow all 26 | coredump_dir /var/spool/squid 27 | 28 | --- 29 | # Deployment for the proxy itself 30 | apiVersion: apps/v1 31 | kind: Deployment 32 | metadata: 33 | name: squid 34 | namespace: squid-proxy 35 | spec: 36 | replicas: 1 37 | selector: 38 | matchLabels: 39 | app: squid 40 | template: 41 | metadata: 42 | labels: 43 | app: squid 44 | spec: 45 | volumes: 46 | - name: proxy-config 47 | configMap: 48 | name: proxy-configmap 49 | containers: 50 | - name: squid 51 | image: ubuntu/squid:6.1-23.10_beta 52 | imagePullPolicy: IfNotPresent 53 | volumeMounts: 54 | - name: proxy-config 55 | mountPath: /etc/squid 56 | readOnly: true 57 | ports: 58 | - containerPort: 3128 59 | --- 60 | # Service for exposing the proxy 61 | apiVersion: v1 62 | kind: Service 63 | metadata: 64 | name: squid-proxy-service 65 | namespace: squid-proxy 66 | spec: 67 | selector: 68 | app: squid 69 | ports: 70 | - protocol: TCP 71 | port: 80 72 | targetPort: 3128 73 | -------------------------------------------------------------------------------- /kubernetes/using-pulumi/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: k8s-using-pulumi 2 | description: Create a K8s Pod 3 | runtime: nodejs -------------------------------------------------------------------------------- /kubernetes/using-pulumi/README.md: -------------------------------------------------------------------------------- 1 | # Kubernetes Using Pulumi 2 | 3 | Create a k8s pod resource with [Pulumi k8s provider](https://www.pulumi.com/registry/packages/kubernetes/). 4 | 5 | ### Connect to your K8s cluster in env0 6 | In order to apply this resource as an env0 [Pulumi template](https://docs.env0.com/docs/pulumi), you'll have to first connect to your cluster in env0. 7 | It can be easily done by following our [Kubernetes integration guide](https://docs.env0.com/docs/connect-your-cloud-account#kubernetes). 8 | 9 | ### Setting the k8s provider 10 | When you use our [Kubernetes integration](https://docs.env0.com/docs/connect-your-cloud-account#kubernetes) we create a kubeconfig file for you in the default location `~/.kube/config`. 11 | Pulumi, by default, will look for a kubeconfig file in that location when using the Pulumi provider configuration: 12 | 13 | ```typescript 14 | let provider = new k8s.Provider("k8s-provider"); 15 | ``` -------------------------------------------------------------------------------- /kubernetes/using-pulumi/env0.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | 3 | deploy: 4 | steps: 5 | setupVariables: 6 | after: 7 | - npm i 8 | pulumiLogin: 9 | before: 10 | - pulumi version 11 | 12 | destroy: 13 | steps: 14 | setupVariables: 15 | after: 16 | - npm i 17 | pulumiLogin: 18 | before: 19 | - pulumi version -------------------------------------------------------------------------------- /kubernetes/using-pulumi/index.ts: -------------------------------------------------------------------------------- 1 | import * as k8s from "@pulumi/kubernetes"; 2 | 3 | // Create a Kubernetes provider without specifying a kubeconfig 4 | // It automatically uses the default kubeconfig on your machine 5 | let provider = new k8s.Provider("k8s-provider"); 6 | 7 | // uses the created provider to create an Nginx pod 8 | let pod = new k8s.core.v1.Pod("my-nginx", { 9 | metadata: { 10 | name: "my-nginx", 11 | }, 12 | spec: { 13 | containers: [{ 14 | name: "my-nginx", 15 | image: "nginx", 16 | }], 17 | }, 18 | }, { provider }); 19 | 20 | // Export the name of the Pod 21 | export const podName = pod.metadata; -------------------------------------------------------------------------------- /kubernetes/using-pulumi/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "k8s-using-pulumi", 3 | "devDependencies": { 4 | "@types/node": "^8.0.0" 5 | }, 6 | "dependencies": { 7 | "@pulumi/pulumi": "latest", 8 | "@pulumi/kubernetes": "latest" 9 | } 10 | } -------------------------------------------------------------------------------- /kubernetes/using-pulumi/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "bin", 4 | "target": "es2016", 5 | "module": "commonjs", 6 | "moduleResolution": "node", 7 | "sourceMap": true, 8 | "experimentalDecorators": true, 9 | "pretty": true, 10 | "noFallthroughCasesInSwitch": true, 11 | "noImplicitAny": true, 12 | "noImplicitReturns": true, 13 | "forceConsistentCasingInFileNames": true, 14 | "strictNullChecks": true 15 | }, 16 | "files": [ 17 | "index.ts" 18 | ] 19 | } -------------------------------------------------------------------------------- /kubernetes/using-terraform/README.md: -------------------------------------------------------------------------------- 1 | # Kubernetes Using Terraform 2 | 3 | Create a k8s pod resource with [Terraform k8s provider](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs). 4 | 5 | ### Connect to your K8s cluster in env0 6 | In order to apply this resource as an env0 [Terraform template](https://docs.env0.com/docs/templates#terraform), you'll have to first connect to your cluster in env0. 7 | It can be easily done by following our [Kubernetes integration guide](https://docs.env0.com/docs/connect-your-cloud-account#kubernetes). 8 | 9 | ### Setting the k8s provider 10 | When you use our [Kubernetes integration](https://docs.env0.com/docs/connect-your-cloud-account#kubernetes) we create a kubeconfig file for you in the default location `~/.kube/config`. 11 | You can easily use this kubeconfig file with the k8s provider by using the following Terraform provider configuration: 12 | 13 | ```hcl 14 | provider "kubernetes" { 15 | config_path = "~/.kube/config" 16 | } 17 | ``` -------------------------------------------------------------------------------- /kubernetes/using-terraform/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | kubernetes = { 4 | source = "hashicorp/kubernetes" 5 | } 6 | } 7 | } 8 | 9 | provider "kubernetes" { 10 | config_path = "~/.kube/config" 11 | } 12 | 13 | resource "kubernetes_deployment" "nginx" { 14 | metadata { 15 | name = "scalable-nginx-example" 16 | labels = { 17 | App = "ScalableNginxExample" 18 | } 19 | } 20 | 21 | spec { 22 | replicas = 2 23 | selector { 24 | match_labels = { 25 | App = "ScalableNginxExample" 26 | } 27 | } 28 | template { 29 | metadata { 30 | labels = { 31 | App = "ScalableNginxExample" 32 | } 33 | } 34 | spec { 35 | container { 36 | image = "nginx:1.7.8" 37 | name = "example" 38 | 39 | port { 40 | container_port = 80 41 | } 42 | 43 | resources { 44 | limits = { 45 | cpu = "0.5" 46 | memory = "512Mi" 47 | } 48 | requests = { 49 | cpu = "250m" 50 | memory = "50Mi" 51 | } 52 | } 53 | } 54 | } 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /misc/ansible/playbook.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Debug 3 | hosts: localhost 4 | tasks: 5 | - name: Msg 6 | debug: 7 | msg: "hello" 8 | -------------------------------------------------------------------------------- /misc/azure-vault-sensitive-var/README.md: -------------------------------------------------------------------------------- 1 | This template validates that sensitive variables stored in azure vault are taken correctly during deployment. 2 | Relevant for self hosted agents only. 3 | 4 | It specifically validates that `$AZURE_SHAG_FAKE_SECRET`'s value is `FAKE_NEWS` 5 | -------------------------------------------------------------------------------- /misc/azure-vault-sensitive-var/env0.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | 3 | deploy: 4 | steps: 5 | setupVariables: 6 | after: 7 | - chmod +x validate.sh 8 | - ./validate.sh 9 | -------------------------------------------------------------------------------- /misc/azure-vault-sensitive-var/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "null" { 2 | } 3 | -------------------------------------------------------------------------------- /misc/azure-vault-sensitive-var/validate.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | if [[ "$AZURE_SHAG_FAKE_SECRET" == "FAKE_NEWS" ]]; 4 | then 5 | echo "Loaded secret from azure vault successfully" 6 | exit 0 7 | else 8 | echo "Validation failed! Value of azure vault secret is $AZURE_SHAG_FAKE_SECRET" 9 | exit 1 10 | fi 11 | -------------------------------------------------------------------------------- /misc/clone-with-commit-integ-test/env0.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | deploy: 3 | steps: 4 | setupVariables: 5 | after: 6 | - name: "Compare revisions" 7 | run: | 8 | #!/bin/bash 9 | 10 | # Ensure that the script exits on any error 11 | set -e 12 | 13 | # Get the current git revision 14 | current_revision=$(git rev-parse HEAD) 15 | 16 | echo "current revision: $current_revision" 17 | echo "env0 revision: $ENV0_DEPLOYMENT_REVISION" 18 | 19 | # Compare the current git revision with the ENV0_DEPLOYMENT_REVISION 20 | if [ "$current_revision" != "$ENV0_DEPLOYMENT_REVISION" ]; then 21 | echo "Error: Current git revision ($current_revision) does not match ENV0_DEPLOYMENT_REVISION ($ENV0_DEPLOYMENT_REVISION)." >&2 22 | exit 1 23 | fi 24 | -------------------------------------------------------------------------------- /misc/clone-with-commit-integ-test/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "null" { 2 | } 3 | -------------------------------------------------------------------------------- /misc/custom-flow-tf-vars/README.md: -------------------------------------------------------------------------------- 1 | ### Custom Flow TF_VAR 2 | 3 | This template will output a TF_VAR that was defined using `$ENV0_ENV` 4 | -------------------------------------------------------------------------------- /misc/custom-flow-tf-vars/env0.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | 3 | deploy: 4 | steps: 5 | terraformInit: 6 | before: 7 | - echo TF_VAR_email=user@domain.com >> $ENV0_ENV 8 | -------------------------------------------------------------------------------- /misc/custom-flow-tf-vars/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "null" { 2 | } 3 | 4 | variable "email" { 5 | type = string 6 | description = "env variable exported in env0.yml" 7 | default = "default@domain.com" 8 | } 9 | 10 | output "custom_flow_tf_var" { 11 | value = var.email 12 | } 13 | -------------------------------------------------------------------------------- /misc/custom-flows-environment-variables/README.md: -------------------------------------------------------------------------------- 1 | # Env0 System Environment Variables 2 | 3 | This folder will deploy `null-resource` environment to `env0`
4 | and will also `echo` environment variables defined by the user in a different step than the one they ae printed on
5 | -------------------------------------------------------------------------------- /misc/custom-flows-environment-variables/env0.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | 3 | deploy: 4 | steps: 5 | terraformPlan: 6 | before: 7 | - echo USER_NAME=user >> $ENV0_ENV 8 | - echo FULL_NAME_WITH_WHITESPACE=\"John Doe\" >> $ENV0_ENV 9 | - ./export-user-id.sh 10 | - echo "Populating ENV0_TERRAFORM_CONFIG_FILE_PATH - will be tested in main.tf to find an actual variable" 11 | - echo ENV0_TERRAFORM_CONFIG_FILE_PATH=var-file.json >> $ENV0_ENV 12 | after: 13 | - echo $USER_NAME 14 | - echo $FULL_NAME_WITH_WHITESPACE 15 | - ./print-user-id.sh 16 | - echo IN_SAME_STEP=works >> $ENV0_ENV 17 | - echo "****** Asserting expected values..." 18 | - "[ $USER_NAME == user ]" 19 | - '[ "$FULL_NAME_WITH_WHITESPACE" == "John Doe" ]' 20 | - "[ $USER_ID == user_id ]" 21 | - "[ $IN_SAME_STEP == works ]" 22 | - "[ $ENV0_TERRAFORM_CONFIG_FILE_PATH == var-file.json ]" 23 | destroy: 24 | steps: 25 | terraformPlan: 26 | before: 27 | - echo ENV0_TERRAFORM_CONFIG_FILE_PATH=var-file.json >> $ENV0_ENV 28 | -------------------------------------------------------------------------------- /misc/custom-flows-environment-variables/export-user-id.sh: -------------------------------------------------------------------------------- 1 | echo USER_ID=user_id >> $ENV0_ENV 2 | -------------------------------------------------------------------------------- /misc/custom-flows-environment-variables/main.tf: -------------------------------------------------------------------------------- 1 | variable "my-mandatory-var" { 2 | description = "This is mandatory and we will set it up using a magic var instantiated from a custom flow" 3 | } 4 | 5 | resource "null_resource" "null" { 6 | } 7 | -------------------------------------------------------------------------------- /misc/custom-flows-environment-variables/print-user-id.sh: -------------------------------------------------------------------------------- 1 | echo $USER_ID 2 | -------------------------------------------------------------------------------- /misc/custom-flows-environment-variables/var-file.json: -------------------------------------------------------------------------------- 1 | { 2 | "my-mandatory-var": "this is the value of the Mandalorian var" 3 | } 4 | -------------------------------------------------------------------------------- /misc/decode-oidc/decode-oidc-token.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | decode_base64() { 4 | local len=$((${#1} % 4)) 5 | local result="$1" 6 | if [ $len -eq 2 ]; then result="$1"'==' 7 | elif [ $len -eq 3 ]; then result="$1"'=' 8 | fi 9 | echo "$result" | tr '_-' '/+' | base64 -d 10 | } 11 | 12 | decode_jwt(){ 13 | decode_base64 $(echo -n $2 | cut -d "." -f $1) | jq . 14 | } 15 | 16 | decode_jwt 1 $ENV0_OIDC_TOKEN 17 | 18 | # Decode JWT Payload 19 | decode_jwt 2 $ENV0_OIDC_TOKEN 20 | -------------------------------------------------------------------------------- /misc/decode-oidc/env0.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | 3 | deploy: 4 | steps: 5 | terraformPlan: 6 | before: 7 | # Check tools permissions 8 | - ./decode-oidc-token.sh 9 | 10 | -------------------------------------------------------------------------------- /misc/decode-oidc/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "null" { 2 | } 3 | 4 | -------------------------------------------------------------------------------- /misc/drift-detection/env0.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | 3 | deploy: 4 | steps: 5 | terraformApply: 6 | after: 7 | - rm foo.bar 8 | 9 | -------------------------------------------------------------------------------- /misc/drift-detection/main.tf: -------------------------------------------------------------------------------- 1 | resource "local_file" "foo" { 2 | content = "foo!" 3 | filename = "${path.module}/foo.bar" 4 | } 5 | -------------------------------------------------------------------------------- /misc/ensure-permissions-on-tools-and-folders-for-user-node/ensure-permissions.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e -x 3 | 4 | # list installed apk packages 5 | apk list --installed 6 | 7 | # list installed python packages 8 | pip3 list 9 | 10 | # from base image 11 | node --version 12 | npm --version 13 | yarn --version 14 | 15 | #from alpine repos 16 | bash --version 17 | git --version 18 | python3 --version 19 | pip3 --version 20 | jq --version 21 | openssl version 22 | ssh -V 23 | curl --version 24 | 25 | # other 26 | aws --version 27 | awsv2 --version 28 | gcloud --version 29 | az --version 30 | kubectl version --client 31 | tfenv --version 32 | terraform --version 33 | tgenv --version 34 | terratag --help 35 | pwsh -v 36 | infracost --version 37 | helm version 38 | 39 | # Check write permissions 40 | touch /opt/test 41 | rm /opt/test 42 | touch /tmp/test 43 | rm /tmp/test 44 | touch /home/node/test 45 | rm /home/node/test 46 | mkdir -p /home/node/.cache 47 | python3 -m venv -h 48 | helm repo add env0 https://env0.github.io/self-hosted 49 | helm repo update 50 | helm show chart env0/env0-agent 51 | 52 | # Check packages install 53 | pip install --break-system-packages --user ansible 54 | ansible --version 55 | 56 | sudo apk add --no-cache rsync 57 | rsync --version 58 | 59 | sudo npm install -g @env0/cli 60 | env0 help 61 | -------------------------------------------------------------------------------- /misc/ensure-permissions-on-tools-and-folders-for-user-node/env0.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | 3 | deploy: 4 | steps: 5 | terraformPlan: 6 | before: 7 | # Check tools permissions 8 | - ./ensure-permissions.sh 9 | 10 | -------------------------------------------------------------------------------- /misc/ensure-permissions-on-tools-and-folders-for-user-node/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "null" { 2 | } 3 | 4 | -------------------------------------------------------------------------------- /misc/environment-outputs/inputs/env0.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | 3 | deploy: 4 | steps: 5 | setupVariables: 6 | after: 7 | - chmod +x validate.sh 8 | - ./validate.sh 9 | -------------------------------------------------------------------------------- /misc/environment-outputs/inputs/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "null" { 2 | } 3 | -------------------------------------------------------------------------------- /misc/environment-outputs/inputs/validate.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | if [[ "$SENSITIVE" == "sensitive" ]]; 4 | then 5 | echo "Resolved SENSITIVE input correctly" 6 | else 7 | echo "Didnt resolve SENSITIVE input correctly, got - $SENSITIVE" 8 | exit 1 9 | fi 10 | 11 | if [[ "$NOT_SENSITIVE" == "not sensitive" ]]; 12 | then 13 | echo "Resolved NOT_SENSITIVE input correctly" 14 | else 15 | echo "Didnt resolve NOT_SENSITIVE input correctly, got - $NOT_SENSITIVE" 16 | exit 1 17 | fi 18 | -------------------------------------------------------------------------------- /misc/environment-outputs/outputs/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "null" { 2 | } 3 | 4 | output "not_sensitive_output" { 5 | value = "not sensitive" 6 | } 7 | 8 | 9 | output "sensitive_output" { 10 | value = "sensitive" 11 | sensitive = true 12 | } 13 | -------------------------------------------------------------------------------- /misc/environment-variables/README.md: -------------------------------------------------------------------------------- 1 | # Env0 System Environment Variables 2 | 3 | This folder will deploy `null-resource` environment to `env0`
4 | and will also `echo` our system environment variables that we currently support
5 | ```shell 6 | ENV0_ENVIRONMENT_ID 7 | ENV0_PROJECT_ID 8 | ENV0_DEPLOYMENT_LOG_ID 9 | ENV0_WORKSPACE_NAME 10 | ENV0_ORGANIZATION_ID 11 | ENV0_TEMPLATE_ID 12 | ENV0_TEMPLATE_NAME 13 | ENV0_ENVIRONMENT_NAME 14 | ENV0_ENVIRONMENT_CREATOR_NAME 15 | ENV0_ENVIRONMENT_CREATOR_EMAIL 16 | ENV0_DEPLOYER_NAME 17 | ENV0_DEPLOYER_EMAIL 18 | ``` 19 | -------------------------------------------------------------------------------- /misc/environment-variables/env0.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | 3 | deploy: 4 | steps: 5 | terraformPlan: 6 | before: 7 | - echo $ENV0_ENVIRONMENT_ID 8 | - echo $ENV0_PROJECT_ID 9 | - echo $ENV0_DEPLOYMENT_LOG_ID 10 | - echo $ENV0_WORKSPACE_NAME 11 | - echo $ENV0_ORGANIZATION_ID 12 | - echo $ENV0_TEMPLATE_ID 13 | - echo $ENV0_TEMPLATE_NAME 14 | - echo $ENV0_ENVIRONMENT_NAME 15 | - echo $ENV0_ENVIRONMENT_CREATOR_NAME 16 | - echo $ENV0_ENVIRONMENT_CREATOR_EMAIL 17 | - echo $ENV0_DEPLOYER_NAME 18 | - echo $ENV0_DEPLOYER_EMAIL 19 | -------------------------------------------------------------------------------- /misc/environment-variables/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "null" { 2 | } 3 | -------------------------------------------------------------------------------- /misc/git-submodules/https/README.md: -------------------------------------------------------------------------------- 1 | # Git Modules 2 | This is an example of using [Git Modules](https://git-scm.com/book/en/v2/Git-Tools-Submodules) defined via `.gitmodules` (unlike terraform module) using hard coded https path. 3 | 4 | -------------------------------------------------------------------------------- /misc/git-submodules/relative/README.md: -------------------------------------------------------------------------------- 1 | # Git Modules 2 | This is an example of using [Git Modules](https://git-scm.com/book/en/v2/Git-Tools-Submodules) defined via `.gitmodules` (unlike terraform module) as path **relative** to the **repository** as describe [here](https://git-scm.com/docs/git-submodule#_commands). 3 | 4 | -------------------------------------------------------------------------------- /misc/local-sub-module/child/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "null" { 2 | } 3 | -------------------------------------------------------------------------------- /misc/local-sub-module/parent/main.tf: -------------------------------------------------------------------------------- 1 | module "remote-module" { 2 | source = "../child" 3 | } 4 | -------------------------------------------------------------------------------- /misc/null-fail-by-variable/README.md: -------------------------------------------------------------------------------- 1 | A template used to simulate a failure using the `SHOULD_PASS` environment variable. -------------------------------------------------------------------------------- /misc/null-fail-by-variable/env0.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | deploy: 3 | steps: 4 | setupVariables: 5 | after: 6 | - if [ -z "$SHOULD_PASS" ]; then echo "SHOULD_PASS must be supplied" 1>&2 && exit 1; fi -------------------------------------------------------------------------------- /misc/null-fail-by-variable/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "null" { 2 | } -------------------------------------------------------------------------------- /misc/null-resource-with-tf-version-constraints/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.2.0, < 2.0.0" 3 | } 4 | resource "null_resource" "null" { 5 | } 6 | -------------------------------------------------------------------------------- /misc/null-resource-workflow-environment/README.md: -------------------------------------------------------------------------------- 1 | ## What is this? 2 | 3 | Very simple workflow that deploy two environments from `null-resource` template 4 | -------------------------------------------------------------------------------- /misc/null-resource-workflow-environment/env0.workflow.yml: -------------------------------------------------------------------------------- 1 | environments: 2 | first-alias: 3 | name: first-name 4 | templateName: 'null-resource-1' 5 | second-alias: 6 | name: second-name 7 | templateName: 'null-resource-2' 8 | needs: [ first-alias ] 9 | -------------------------------------------------------------------------------- /misc/null-resource/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "null" { 2 | } 3 | -------------------------------------------------------------------------------- /misc/null-sleep/env0.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | 3 | deploy: 4 | steps: 5 | setupVariables: 6 | after: 7 | - sleep ${SLEEP_IN_SECONDS:-60} 8 | -------------------------------------------------------------------------------- /misc/null-sleep/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "null" { 2 | } 3 | -------------------------------------------------------------------------------- /misc/remote-backend-on-s3/env0.yml: -------------------------------------------------------------------------------- 1 | deploy: 2 | steps: 3 | terraformInit: 4 | before: 5 | - aws s3api create-bucket --bucket env0-tf-remote-backend-bucket --region us-east-1 6 | -------------------------------------------------------------------------------- /misc/remote-backend-on-s3/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | version = "~> 2.0" 3 | region = "us-east-1" 4 | } 5 | 6 | terraform { 7 | backend "s3" { 8 | bucket = "env0-tf-remote-backend-bucket" 9 | key = "remote-backend" 10 | region = "us-east-1" 11 | } 12 | } 13 | 14 | resource "null_resource" "null" { 15 | } 16 | -------------------------------------------------------------------------------- /misc/remote-backend/env0.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | 3 | deploy: 4 | steps: 5 | terraformApply: 6 | after: 7 | - chmod 700 ./validate-remote.sh 8 | - ./validate-remote.sh 9 | -------------------------------------------------------------------------------- /misc/remote-backend/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "null-resource" { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /misc/remote-backend/validate-remote.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | EXPECTED_TYPE='remote' 4 | ACTUAL_TYPE=$(cat .terraform/terraform.tfstate | jq -r ".backend.type") 5 | echo "Actual backend type: $ACTUAL_TYPE" 6 | if [[ "$EXPECTED_TYPE" == "$ACTUAL_TYPE" ]]; 7 | then 8 | echo 'backend type is remote. OK' 9 | exit 0 10 | else 11 | echo 'backend type is not remote. FAILED' 12 | exit 1 13 | fi 14 | -------------------------------------------------------------------------------- /misc/single-environment-workflow/README.md: -------------------------------------------------------------------------------- 1 | ## What is this? 2 | 3 | This is an example of a workflow template with one environment. 4 | In this specific scenario: 5 | - Deployment would start deployment of one null-resource stack `nullService1` 6 | 7 | ## How to run in env0? 8 | 9 | ### Prerequisites 10 | 11 | This example assumes the template with the following name already exist on your env0 organisation: 12 | - 'null resource' 13 | 14 | You can either create it in your organization, or alter `env0.workflow.yml` file to match other existing templates in your env0 organisation 15 | 16 | ### Defining the template 17 | 18 | - In env0, create a new template of type "env0 workflow" 19 | - On the VCS step, pick the repository containing this file, and put `misc/single-environment-workflow` under "env0 Workflow Location" 20 | - Save the template 21 | 22 | ### Running the template 23 | 24 | Now that the template is defined, you can simply run it in any env0 project using the "Create New Environment" button. 25 | Make sure to pick the template defined in the last step 26 | -------------------------------------------------------------------------------- /misc/single-environment-workflow/env0.workflow.yml: -------------------------------------------------------------------------------- 1 | environments: 2 | rootService1: 3 | name: nullService1 4 | templateName: 'null resource' 5 | -------------------------------------------------------------------------------- /misc/slack-notification/README.md: -------------------------------------------------------------------------------- 1 | # Env0 Deployment Slack Notifications 2 | 3 | Sends a Slack message for multiple events: 4 | * Deploy start 5 | * Destroy start 6 | * Found changes (terraform plan) 7 | * Deploy failed 8 | * Destroy failed 9 | * Waiting for approval 10 | * Deploy approved 11 | * Destroy approved 12 | 13 | For this to work the following environment variables should be provided: 14 | 15 | * `SLACK_URL` - The webhook url to post to (found in [Slack](https://env0.slack.com/apps/A0F7XDUAZ-incoming-webhooks)) 16 | -------------------------------------------------------------------------------- /misc/slack-notification/env0.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | 3 | deploy: 4 | steps: 5 | setupVariables: 6 | after: 7 | - ./on-start.sh 8 | terraformPlan: 9 | after: 10 | - ./on-plan.sh 11 | terraformApply: 12 | before: 13 | - ./on-approve.sh 14 | storeState: 15 | after: 16 | - ./on-store-state.sh 17 | onSuccess: 18 | - ./on-success.sh 19 | onFailure: 20 | - ./on-fail.sh 21 | 22 | destroy: 23 | steps: 24 | setupVariables: 25 | after: 26 | - ./on-start.sh 27 | terraformPlan: 28 | after: 29 | - ./on-plan.sh 30 | terraformDestroy: 31 | before: 32 | - ./on-approve.sh 33 | onSuccess: 34 | - ./on-success.sh 35 | onFailure: 36 | - ./on-fail.sh 37 | -------------------------------------------------------------------------------- /misc/slack-notification/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "null" { 2 | } 3 | -------------------------------------------------------------------------------- /misc/slack-notification/on-approve.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [[ -n "${ENV0_REVIEWER_NAME}" ]]; then 4 | MESSAGE="\`${ENV0_DEPLOYMENT_TYPE}\` deployment approved by: \`${ENV0_REVIEWER_NAME} (${ENV0_REVIEWER_EMAIL})\`" 5 | 6 | __dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 7 | source "${__dir}"/slack.sh "$MESSAGE" 8 | fi 9 | 10 | touch apply_ran_successfully 11 | -------------------------------------------------------------------------------- /misc/slack-notification/on-fail.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | MESSAGE="Failed running \`${ENV0_DEPLOYMENT_TYPE}\` deployment." 4 | 5 | __dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 6 | source "${__dir}"/slack.sh "$MESSAGE" 7 | -------------------------------------------------------------------------------- /misc/slack-notification/on-plan.sh: -------------------------------------------------------------------------------- 1 | DIFFERENCE=$(terraform show -json .tf-plan | jq '.resource_changes[] | select(.| .change.actions[0] != "no-op")') 2 | 3 | if [[ -z "${DIFFERENCE}" ]]; then 4 | echo "No changes in terraform plan" 5 | else 6 | __dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 7 | source "${__dir}"/slack.sh "Found changes in terraform plan" 8 | fi 9 | -------------------------------------------------------------------------------- /misc/slack-notification/on-start.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [[ -z "${ENV0_REVIEWER_NAME}" ]]; then 4 | ACTION="Started" 5 | else 6 | ACTION="Continued" 7 | fi 8 | 9 | if [ "${ENV0_DEPLOYER_NAME}" = "env0" ]; then 10 | TRIGGER="System" 11 | else 12 | TRIGGER="Manual" 13 | fi 14 | 15 | MESSAGE="${ACTION} running \`${ENV0_DEPLOYMENT_TYPE}\` deployment.\nTrigger: ${TRIGGER} Run" 16 | 17 | __dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 18 | source "${__dir}"/slack.sh "$MESSAGE" 19 | 20 | rm -f apply_ran_successfully 21 | -------------------------------------------------------------------------------- /misc/slack-notification/on-store-state.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | __dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 4 | 5 | if [ -f apply_ran_successfully ]; then 6 | echo 'apply step ran, not waiting for approval' 7 | else 8 | MESSAGE="Environment \`${ENV0_ENVIRONMENT_NAME}\` is waiting for approval." 9 | source "${__dir}"/slack.sh "$MESSAGE" 10 | fi 11 | -------------------------------------------------------------------------------- /misc/slack-notification/on-success.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | MESSAGE="Successfully finished running \`${ENV0_DEPLOYMENT_TYPE}\` deployment." 4 | 5 | __dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 6 | source "${__dir}"/slack.sh "$MESSAGE" 7 | -------------------------------------------------------------------------------- /misc/slack-notification/slack.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [[ -z "${ENV0_DEPLOYMENT_REVISION}" ]]; then 4 | REVISION="repository's default branch" 5 | else 6 | REVISION=$ENV0_DEPLOYMENT_REVISION 7 | fi 8 | 9 | DEPLOYMENT_DETAILS="" 10 | 11 | MESSAGE=":rocket: :information_source: ${DEPLOYMENT_DETAILS} - ${1}" 12 | ICON_URL="https://uploads-ssl.webflow.com/5ceab5395d0f478e169de7c0/5f21eb54b57c7a8559c68ff7_Env0-Color%20Icon%403x.png" 13 | 14 | PAYLOAD="{\"username\": \"env0\", \"text\": \"${MESSAGE}\", \"icon_url\": \"${ICON_URL}\"}" 15 | 16 | curl -X POST --data-urlencode "payload=${PAYLOAD}" "${SLACK_URL}" 17 | -------------------------------------------------------------------------------- /misc/ssm-sensitive-var/README.md: -------------------------------------------------------------------------------- 1 | This template validates that sensitive variable accessed via SSM are taken correctly during deployment. 2 | Relevant for self hosted agents only. 3 | 4 | It specifically validates that `$SHAG_FAKE_SECRET`'s value is `FAKE_NEWS` 5 | -------------------------------------------------------------------------------- /misc/ssm-sensitive-var/env0.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | 3 | deploy: 4 | steps: 5 | setupVariables: 6 | after: 7 | - chmod +x validate.sh 8 | - ./validate.sh 9 | -------------------------------------------------------------------------------- /misc/ssm-sensitive-var/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "null1" { 2 | } 3 | -------------------------------------------------------------------------------- /misc/ssm-sensitive-var/validate.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | if [[ "$SHAG_FAKE_SECRET" == "FAKE_NEWS" ]]; 4 | then 5 | echo "Loaded secret from SSM successfully" 6 | exit 0 7 | else 8 | echo "Validation failed! Value of SSM secret is $SHAG_FAKE_SECRET" 9 | exit 1 10 | fi 11 | -------------------------------------------------------------------------------- /misc/terraform-validate-workspace/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.15.1" 3 | } 4 | 5 | resource "null_resource" "null" { 6 | count = terraform.workspace == "default" ? -1 : 0 # This is used to check that the workspace in "terraform validate" isn't the default one 7 | } 8 | -------------------------------------------------------------------------------- /misc/validate-assume-role/README.md: -------------------------------------------------------------------------------- 1 | ### Validate Assume Role 2 | 3 | This template validates that an assumed AWS IAM role has been assumed correctly by env0. 4 | It will validate that the assumed identity ARN matches the regex given in the environment variable `EXPECTED_ARN` 5 | -------------------------------------------------------------------------------- /misc/validate-assume-role/env0.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | 3 | deploy: 4 | steps: 5 | setupVariables: 6 | after: 7 | - ./validate.sh 8 | -------------------------------------------------------------------------------- /misc/validate-assume-role/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "null" { 2 | } 3 | -------------------------------------------------------------------------------- /misc/validate-assume-role/validate.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | if [[ "$EXPECTED_ARN" == "" ]] 5 | then 6 | echo "Missing var EXPECTED_ARN" 7 | exit 1 8 | fi 9 | 10 | export ASSUMED_ARN=$(aws sts get-caller-identity --query Arn) 11 | 12 | echo "Assumed Role $ASSUMED_ARN" 13 | 14 | if [[ ! "$ASSUMED_ARN" =~ "$EXPECTED_ARN" ]] 15 | then 16 | echo "Assumed role expectation failed" 17 | exit 1 18 | fi 19 | 20 | echo "Assumed role expectation passed" 21 | -------------------------------------------------------------------------------- /misc/validate-state/env0.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | 3 | deploy: 4 | steps: 5 | terraformPlan: 6 | after: 7 | - ./validate.sh 8 | -------------------------------------------------------------------------------- /misc/validate-state/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = "0.12.24" 3 | } 4 | 5 | resource "null_resource" "null1" { 6 | } 7 | 8 | resource "null_resource" "null2" { 9 | } 10 | -------------------------------------------------------------------------------- /misc/validate-state/validate.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | if [[ "$IS_REDEPLOY" == "true" ]]; 4 | then 5 | EXPECTED_PLAN_OUTPUT="Plan: 0 to add, 0 to change, 0 to destroy." 6 | PLAN_OUTPUT=$(terraform show -no-color .tf-plan | tail -1) 7 | if [[ "$PLAN_OUTPUT" == "$EXPECTED_PLAN_OUTPUT" ]]; 8 | then 9 | echo "Redeploy plan is OK" 10 | exit 0 11 | else 12 | echo "Validation Failed, Redeploy plan is $PLAN_OUTPUT"; 13 | exit 1 14 | fi 15 | else 16 | echo "Not Redeploy so not validating" 17 | fi 18 | -------------------------------------------------------------------------------- /misc/vault-integration/README.md: -------------------------------------------------------------------------------- 1 | ### Vault Integration test template 2 | 3 | - This template runs a Hashicorp Vault _client_ that's meant to test the JWT integration with a running Vault server instance. 4 | - It runs the `vault.sh` script which authenticates against vault. 5 | - `VAULT_ROLE`, `VAULT_NAMESPACE`, `VAULT_ADDR`, `VAULT_DEV_ROOT_TOKEN` - these should be supplied as env vars to the deployment. See `aws/vault-server-on-eks/README.md` for more info. 6 | -------------------------------------------------------------------------------- /misc/vault-integration/configure-vault.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | echo "Installing vault client..." 5 | 6 | curl -sL https://releases.hashicorp.com/vault/1.11.1/vault_1.11.1_linux_amd64.zip -o vault1.zip 7 | unzip -o vault1.zip 8 | ./vault --version 9 | 10 | # The token should only be used to configure vault - after that we will login using OIDC 11 | export VAULT_TOKEN=$VAULT_DEV_ROOT_TOKEN 12 | 13 | # Cleaning up anything previously configured 14 | ./vault secrets disable secrets-for-env0/ || true 15 | ./vault auth disable env0-jwt/ || true 16 | 17 | # Configuring vault 18 | ./vault secrets enable -path=secrets-for-env0/ kv 19 | 20 | # # Bound a ACL policy for permissions 21 | ./vault policy write env0-access - < 2 | 3 | 4 | 5 | Hello from env0! 6 | 7 | 8 | 37 | 38 | 39 | 40 |
41 |

Welcome to your own environment !!!USER!!!

42 | 43 | hello 44 |
45 | Powered by   46 | 47 | 49 | 50 |
51 |
52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /pulumi/aws/hello-world/index.ts: -------------------------------------------------------------------------------- 1 | import * as apigateway from "@pulumi/aws-apigateway"; 2 | import * as fs from 'fs'; 3 | 4 | const indexTemplate = fs.readFileSync('index.template.html', 'utf-8'); 5 | const index = indexTemplate.replace(new RegExp('!!!USER!!!', 'g'), process.env.USER!); 6 | fs.writeFileSync('www/index.html', index); 7 | 8 | const api = new apigateway.RestAPI('pulumi-api-gw', { 9 | routes: [ 10 | { 11 | path: "/", 12 | localPath: "www" 13 | }, 14 | ], 15 | }); 16 | 17 | export const url = api.url; -------------------------------------------------------------------------------- /pulumi/aws/hello-world/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hello-world", 3 | "version": "1.0.0", 4 | "devDependencies": { 5 | "@types/node": "^14" 6 | }, 7 | "dependencies": { 8 | "@pulumi/aws": "^4.0.0", 9 | "@pulumi/aws-apigateway": "0.0.6", 10 | "@pulumi/awsx": "^0.30.0", 11 | "@pulumi/pulumi": "^3.119.0" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /pulumi/aws/hello-world/sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/env0/templates/80e65be109ec494bd2b4d5feefc20eb586d0b581/pulumi/aws/hello-world/sample.png -------------------------------------------------------------------------------- /pulumi/aws/hello-world/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "strict": true, 4 | "outDir": "bin", 5 | "target": "es2016", 6 | "module": "commonjs", 7 | "moduleResolution": "node", 8 | "sourceMap": true, 9 | "experimentalDecorators": true, 10 | "pretty": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "noImplicitReturns": true, 13 | "forceConsistentCasingInFileNames": true 14 | }, 15 | "files": [ 16 | "index.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /pulumi/aws/hello-world/www/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello from env0! 6 | 7 | 8 | 37 | 38 | 39 | 40 |
41 |

Welcome to your own environment Roni

42 | 43 | hello 44 |
45 | Powered by   46 | 47 | 49 | 50 |
51 |
52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /pulumi/dummy-resource/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: dummy-pulumi 2 | runtime: nodejs 3 | description: A dummy Pulumi project to test Pulumi functionality. 4 | -------------------------------------------------------------------------------- /pulumi/dummy-resource/env0.yaml: -------------------------------------------------------------------------------- 1 | version: 1 2 | 3 | deploy: 4 | steps: 5 | setupVariables: 6 | after: 7 | - npm i 8 | pulumiLogin: 9 | before: 10 | - pulumi version 11 | 12 | destroy: 13 | steps: 14 | setupVariables: 15 | after: 16 | - npm i 17 | pulumiLogin: 18 | before: 19 | - pulumi version 20 | -------------------------------------------------------------------------------- /pulumi/dummy-resource/index.ts: -------------------------------------------------------------------------------- 1 | import * as pulumi from "@pulumi/pulumi"; 2 | 3 | // Define a dynamic provider that does nothing. 4 | class DummyProvider implements pulumi.dynamic.ResourceProvider { 5 | async create(inputs: any) { 6 | return { id: "dummy-id", outs: inputs }; 7 | } 8 | async update(id: string, olds: any, news: any) { 9 | return { outs: news }; 10 | } 11 | async delete(id: string, props: any) { 12 | // No action needed for delete. 13 | } 14 | } 15 | 16 | // Define a dummy resource using the dynamic provider. 17 | class DummyResource extends pulumi.dynamic.Resource { 18 | constructor(name: string, props: pulumi.Inputs = {}) { 19 | super(new DummyProvider(), name, props); 20 | } 21 | } 22 | 23 | // Instantiate the dummy resource. 24 | const dummy = new DummyResource("dummy", {}); 25 | 26 | // Export an output. 27 | export const dummyId = dummy.id; 28 | -------------------------------------------------------------------------------- /pulumi/dummy-resource/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dummy-pulumi", 3 | "version": "1.0.0", 4 | "description": "A dummy Pulumi project to test Pulumi functionality.", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "tsc", 8 | "preview": "pulumi preview", 9 | "up": "pulumi up", 10 | "destroy": "pulumi destroy" 11 | }, 12 | "dependencies": { 13 | "@pulumi/pulumi": "^3.0.0" 14 | }, 15 | "devDependencies": { 16 | "@types/node": "^14.0.0", 17 | "typescript": "^4.0.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /pulumi/dummy-resource/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "commonjs", 5 | "strict": true, 6 | "esModuleInterop": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "skipLibCheck": true, 9 | "outDir": "bin" 10 | }, 11 | "include": [ 12 | "index.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /root-folder-terraform.tf: -------------------------------------------------------------------------------- 1 | # root folder terraform 2 | resource "null_resource" "null" { 3 | } 4 | -------------------------------------------------------------------------------- /terragrunt/__inputs/temp.hcl: -------------------------------------------------------------------------------- 1 | terraform { 2 | source = "github.com/env0/templates.git" 3 | } 4 | -------------------------------------------------------------------------------- /terragrunt/__inputs/temp2.hcl: -------------------------------------------------------------------------------- 1 | terraform { 2 | source = "github.com/env0/templates.git" 3 | } 4 | -------------------------------------------------------------------------------- /terragrunt/misc/ensure-permissions-on-tools-and-folders-for-user-node/env0.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | 3 | deploy: 4 | steps: 5 | terraformPlan: 6 | before: 7 | # Check tools permissions 8 | - "$ENV0_ROOT_DIR/misc/ensure-permissions-on-tools-and-folders-for-user-node/ensure-permissions.sh" 9 | # Check terragrunt permissions 10 | - terragrunt --version 11 | 12 | -------------------------------------------------------------------------------- /terragrunt/misc/ensure-permissions-on-tools-and-folders-for-user-node/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "null" { 2 | } 3 | 4 | -------------------------------------------------------------------------------- /terragrunt/misc/ensure-permissions-on-tools-and-folders-for-user-node/terragrunt.hcl: -------------------------------------------------------------------------------- 1 | # Terragrunt requires a terragrunt.hcl file to function. 2 | 3 | -------------------------------------------------------------------------------- /terragrunt/misc/module-resource/README.md: -------------------------------------------------------------------------------- 1 | # Terragrunt source Template 2 | The root Terragrunt configuration will use a terraform source block to create a null resource by a local module. 3 | The Terragrunt project contain two (unrelated) stage: 4 | * "simple" which only use the root Terragrunt configuration. 5 | * "with-env-yaml" which also add env0.yaml to delete the .terragrunt-cache folder after TG plan 6 | -------------------------------------------------------------------------------- /terragrunt/misc/module-resource/module/null-module/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "null" { 2 | } 3 | -------------------------------------------------------------------------------- /terragrunt/misc/module-resource/simple/terragrunt.hcl: -------------------------------------------------------------------------------- 1 | include { 2 | path = find_in_parent_folders() 3 | } 4 | -------------------------------------------------------------------------------- /terragrunt/misc/module-resource/terragrunt.hcl: -------------------------------------------------------------------------------- 1 | # Terragrunt will copy the Terraform configurations specified by the source parameter, along with any files in the 2 | # working directory, into a temporary folder, and execute your Terraform commands in that folder. 3 | terraform { 4 | source = "../module/null-module" 5 | } 6 | -------------------------------------------------------------------------------- /terragrunt/misc/module-resource/with-env-yaml/env0.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | 3 | deploy: 4 | steps: 5 | terraformPlan: 6 | after: 7 | - rm -rf .terragrunt-cache 8 | terraformApply: 9 | before: 10 | - ls -la 11 | - pwd 12 | -------------------------------------------------------------------------------- /terragrunt/misc/module-resource/with-env-yaml/terragrunt.hcl: -------------------------------------------------------------------------------- 1 | include { 2 | path = find_in_parent_folders() 3 | } 4 | -------------------------------------------------------------------------------- /terragrunt/misc/null-resource/.gitignore: -------------------------------------------------------------------------------- 1 | **/tg.*.tf 2 | .terraform 3 | -------------------------------------------------------------------------------- /terragrunt/misc/null-resource/README.md: -------------------------------------------------------------------------------- 1 | # Terragrunt Null Template 2 | A Terragrunt project with two stages: prod and dev. 3 | The root Terragrunt configuration will use a generated block to generate the null resource in the child modules. 4 | -------------------------------------------------------------------------------- /terragrunt/misc/null-resource/dev/main.tf: -------------------------------------------------------------------------------- 1 | /* empty file - Terragrunt will generate all resources */ 2 | -------------------------------------------------------------------------------- /terragrunt/misc/null-resource/dev/terragrunt.hcl: -------------------------------------------------------------------------------- 1 | include { 2 | path = find_in_parent_folders() 3 | } 4 | -------------------------------------------------------------------------------- /terragrunt/misc/null-resource/prod/main.tf: -------------------------------------------------------------------------------- 1 | /* empty file - Terragrunt will generate all resources */ 2 | -------------------------------------------------------------------------------- /terragrunt/misc/null-resource/prod/terragrunt.hcl: -------------------------------------------------------------------------------- 1 | include { 2 | path = find_in_parent_folders() 3 | } 4 | -------------------------------------------------------------------------------- /terragrunt/misc/null-resource/terragrunt.hcl: -------------------------------------------------------------------------------- 1 | generate "null_resource" { 2 | path = "tg.main.tf" 3 | if_exists = "overwrite_terragrunt" 4 | contents = < /dev/null 2>&1 & 21 | ''' 22 | 23 | ssh = paramiko.SSHClient() 24 | ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 25 | ssh.connect(host, ssh_port, username, password) 26 | 27 | ssh.exec_command(f'sudo kill -9 $(sudo lsof -t -i:{http_server_port})') 28 | 29 | transport = ssh.get_transport() 30 | channel = transport.open_session() 31 | 32 | channel.exec_command(command) 33 | 34 | print(f'serving at http://{host}:{http_server_port}') -------------------------------------------------------------------------------- /vsphere/vm-http-server/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = "0.13.3" 3 | } 4 | 5 | provider "vsphere" { 6 | # If you have a self-signed cert 7 | allow_unverified_ssl = true 8 | } 9 | 10 | resource "vsphere_virtual_machine" "vm" { 11 | name = var.vm_name 12 | resource_pool_id = data.vsphere_resource_pool.pool.id 13 | datastore_id = data.vsphere_datastore.datastore.id 14 | 15 | wait_for_guest_net_timeout = 0 16 | wait_for_guest_ip_timeout = 5 # for vmware tools < 10 17 | 18 | num_cpus = 2 19 | memory = 1024 20 | guest_id = data.vsphere_virtual_machine.template.guest_id 21 | 22 | scsi_type = data.vsphere_virtual_machine.template.scsi_type 23 | 24 | network_interface { 25 | network_id = data.vsphere_network.network.id 26 | adapter_type = data.vsphere_virtual_machine.template.network_interface_types[0] 27 | } 28 | 29 | disk { 30 | label = "disk0" 31 | size = data.vsphere_virtual_machine.template.disks.0.size 32 | eagerly_scrub = data.vsphere_virtual_machine.template.disks.0.eagerly_scrub 33 | thin_provisioned = data.vsphere_virtual_machine.template.disks.0.thin_provisioned 34 | } 35 | 36 | clone { 37 | template_uuid = data.vsphere_virtual_machine.template.id 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /vsphere/vm-http-server/outputs.tf: -------------------------------------------------------------------------------- 1 | output "vm_default_ip_address" { 2 | value = vsphere_virtual_machine.vm.default_ip_address 3 | } 4 | 5 | output "vm_http_server" { 6 | value = "http://${vsphere_virtual_machine.vm.default_ip_address}:${var.http_server_port}" 7 | } -------------------------------------------------------------------------------- /vsphere/vm-http-server/variables.tf: -------------------------------------------------------------------------------- 1 | variable "vm_name" { 2 | type = string 3 | description = "the name of the vm to spin up" 4 | } 5 | 6 | variable "http_server_port" { 7 | type = number 8 | description = "the port to run the http server on" 9 | } --------------------------------------------------------------------------------