Skip to content
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
9 changes: 5 additions & 4 deletions .github/workflows/terraform-validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,14 @@ jobs:
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3

- name: Check resource group configuration
# # TODO: The test must be fixed in the main branch. Resource group must exist before terraform init
- name: Check resource group data source
run: |
if ! grep -q 'resource "azurerm_resource_group"' main.tf; then
echo "Resource group configuration not found in main.tf!"
if ! grep -q 'data "azurerm_resource_group"' main.tf; then
echo "Resource group data source not found in main.tf!"
exit 1
fi
echo "Resource group configuration is present."
echo "Resource group data source is present."

- name: Check storage account configuration
run: |
Expand Down
37 changes: 37 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Local .terraform directories
.terraform/

# .tfstate files
*.tfstate
*.tfstate.*

# Crash log files
crash.log
crash.*.log

# Exclude all .tfvars files, which are likely to contain sensitive data, such as
# password, private keys, and other secrets. These should not be part of version
# control as they are data points which are potentially sensitive and subject
# to change depending on the environment.
*.tfvars.json
Comment thread
kenu21 marked this conversation as resolved.
Comment thread
kenu21 marked this conversation as resolved.
*.tfvars

# Ignore override files as they are usually used to override resources locally and so
# are not checked in
override.tf
override.tf.json
*_override.tf
*_override.tf.json

# Ignore transient lock info files created by terraform apply
.terraform.tfstate.lock.info

# Include override files you do wish to add to version control using negated pattern
# !example_override.tf

# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
# example: *tfplan*

# Ignore CLI configuration files
.terraformrc
terraform.rc
41 changes: 41 additions & 0 deletions .terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

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" {
resource_group_name = "mate-azure-task-12"
storage_account_name = "yuriikeniustorageaccount"
Comment thread
kenu21 marked this conversation as resolved.
Comment thread
kenu21 marked this conversation as resolved.
Comment thread
kenu21 marked this conversation as resolved.
container_name = "tfstate"
key = "terraform.tfstate"
}
}
18 changes: 9 additions & 9 deletions install-app.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@
# 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
sudo apt-get update -yq
sudo apt-get install python3-pip -yq
Comment thread
kenu21 marked this conversation as resolved.

