diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b8e400e --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +terraform +.DS_Store \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..c20e94d --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# terraform-cloud-vm +a repo for chapter 8 diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..f43b2a4 --- /dev/null +++ b/main.tf @@ -0,0 +1 @@ +# required file \ No newline at end of file diff --git a/modules/aws/README.md b/modules/aws/README.md new file mode 100644 index 0000000..2e44506 --- /dev/null +++ b/modules/aws/README.md @@ -0,0 +1,2 @@ +# terraform-cloud-vm/aws +deploys a VM on AWS \ No newline at end of file diff --git a/modules/aws/main.tf b/modules/aws/main.tf new file mode 100644 index 0000000..e8b8998 --- /dev/null +++ b/modules/aws/main.tf @@ -0,0 +1,42 @@ +data "aws_vpc" "default" { + default = true +} + +module "instance_sg" { + source = "scottwinkler/sg/aws" + vpc_id = data.aws_vpc.default.id + ingress_rules = [ + { + port = 8080 + cidr_blocks = ["0.0.0.0/0"] + } + ] +} + +module "iam_instance_profile" { + source = "scottwinkler/iip/aws" + actions = ["logs:*", "ec2:DescribeInstances"] +} + +data "aws_ami" "ubuntu" { + most_recent = true + filter { + name = "name" + values = ["ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*"] + } + owners = ["099720109477"] +} + +resource "aws_instance" "instance" { + ami = data.aws_ami.ubuntu.id + instance_type = "t3.micro" + key_name = var.ssh_keypair + vpc_security_group_ids = [module.instance_sg.security_group.id] + associate_public_ip_address = true + user_data = templatefile("${path.module}/templates/startup.sh", { NAME = var.environment.name, BG_COLOR = var.environment.background_color }) + iam_instance_profile = module.iam_instance_profile.name + + tags = { + Name = "aws-vm" + } +} diff --git a/modules/aws/outputs.tf b/modules/aws/outputs.tf new file mode 100644 index 0000000..7b52475 --- /dev/null +++ b/modules/aws/outputs.tf @@ -0,0 +1,7 @@ +output "public_ip" { + value = aws_instance.instance.public_ip +} + +output "network_address" { + value = "${aws_instance.instance.public_ip}:8080" +} \ No newline at end of file diff --git a/modules/aws/templates/startup.sh b/modules/aws/templates/startup.sh new file mode 100644 index 0000000..51320d2 --- /dev/null +++ b/modules/aws/templates/startup.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +set -e +echo "Installing dependencies..." +sudo apt-get -qq update &>/dev/null + +echo "Installing Docker..." +curl -fsSL https://get.docker.com -o get-docker.sh +sudo sh get-docker.sh + +echo "Configuring application service..." +sudo tee /etc/systemd/system/app.service > /dev/null <<"EOF" +[Unit] +Description=Application +Requires=network-online.target +After=network-online.target + +[Service] +Restart=on-failure +Environment=CONSUL_ALLOW_PRIVILEGED_PORTS=true +ExecStart=/usr/bin/docker run -dit -e NAME=${NAME} -e BG_COLOR=${BG_COLOR} -p 8080:80 swinkler/tia-webserver +ExecReload=/bin/kill -HUP $MAINPID +KillSignal=SIGTERM +User=root +Group=root + +[Install] +WantedBy=multi-user.target +EOF + +echo "Starting services..." +sudo systemctl daemon-reload +sudo systemctl enable app.service +sudo systemctl start app.service \ No newline at end of file diff --git a/modules/aws/variables.tf b/modules/aws/variables.tf new file mode 100644 index 0000000..3d4e37e --- /dev/null +++ b/modules/aws/variables.tf @@ -0,0 +1,11 @@ +variable "environment" { + type = object({ + name = string + background_color=string + }) +} + +variable "ssh_keypair" { + default = null + type = string +} diff --git a/modules/azure/README.md b/modules/azure/README.md new file mode 100644 index 0000000..eeac3ed --- /dev/null +++ b/modules/azure/README.md @@ -0,0 +1,2 @@ +# terraform-cloud-vm/azure +deploys a VM on Azure \ No newline at end of file diff --git a/modules/azure/main.tf b/modules/azure/main.tf new file mode 100644 index 0000000..9cb9f90 --- /dev/null +++ b/modules/azure/main.tf @@ -0,0 +1,118 @@ +resource "random_string" "rand_rg" { + length = 24 + special = false + upper = false +} + +resource "azurerm_resource_group" "resource_group" { + name = random_string.rand_rg.result + location = var.location +} + +resource "azurerm_virtual_network" "virtual_network" { + name = "default" + address_space = ["172.16.0.0/16"] + location = var.location + resource_group_name = azurerm_resource_group.resource_group.name +} + +resource "azurerm_subnet" "vm_subnet" { + name = "vm-subnet" + resource_group_name = azurerm_resource_group.resource_group.name + virtual_network_name = azurerm_virtual_network.virtual_network.name + address_prefix = "172.16.0.0/24" +} + +resource "azurerm_network_security_group" "vm_sg" { + name = "VM-NetworkSecurityGroup" + location = var.location + resource_group_name = azurerm_resource_group.resource_group.name + + security_rule { + name = "app" + priority = 100 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_port_range = "*" + destination_port_range = "8080" + source_address_prefix = "*" + destination_address_prefix = "*" + } +} + +resource "azurerm_public_ip" "public_ip" { + name = "vm-public_ip" + location = var.location + resource_group_name = azurerm_resource_group.resource_group.name + allocation_method = "Static" + sku = "Standard" +} + +resource "azurerm_network_interface" "network_interface" { + name = "vm-nic" + location = var.location + resource_group_name = azurerm_resource_group.resource_group.name + network_security_group_id = azurerm_network_security_group.vm_sg.id + + ip_configuration { + name = "vm-IPConfiguration" + subnet_id = azurerm_subnet.vm_subnet.id + private_ip_address_allocation = "Dynamic" + public_ip_address_id = azurerm_public_ip.public_ip.id + } +} + +# Enable Boot Diagnostics +resource "random_string" "rand_bd" { + length = 24 + special = false + upper = false +} + +resource "azurerm_storage_account" "storage_account" { + name = random_string.rand_bd.result + resource_group_name = azurerm_resource_group.resource_group.name + location = var.location + account_tier = "Standard" + account_replication_type = "LRS" +} + +resource "azurerm_virtual_machine" "virtual_machine" { + name = "azure-vm" + location = var.location + resource_group_name = azurerm_resource_group.resource_group.name + network_interface_ids = [azurerm_network_interface.network_interface.id] + vm_size = "Standard_A1" + delete_os_disk_on_termination = true + delete_data_disks_on_termination = true + + storage_os_disk { + name = "vm-osdisk" + caching = "ReadWrite" + create_option = "FromImage" + managed_disk_type = "Standard_LRS" + } + + storage_image_reference { + publisher = "Canonical" + offer = "UbuntuServer" + sku = "18.04-LTS" + version = "latest" + } + + boot_diagnostics { + enabled = true + storage_uri = azurerm_storage_account.storage_account.primary_blob_endpoint + } + + os_profile { + computer_name = "azure-vm" + admin_username = "azure" + admin_password = "Passwword1234" + custom_data = templatefile("${path.module}/templates/startup.sh",{ NAME = var.environment.name, BG_COLOR = var.environment.background_color }) + } + os_profile_linux_config { + disable_password_authentication = false + } +} diff --git a/modules/azure/outputs.tf b/modules/azure/outputs.tf new file mode 100644 index 0000000..260205b --- /dev/null +++ b/modules/azure/outputs.tf @@ -0,0 +1,7 @@ +output "public_ip" { + value = azurerm_public_ip.public_ip.ip_address +} + +output "network_address" { + value = "${azurerm_public_ip.public_ip.ip_address}:8080" +} \ No newline at end of file diff --git a/modules/azure/templates/startup.sh b/modules/azure/templates/startup.sh new file mode 100644 index 0000000..51320d2 --- /dev/null +++ b/modules/azure/templates/startup.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +set -e +echo "Installing dependencies..." +sudo apt-get -qq update &>/dev/null + +echo "Installing Docker..." +curl -fsSL https://get.docker.com -o get-docker.sh +sudo sh get-docker.sh + +echo "Configuring application service..." +sudo tee /etc/systemd/system/app.service > /dev/null <<"EOF" +[Unit] +Description=Application +Requires=network-online.target +After=network-online.target + +[Service] +Restart=on-failure +Environment=CONSUL_ALLOW_PRIVILEGED_PORTS=true +ExecStart=/usr/bin/docker run -dit -e NAME=${NAME} -e BG_COLOR=${BG_COLOR} -p 8080:80 swinkler/tia-webserver +ExecReload=/bin/kill -HUP $MAINPID +KillSignal=SIGTERM +User=root +Group=root + +[Install] +WantedBy=multi-user.target +EOF + +echo "Starting services..." +sudo systemctl daemon-reload +sudo systemctl enable app.service +sudo systemctl start app.service \ No newline at end of file diff --git a/modules/azure/variables.tf b/modules/azure/variables.tf new file mode 100644 index 0000000..7829b73 --- /dev/null +++ b/modules/azure/variables.tf @@ -0,0 +1,11 @@ +variable "location" { + default = "westus2" + type = string +} + +variable "environment" { + type = object({ + name = string + background_color=string + }) +} \ No newline at end of file diff --git a/modules/gcp/README.md b/modules/gcp/README.md new file mode 100644 index 0000000..f2c2a06 --- /dev/null +++ b/modules/gcp/README.md @@ -0,0 +1,2 @@ +# terraform-cloud-vm/gcp +deploys a VM on GCP \ No newline at end of file diff --git a/modules/gcp/main.tf b/modules/gcp/main.tf new file mode 100644 index 0000000..b3a7d03 --- /dev/null +++ b/modules/gcp/main.tf @@ -0,0 +1,58 @@ +locals { + services = ["compute.googleapis.com"] +} + +resource "google_project_service" "enabled_service" { + for_each = toset(local.services) + project = var.project_id + service = each.key + provisioner "local-exec" { + command = "sleep 60" + } + disable_on_destroy = false +} + +resource "google_compute_firewall" "default" { + depends_on = [google_project_service.enabled_service["compute.googleapis.com"]] + name = "default-firewall" + network = "default" + + allow { + protocol = "icmp" + } + + allow { + protocol = "tcp" + ports = ["8080"] + } + + source_ranges = ["0.0.0.0/0"] +} + +// A single Google Cloud Engine instance +resource "google_compute_instance" "compute_instance" { + depends_on = [google_project_service.enabled_service["compute.googleapis.com"]] + name = "gcp-vm" + machine_type = "n1-standard-1" + zone = "${var.region}-a" + + boot_disk { + initialize_params { + image = "ubuntu-os-cloud/ubuntu-1804-lts" + } + } + + metadata_startup_script = templatefile("${path.module}/templates/startup.sh",{ NAME = var.environment.name, BG_COLOR = var.environment.background_color }) + + network_interface { + network = "default" + + access_config { + // Ephemeral IP + } + } + + service_account { + scopes = ["userinfo-email", "compute-ro", "storage-ro"] + } +} diff --git a/modules/gcp/outputs.tf b/modules/gcp/outputs.tf new file mode 100644 index 0000000..01c3ad9 --- /dev/null +++ b/modules/gcp/outputs.tf @@ -0,0 +1,7 @@ +output "public_ip" { + value = google_compute_instance.compute_instance.network_interface.0.access_config.0.nat_ip +} + +output "network_address" { + value = "${google_compute_instance.compute_instance.network_interface.0.access_config.0.nat_ip}:8080" +} \ No newline at end of file diff --git a/modules/gcp/templates/startup.sh b/modules/gcp/templates/startup.sh new file mode 100644 index 0000000..51320d2 --- /dev/null +++ b/modules/gcp/templates/startup.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +set -e +echo "Installing dependencies..." +sudo apt-get -qq update &>/dev/null + +echo "Installing Docker..." +curl -fsSL https://get.docker.com -o get-docker.sh +sudo sh get-docker.sh + +echo "Configuring application service..." +sudo tee /etc/systemd/system/app.service > /dev/null <<"EOF" +[Unit] +Description=Application +Requires=network-online.target +After=network-online.target + +[Service] +Restart=on-failure +Environment=CONSUL_ALLOW_PRIVILEGED_PORTS=true +ExecStart=/usr/bin/docker run -dit -e NAME=${NAME} -e BG_COLOR=${BG_COLOR} -p 8080:80 swinkler/tia-webserver +ExecReload=/bin/kill -HUP $MAINPID +KillSignal=SIGTERM +User=root +Group=root + +[Install] +WantedBy=multi-user.target +EOF + +echo "Starting services..." +sudo systemctl daemon-reload +sudo systemctl enable app.service +sudo systemctl start app.service \ No newline at end of file diff --git a/modules/gcp/variables.tf b/modules/gcp/variables.tf new file mode 100644 index 0000000..045f5ba --- /dev/null +++ b/modules/gcp/variables.tf @@ -0,0 +1,17 @@ +variable "project_id" { + description = "The GCP project id" + type = string +} + +variable "region" { + default = "us-central1" + description = "GCP region" + type = string +} + +variable "environment" { + type = object({ + name = string + background_color=string + }) +} \ No newline at end of file diff --git a/modules/loadbalancer/README.md b/modules/loadbalancer/README.md new file mode 100644 index 0000000..2cd38a6 --- /dev/null +++ b/modules/loadbalancer/README.md @@ -0,0 +1,2 @@ +# terraform-cloud-vm/loadbalancer +deploys a Docker container on the local machine \ No newline at end of file diff --git a/modules/loadbalancer/main.tf b/modules/loadbalancer/main.tf new file mode 100644 index 0000000..8836ed7 --- /dev/null +++ b/modules/loadbalancer/main.tf @@ -0,0 +1,15 @@ +#docker run -d -v /var/run/docker.sock:/var/run/docker.sock -p 127.0.0.1:2375:2375 bobrik/socat TCP-LISTEN:2375,fork UNIX-CONNECT:/var/run/docker.sock +#export DOCKER_HOST=tcp://localhost:2375 + +resource "docker_container" "loadbalancer" { + name = "tia-loadbalancer" + image = "swinkler/tia-loadbalancer" + env = [ + "ADDRESSES=${join(" ",var.addresses)}" + ] + ports { + internal = 80 + external = 5000 + } +} + diff --git a/modules/loadbalancer/outputs.tf b/modules/loadbalancer/outputs.tf new file mode 100644 index 0000000..e30c25b --- /dev/null +++ b/modules/loadbalancer/outputs.tf @@ -0,0 +1,3 @@ +output "network_address" { + value = "localhost:5000" +} \ No newline at end of file diff --git a/modules/loadbalancer/variables.tf b/modules/loadbalancer/variables.tf new file mode 100644 index 0000000..48f773d --- /dev/null +++ b/modules/loadbalancer/variables.tf @@ -0,0 +1,3 @@ +variable "addresses" { + type = list(string) +} \ No newline at end of file