Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Solution #11

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions backend.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
terraform {
backend "azurerm" {
storage_account_name = "shutftask12sa"
container_name = "tfstate"
key = "terraform.tfstate"
resource_group_name = "mate-azure-task-12"
}
}
22 changes: 9 additions & 13 deletions install-app.sh
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
#!/bin/bash

# Script to silently install and start the todo web app on the virtual machine.
# Note that all commands bellow are without sudo - that's because extention mechanism
# runs scripts under root user.

# install system updates and isntall python3-pip package using apt. '-yq' flags are
# used to suppress any interactive prompts - we won't be able to confirm operation
# when running the script as VM extention.
apt-get update -yq
apt-get install python3-pip -yq

# Create a directory for the app and download the files.
mkdir /app
# make sure to uncomment the line bellow and update the link with your GitHub username
# git clone https://github.com/<your-gh-username>/azure_task_12_deploy_app_with_vm_extention.git
cp -r devops_todolist_terraform_task/app/* /app
cd ~
git clone https://github.com/v-shutov/devops_todolist_terraform_task.git

mkdir /app
cp -r ~/devops_todolist_terraform_task/app/* /app
rm -rf ~/devops_todolist_terraform_task

cd /app
chmod +x start.sh

# create a service for the app via systemctl and start the app
mv /app/todoapp.service /etc/systemd/system/
systemctl daemon-reload
systemctl start todoapp
Expand Down
62 changes: 62 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "3.105.0"
}
}
}

provider "azurerm" {
features {}
}

resource "azurerm_resource_group" "main" {
name = var.resource_group_name
location = var.location
}

resource "azurerm_storage_container" "backend" {
name = var.backend_container_name
storage_account_name = module.storage.storage_account.name
container_access_type = "private"
depends_on = [module.storage]
}

module "network" {
source = "./modules/network"
depends_on = [azurerm_resource_group.main]
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
virtual_network_name = var.virtual_network_name
vnet_address_prefix = var.vnet_address_prefix
subnet_name = var.subnet_name
subnet_address_prefix = var.subnet_address_prefix
network_security_group_name = var.network_security_group_name
public_ip_address_name = var.public_ip_address_name
dns_label = var.dns_label
}

module "compute" {
source = "./modules/compute"
depends_on = [azurerm_resource_group.main, module.network, module.storage]
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
vm_name = var.vm_name
vm_size = var.vm_size
subnet_id = module.network.subnet.id
public_ip_address_id = module.network.public_ip.id
admin_username = var.admin_username
linuxboxsshkey = var.ssh_key_public
blob_url = module.storage.storage_blob.url
blob_name = module.storage.storage_blob.name
}

module "storage" {
source = "./modules/storage"
depends_on = [azurerm_resource_group.main]
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
storage_account_name = var.storage_account_name
task_artifacts_container_name = var.task_artifacts_container_name
}
55 changes: 55 additions & 0 deletions modules/compute/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
resource "azurerm_network_interface" "main" {
name = "${var.vm_name}-nic"
location = var.location
resource_group_name = var.resource_group_name

ip_configuration {
name = "internal"
subnet_id = var.subnet_id
private_ip_address_allocation = "Dynamic"
public_ip_address_id = var.public_ip_address_id
}
}

resource "azurerm_linux_virtual_machine" "main" {
name = var.vm_name
location = var.location
resource_group_name = var.resource_group_name
network_interface_ids = [azurerm_network_interface.main.id]
size = var.vm_size
admin_username = var.admin_username

admin_ssh_key {
username = var.admin_username
public_key = file(var.linuxboxsshkey)
}

source_image_reference {
publisher = "Canonical"
offer = "0001-com-ubuntu-server-jammy"
sku = "22_04-lts"
version = "latest"
}

os_disk {
storage_account_type = "Standard_LRS"
caching = "ReadWrite"
disk_size_gb = "64"
}
}

resource "azurerm_virtual_machine_extension" "custom_script" {
name = "install_app"
virtual_machine_id = azurerm_linux_virtual_machine.main.id
publisher = "Microsoft.Azure.Extensions"
type = "CustomScript"
type_handler_version = "2.0"
auto_upgrade_minor_version = true

settings = <<SETTINGS
{
"fileUris": ["${var.blob_url}"],
"commandToExecute": "bash ${var.blob_name}"
}
SETTINGS
}
7 changes: 7 additions & 0 deletions modules/compute/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
output "nic" {
value = azurerm_network_interface.main
}

output "vm" {
value = azurerm_linux_virtual_machine.main
}
49 changes: 49 additions & 0 deletions modules/compute/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
variable "location" {
description = "The location where all resources will be deployed."
type = string
}

variable "resource_group_name" {
description = "The name of the resource group that will contain all the resources."
type = string
}

variable "subnet_id" {
description = "The ID of the subnet in which the virtual machine's network interface will be created."
type = string
}

variable "public_ip_address_id" {
description = "The ID of the public IP address to be associated with the network interface."
type = string
}

variable "vm_name" {
description = "The name of the virtual machine to be created."
type = string
}

variable "vm_size" {
description = "The size of the virtual machine, such as 'Standard_B1s'."
type = string
}

variable "admin_username" {
description = "The username for the admin account on the virtual machine."
type = string
}

variable "linuxboxsshkey" {
description = "The SSH public key to be used for authentication to the virtual machine."
type = string
}

variable "blob_url" {
description = "The URL of the blob"
type = string
}

variable "blob_name" {
description = "The blob with script name"
type = string
}
49 changes: 49 additions & 0 deletions modules/network/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
resource "azurerm_virtual_network" "vnet" {
name = var.virtual_network_name
address_space = var.vnet_address_prefix
location = var.location
resource_group_name = var.resource_group_name
}

resource "azurerm_subnet" "subnet" {
name = var.subnet_name
resource_group_name = var.resource_group_name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefixes = var.subnet_address_prefix
}

resource "azurerm_network_security_group" "defaultnsg" {
name = var.network_security_group_name
location = var.location
resource_group_name = var.resource_group_name

dynamic "security_rule" {
for_each = var.nsg_rules

content {
name = security_rule.value["name"]
priority = security_rule.value["priority"]
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = security_rule.value["destination_port_range"]
source_address_prefix = "*"
destination_address_prefix = "*"
}
}
}

resource "random_integer" "dns_suffix" {
min = 1
max = 9999
}

resource "azurerm_public_ip" "linuxboxpip" {
name = var.public_ip_address_name
resource_group_name = var.resource_group_name
location = var.location
allocation_method = "Dynamic"
sku = "Basic"
domain_name_label = "${var.dns_label}${random_integer.dns_suffix.result}"
}
15 changes: 15 additions & 0 deletions modules/network/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
output "vnet" {
value = azurerm_virtual_network.vnet
}

output "subnet" {
value = azurerm_subnet.subnet
}

output "nsg" {
value = azurerm_network_security_group.defaultnsg
}

output "public_ip" {
value = azurerm_public_ip.linuxboxpip
}
61 changes: 61 additions & 0 deletions modules/network/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
variable "location" {
description = "The location where all resources will be deployed."
type = string
}

variable "resource_group_name" {
description = "The name of the resource group that will contain all the resources."
type = string
}

variable "dns_label" {
description = "The DNS label assigned to the public IP address."
type = string
}

variable "vnet_address_prefix" {
description = "The address prefix for the virtual network, in CIDR format."
type = list(string)
}

variable "subnet_address_prefix" {
description = "The address prefix for the subnet, in CIDR format."
type = list(string)
}

variable "virtual_network_name" {
description = "The name of the virtual network to be created."
type = string
}

variable "subnet_name" {
description = "The name of the subnet within the virtual network."
type = string
}

variable "network_security_group_name" {
description = "The name of the network security group associated with the subnet."
type = string
}

variable "nsg_rules" {
description = "A list of objects defining the NSG rules. Each rule object should include a name, priority, and destination port range. The rules will be applied with Inbound direction, Allow access, and TCP protocol by default."
type = list(object({
name = string
priority = number
destination_port_range = string
}))

default = [
{
name = "SSH",
priority = 100,
destination_port_range = "22"
}
]
}

variable "public_ip_address_name" {
description = "The name of the public IP address resource with dynamic allocation method."
type = string
}
27 changes: 27 additions & 0 deletions modules/storage/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
resource "azurerm_storage_account" "main" {
name = var.storage_account_name
resource_group_name = var.resource_group_name
location = var.location
account_tier = "Standard"
account_replication_type = "LRS"
}

resource "azurerm_storage_container" "task_artifacts" {
name = var.task_artifacts_container_name
storage_account_name = azurerm_storage_account.main.name
container_access_type = "private"
}

resource "azurerm_storage_container" "script" {
name = "${var.storage_account_name}-script-storage"
storage_account_name = azurerm_storage_account.main.name
container_access_type = "container"
}

resource "azurerm_storage_blob" "script-blob" {
name = "${var.storage_account_name}-blob"
storage_account_name = azurerm_storage_account.main.name
storage_container_name = azurerm_storage_container.script.name
type = "Block"
source = "C:/Users/User.SHU/projects/terraform/devops_todolist_terraform_task/install-app.sh"
}
11 changes: 11 additions & 0 deletions modules/storage/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
output "storage_account" {
value = azurerm_storage_account.main
}

output "task_artifacts_storage_container" {
value = azurerm_storage_container.task_artifacts
}

output "storage_blob" {
value = azurerm_storage_blob.script-blob
}
Loading