# Create a directory for the app and download the files.
mkdir /app
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
git clone https://github.com/kenu21/azure_task_12_deploy_app_with_vm_extention.git
sudo cp -r azure_task_12_deploy_app_with_vm_extention/app/* /app

# 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
systemctl enable todoapp
sudo mv /app/todoapp.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl start todoapp
sudo systemctl enable todoapp
58 changes: 58 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "4.52.0"
}
}
}

provider "azurerm" {
features {}

subscription_id = var.subscription_id
}
Comment thread
kenu21 marked this conversation as resolved.

data "azurerm_resource_group" "rg" {
name = var.resource_group_name
}
Comment thread
kenu21 marked this conversation as resolved.
Comment thread
kenu21 marked this conversation as resolved.

module "network" {
source = "./modules/network"

resource_group_name = var.resource_group_name
location = var.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_prefix = var.dns_label
vm_name = var.vm_name
}

module "storage" {
source = "./modules/storage"

resource_group_name = var.resource_group_name
location = var.location
storage_account_name = var.storage_account_name
install_app_script_path = var.install_app_script_path
}

module "compute" {
source = "./modules/compute"

resource_group_name = var.resource_group_name
subnet_id = module.network.subnet_id
public_ip_id = module.network.public_ip_id
location = var.location
vm_name = var.vm_name
admin_username = var.admin_username
admin_ssh_key = var.ssh_key_public
vm_size = var.vm_size
storage_account_name = var.storage_account_name
storage_account_key = module.storage.storage_account_primary_key
container_name = var.container_name
}
65 changes: 65 additions & 0 deletions modules/compute/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
resource "azurerm_network_interface" "vm_nic" {
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_id
}
}

resource "azurerm_linux_virtual_machine" "vm" {
name = var.vm_name
resource_group_name = var.resource_group_name
location = var.location
size = var.vm_size
admin_username = var.admin_username

network_interface_ids = [
azurerm_network_interface.vm_nic.id,
]

admin_ssh_key {
username = var.admin_username
public_key = var.admin_ssh_key
}

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

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

resource "azurerm_virtual_machine_extension" "custom_script" {
name = "install-app"
virtual_machine_id = azurerm_linux_virtual_machine.vm.id
publisher = "Microsoft.Azure.Extensions"
type = "CustomScript"
type_handler_version = "2.1"

settings = jsonencode({
fileUris = [
"https://${var.storage_account_name}.blob.core.windows.net/${var.container_name}/install-app.sh"
]
commandToExecute = "bash install-app.sh"
})

protected_settings = jsonencode({
storageAccountName = var.storage_account_name
storageAccountKey = var.storage_account_key
})

depends_on = [
azurerm_linux_virtual_machine.vm
]
}
Empty file added modules/compute/outputs.tf
Empty file.
54 changes: 54 additions & 0 deletions modules/compute/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
variable "subnet_id" {
description = "ID of the subnet for the VM's network interface"
type = string
}

variable "public_ip_id" {
description = "ID of the Public IP assigned to the VM's network interface"
type = string
}

variable "resource_group_name" {
description = "Name of the resource group"
type = string
}

variable "location" {
description = "Azure region for resources"
type = string
}

variable "vm_name" {
description = "Name of the virtual machine"
type = string
}

variable "admin_username" {
description = "Admin username for the virtual machine"
type = string
}

variable "admin_ssh_key" {
description = "SSH public key for the virtual machine"
type = string
}

variable "vm_size" {
description = "Size of the virtual machine"
type = string
}

variable "storage_account_name" {
description = "Storage account name where install-app.sh script is stored"
type = string
}

variable "storage_account_key" {
description = "Storage account key for accessing the script"
type = string
}

variable "container_name" {
description = "Container name where install-app.sh script is stored"
type = string
}
56 changes: 56 additions & 0 deletions modules/network/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
resource "random_integer" "dns_suffix" {
min = 1000
max = 9999
}

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" "default" {
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 = [
{ name = "Allow-SSH", priority = 100, direction = "Inbound", access = "Allow", protocol = "Tcp", port = 22 },
{ name = "Allow-HTTP", priority = 200, direction = "Inbound", access = "Allow", protocol = "Tcp", port = 80 },
{ name = "Allow-HTTP2", priority = 300, direction = "Inbound", access = "Allow", protocol = "Tcp", port = 8080 }
]
content {
name = security_rule.value.name
priority = security_rule.value.priority
direction = security_rule.value.direction
access = security_rule.value.access
protocol = security_rule.value.protocol
source_port_range = "*"
destination_port_range = security_rule.value.port
source_address_prefix = "*"
destination_address_prefix = "*"
}
}
}

resource "azurerm_subnet_network_security_group_association" "default" {
subnet_id = azurerm_subnet.default.id
network_security_group_id = azurerm_network_security_group.defaultnsg.id
}

resource "azurerm_public_ip" "linuxboxpip" {
name = var.public_ip_address_name
location = var.location
resource_group_name = var.resource_group_name
allocation_method = "Static"
Comment thread
kenu21 marked this conversation as resolved.
Comment thread
kenu21 marked this conversation as resolved.
Comment thread
kenu21 marked this conversation as resolved.
domain_name_label = "${var.dns_label_prefix}${random_integer.dns_suffix.result}"
}
9 changes: 9 additions & 0 deletions modules/network/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
output "subnet_id" {
description = "The ID of the subnet used for the virtual machine."
value = azurerm_subnet.default.id
}

output "public_ip_id" {
description = "The ID of the Public IP address associated with the virtual machine."
value = azurerm_public_ip.linuxboxpip.id
}
Loading