diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..dbfd8e1
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+.terraform/
+*.tfstate
+*.tfstate.*
\ No newline at end of file
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..ea7ed09
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,5 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
diff --git a/.idea/devops_todolist_terraform_task.iml b/.idea/devops_todolist_terraform_task.iml
new file mode 100644
index 0000000..aa1d160
--- /dev/null
+++ b/.idea/devops_todolist_terraform_task.iml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..c52c0f4
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..718fab5
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..4d150b8
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/terraform.xml b/.idea/terraform.xml
new file mode 100644
index 0000000..03fd66c
--- /dev/null
+++ b/.idea/terraform.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..c8397c9
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.terraform.lock.hcl b/.terraform.lock.hcl
new file mode 100644
index 0000000..d5aba9f
--- /dev/null
+++ b/.terraform.lock.hcl
@@ -0,0 +1,42 @@
+# This file is maintained automatically by "terraform init".
+# Manual edits may be lost in future updates.
+
+provider "registry.terraform.io/hashicorp/azurerm" {
+ version = "3.105.0"
+ constraints = "3.105.0"
+ hashes = [
+ "h1:MK83TecMdabDD+HjbxdTt3emXp8G6djLj7KvvUGstM0=",
+ "zh:2f81bca6a3bf3d37604bf99fdb2c77d6118520aa379ab65fd28e6b76bed399cd",
+ "zh:3578eb79d175af9544b0dc543124d551c0fed4c48f51773ee17e1dc62e22833a",
+ "zh:377dbb56caea3fa1e6a6599193b55c8594204c40c054fc2ace4f576fdfe750a2",
+ "zh:3d1cf01929cb213ff9a0f9753e35699bf13f60f7f0f15b38f1b216fa2cbb5f72",
+ "zh:481376d79224a0e4aebc6e39dee10de3cc14efd1c7c58b6d74c538e356cf4bb2",
+ "zh:625119aec0d24ff693c589d802b7983ffce3fcf1e9c3351396af02799dd176ca",
+ "zh:65981e62a6e9eb8a39dd332632617e8c929dcce6af48d3829f590f5c0f14362f",
+ "zh:72db82697f4e694c21defa8d0efb22f71d373676d078d71d567e8b4d9a134df7",
+ "zh:a0fa43cf78716ff98eccd7506b017c5c487034d9d9cce88c1accdba9314a4822",
+ "zh:b073f60b68b0102128815251dd895ec7f24bddec84a1b725fc0777de8a78dc7e",
+ "zh:b601e509eb9735756b6b7ccacc15d6333769a7bb2f8ac8c394e39b29cfc6ee55",
+ "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
+ ]
+}
+
+provider "registry.terraform.io/hashicorp/random" {
+ version = "3.9.0"
+ hashes = [
+ "h1:q/uaUTBdKgAmZESrwsoeDQff9uUA/cI/N5ZKNgVwa9c=",
+ "zh:161ad0bd9a75768c82f53fb6e7172a9d8be2d4889b012645a34795031aaf1bf1",
+ "zh:19dc9a5b17729725ccfc4f45b0500af0ee5bc6b6b160c7adb8f2bf617d2c80ea",
+ "zh:269eda8fe42daa7974d5a34d166c3ba9defe80cde86c01e4dadcfdf2e1f05e5f",
+ "zh:373f7c65566f8f2cc7f45d698654feb9d988996957e1266a69ca00c52d6d16d0",
+ "zh:5599d16804c41c83009ec621b6d6b6f74e102f5827678a4750f8809055546b61",
+ "zh:583be0440469a22bff70dcfa56593b01566860b29607437264adb51060cf46fc",
+ "zh:5f211d8ec3f2e1f414870d9584bfe26e6995560ef81c748f8447a48164767398",
+ "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
+ "zh:7b547fd16216761ef86efc3ed516ac5ac0c5c42b7c7eb24a08cef2d93f69ed5e",
+ "zh:7e7c0679daf2a382151d05068c8c3f0dae6b7b7dccf818827b73dd08638df2ef",
+ "zh:8089dec888a8038b9b4fb23b3df7e1057293dbc5b60b42cc47ff690d69d4b61b",
+ "zh:c51f15a031edfd6f23ce8ced3446ca7f8d8d647e2499890d7d5d10d5016d7257",
+ "zh:c94784f005708890dc6895afd53636ec00ec1e430b15d41e5aebfb1d4b39bd04",
+ ]
+}
diff --git a/backend.tf b/backend.tf
new file mode 100644
index 0000000..4c08278
--- /dev/null
+++ b/backend.tf
@@ -0,0 +1,16 @@
+terraform {
+ required_providers {
+ azurerm = {
+ source = "hashicorp/azurerm"
+ version = "3.105.0"
+ }
+ }
+
+ backend "azurerm" {
+ resource_group_name = "mate-azure-task-12"
+ storage_account_name = "storagejghae7"
+ container_name = "task-artifacts"
+ key = "terraform.tfstate"
+ }
+}
+
diff --git a/install-app.sh b/install-app.sh
index 03706de..fed0cf9 100644
--- a/install-app.sh
+++ b/install-app.sh
@@ -13,7 +13,11 @@ 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//azure_task_12_deploy_app_with_vm_extention.git
+git clone https://github.com/Xandane/devops_todolist_terraform_task.git
+cd /app
+pip3 install -r requirements.txt
+sudo python3 manage.py migrate
+python3 manage.py collectstatic --noinput
cp -r devops_todolist_terraform_task/app/* /app
# create a service for the app via systemctl and start the app
diff --git a/main.tf b/main.tf
new file mode 100644
index 0000000..83371a1
--- /dev/null
+++ b/main.tf
@@ -0,0 +1,57 @@
+provider "azurerm" {
+ features {}
+ subscription_id = "6a8d93ad-791e-41b1-a745-b6c493b83991"
+}
+
+
+
+resource "azurerm_resource_group" "example" {
+ name = var.resource_group_name
+ location = var.location
+}
+
+
+module "compute" {
+ source = "./modules/compute"
+ network_security_group_id = module.network.network_security_group_id
+ resource_group_name = azurerm_resource_group.example.name
+ location = azurerm_resource_group.example.location
+
+ vm_name = var.vm_name
+ vm_size = var.vm_size
+ ssh_key_public = var.ssh_key_public
+
+ public_ip_address_name = var.public_ip_address_name
+ subnet_id = module.network.subnet_id
+ public_ip_id = module.network.public_ip_id
+
+ storage_account_name = module.storage.storage_account_name
+ storage_account_key = module.storage.primary_access_key
+ script_blob_url = module.storage.script_blob_url
+
+ depends_on = [module.storage]
+}
+
+module "network" {
+ source = "./modules/network"
+ resource_group_name = azurerm_resource_group.example.name
+ location = azurerm_resource_group.example.location
+ vnet_address_prefix = var.vnet_address_prefix
+ virtual_network_name = var.virtual_network_name
+ 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
+ public_ip_allocation_method = "Dynamic"
+
+}
+
+
+module "storage" {
+ source = "./modules/storage"
+ resource_group_name = var.resource_group_name
+ location = var.location
+ storage_container_name = var.storage_container_name
+ storage_account_key = var.storage_account_key
+ storage_account_name = module.storage.storage_account_name
+}
diff --git a/modules/compute/main.tf b/modules/compute/main.tf
new file mode 100644
index 0000000..4d48e1b
--- /dev/null
+++ b/modules/compute/main.tf
@@ -0,0 +1,88 @@
+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_id
+
+ }
+}
+
+resource "azurerm_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
+ ]
+ vm_size = var.vm_size
+
+
+
+
+
+ # Uncomment this line to delete the OS disk automatically when deleting the VM
+ # delete_os_disk_on_termination = true
+
+ # Uncomment this line to delete the data disks automatically when deleting the VM
+ # delete_data_disks_on_termination = true
+
+ storage_image_reference {
+ publisher = "Canonical"
+ offer = "0001-com-ubuntu-server-jammy"
+ sku = "22_04-lts"
+ version = "latest"
+ }
+
+ storage_os_disk {
+ name = "myosdisk1"
+ caching = "ReadWrite"
+ create_option = "FromImage"
+ managed_disk_type = "Standard_LRS"
+ }
+
+ os_profile {
+ computer_name = "hostname"
+ admin_username = "testadmin"
+ }
+
+ os_profile_linux_config {
+ disable_password_authentication = true
+ ssh_keys {
+ key_data = var.ssh_key_public
+ path = "/home/testadmin/.ssh/authorized_keys"
+ }
+}
+
+ tags = {
+ environment = "staging"
+ }
+}
+
+resource "azurerm_virtual_machine_extension" "main" {
+ name = "install-app"
+ virtual_machine_id = azurerm_virtual_machine.main.id
+
+ publisher = "Microsoft.Azure.Extensions"
+ type = "CustomScript"
+ type_handler_version = "2.1"
+
+ settings = jsonencode({
+ fileUris = [
+ var.script_blob_url
+ ]
+
+ commandToExecute = "sudo bash install-app.sh"
+ })
+}
+
+
+
+resource "azurerm_network_interface_security_group_association" "example" {
+ network_interface_id = azurerm_network_interface.main.id
+ network_security_group_id = var.network_security_group_id
+}
+
diff --git a/modules/compute/outputs.tf b/modules/compute/outputs.tf
new file mode 100644
index 0000000..6accc89
--- /dev/null
+++ b/modules/compute/outputs.tf
@@ -0,0 +1,17 @@
+output "vm_name" {
+ value = azurerm_virtual_machine.main.name
+}
+output "vm_id" {
+ value = azurerm_virtual_machine.main.id
+}
+output "network_interface_id" {
+ value = azurerm_network_interface.main.id
+}
+output "public_ip_address_name" {
+ value = var.public_ip_address_name
+}
+output "nic_id" {
+ value = azurerm_network_interface.main.id
+}
+
+
diff --git a/modules/compute/variables.tf b/modules/compute/variables.tf
new file mode 100644
index 0000000..46f5e5a
--- /dev/null
+++ b/modules/compute/variables.tf
@@ -0,0 +1,46 @@
+variable "subnet_id" {
+ type = string
+}
+variable "public_ip_id" {
+ type = string
+}
+variable "vm_name" {
+ type = string
+}
+variable "vm_size" {
+ type = string
+}
+
+variable "resource_group_name" {
+ type = string
+}
+
+variable "location" {
+ type = string
+}
+
+
+variable "ssh_key_public" {
+ type = string
+}
+
+variable "storage_account_name" {
+ type = string
+}
+
+variable "public_ip_address_name" {
+ type = string
+}
+
+variable "storage_account_key" {
+ type = string
+}
+
+variable "script_blob_url" {
+ type = string
+}
+
+variable "network_security_group_id" {
+ description = "Network Security Group ID"
+ type = string
+}
diff --git a/modules/network/main.tf b/modules/network/main.tf
new file mode 100644
index 0000000..19b0acb
--- /dev/null
+++ b/modules/network/main.tf
@@ -0,0 +1,86 @@
+terraform {
+ required_providers {
+ azurerm = {
+ source = "hashicorp/azurerm"
+ }
+ }
+}
+
+
+provider "azurerm" {
+ features {}
+}
+
+resource "random_id" "dns_suffix" {
+ byte_length = 2
+}
+
+
+
+resource "azurerm_public_ip" "example" {
+ name = var.public_ip_address_name
+ resource_group_name = var.resource_group_name
+ location = var.location
+ allocation_method = "Static"
+ domain_name_label = "matetask${random_id.dns_suffix.dec}"
+ sku = "Standard"
+
+ tags = {
+ environment = "Production"
+ }
+
+
+ lifecycle {
+ create_before_destroy = true
+ }
+}
+
+resource "azurerm_virtual_network" "example" {
+ name = var.virtual_network_name
+ address_space = [var.vnet_address_prefix]
+ location = var.location
+ resource_group_name = var.resource_group_name
+}
+
+resource "azurerm_subnet" "example" {
+ name = var.subnet_name
+ resource_group_name = var.resource_group_name
+ virtual_network_name = azurerm_virtual_network.example.name
+ address_prefixes = [var.subnet_address_prefix]
+}
+
+resource "azurerm_network_security_group" "example" {
+ name = var.network_security_group_name
+ location = var.location
+ resource_group_name = var.resource_group_name
+
+ security_rule {
+ name = "test123"
+ priority = 100
+ direction = "Inbound"
+ access = "Allow"
+ protocol = "Tcp"
+ source_port_range = "*"
+ destination_port_range = "22"
+ source_address_prefix = "*"
+ destination_address_prefix = "*"
+ }
+
+ security_rule {
+ name = "allow-http"
+ priority = 1001
+ direction = "Inbound"
+ access = "Allow"
+ protocol = "Tcp"
+ source_port_range = "*"
+ destination_port_range = "8080"
+ source_address_prefix = "*"
+ destination_address_prefix = "*"
+ }
+
+
+ tags = {
+ environment = "staging"
+ }
+}
+
diff --git a/modules/network/outputs.tf b/modules/network/outputs.tf
new file mode 100644
index 0000000..d040fd6
--- /dev/null
+++ b/modules/network/outputs.tf
@@ -0,0 +1,16 @@
+output "subnet_id" {
+ value = azurerm_subnet.example.id
+}
+output "public_ip_id" {
+ value = azurerm_public_ip.example.id
+}
+output "public_ip_address" {
+ value = azurerm_public_ip.example.ip_address
+}
+
+output "network_security_group_id" {
+ value = azurerm_network_security_group.example.id
+}
+
+
+
diff --git a/modules/network/variables.tf b/modules/network/variables.tf
new file mode 100644
index 0000000..4fca7b6
--- /dev/null
+++ b/modules/network/variables.tf
@@ -0,0 +1,43 @@
+
+
+variable "public_ip_address_name" {
+ description = ""
+ type = string
+}
+
+variable "public_ip_allocation_method" {
+ description = ""
+ type = string
+}
+
+variable "virtual_network_name" {
+ description = ""
+ type = string
+}
+
+variable "subnet_name" {
+ description = ""
+ type = string
+}
+
+variable "network_security_group_name" {
+ description = ""
+ type = string
+}
+
+
+variable "resource_group_name" {
+ type = string
+}
+
+variable "location" {
+ type = string
+}
+
+variable "vnet_address_prefix" {
+ type = string
+}
+
+variable "subnet_address_prefix" {
+ type = string
+}
\ No newline at end of file
diff --git a/modules/storage/main.tf b/modules/storage/main.tf
new file mode 100644
index 0000000..e4ab31f
--- /dev/null
+++ b/modules/storage/main.tf
@@ -0,0 +1,33 @@
+resource "random_string" "suffix" {
+ length = 6
+ special = false
+ upper = false
+}
+
+resource "azurerm_storage_account" "example" {
+ name = "storage${random_string.suffix.result}"
+ resource_group_name = var.resource_group_name
+ location = var.location
+ account_tier = "Standard"
+ account_replication_type = "GRS"
+
+
+
+ tags = {
+ environment = "staging"
+ }
+}
+
+resource "azurerm_storage_container" "example" {
+ name = var.storage_container_name
+ storage_account_name = azurerm_storage_account.example.name
+ container_access_type = "blob"
+}
+
+resource "azurerm_storage_blob" "script" {
+ name = "install-app.sh"
+ storage_account_name = azurerm_storage_account.example.name
+ storage_container_name = azurerm_storage_container.example.name
+ type = "Block"
+ source = "install-app.sh"
+}
\ No newline at end of file
diff --git a/modules/storage/outputs.tf b/modules/storage/outputs.tf
new file mode 100644
index 0000000..d4b301d
--- /dev/null
+++ b/modules/storage/outputs.tf
@@ -0,0 +1,24 @@
+output "storage_account_name" {
+ value = azurerm_storage_account.example.name
+}
+
+output "storage_container_name" {
+ value = azurerm_storage_container.example.name
+}
+
+output "storage_account_id" {
+ value = azurerm_storage_account.example.id
+}
+
+output "primary_access_key" {
+ value = azurerm_storage_account.example.primary_access_key
+}
+
+output "container_name" {
+ value = azurerm_storage_container.example.name
+}
+
+output "script_blob_url" {
+ value = azurerm_storage_blob.script.url
+}
+
diff --git a/modules/storage/variables.tf b/modules/storage/variables.tf
new file mode 100644
index 0000000..28ba1bf
--- /dev/null
+++ b/modules/storage/variables.tf
@@ -0,0 +1,19 @@
+variable "resource_group_name" {
+ type = string
+}
+
+variable "location" {
+ type = string
+}
+
+variable "storage_account_name" {
+ type = string
+}
+
+variable "storage_container_name" {
+ type = string
+}
+variable "storage_account_key" {
+ description = "Storage account access key"
+ type = string
+}
\ No newline at end of file
diff --git a/outputs.tf b/outputs.tf
new file mode 100644
index 0000000..d4bcee5
--- /dev/null
+++ b/outputs.tf
@@ -0,0 +1,7 @@
+
+output "resource_group_id" {
+ value = azurerm_resource_group.example.id
+}
+output "resource_group_name" {
+ value = azurerm_resource_group.example.name
+}
diff --git a/terraform.tfvars b/terraform.tfvars
new file mode 100644
index 0000000..f240a59
--- /dev/null
+++ b/terraform.tfvars
@@ -0,0 +1,15 @@
+location = "Korea Central"
+resource_group_name = "mate-azure-task-12"
+virtual_network_name = "vnet"
+vnet_address_prefix = "10.0.0.0/16"
+subnet_name = "default"
+subnet_address_prefix = "10.0.0.0/24"
+network_security_group_name = "defaultnsg"
+public_ip_address_name = "linuxboxpip"
+vm_name = "matebox"
+vm_size = "Standard_D2s_v3"
+ssh_key_public = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDJLJItpBN0pq2liPeZaX8mEfFs02hO1WwpwI93YbGy6b2G5DL99O96NP7a3UR9q2O8727sWDSvjX3yusUmbnw6G++vop+Fe98y22Yf5MABhAbglHkV3db0w1ZRvegCD0yp+NtebeCK4NHHZwIA4LD3yhWkmoJ4hpeM6n+EkhiPQnLZ7ZYn7RNpWMGEjyjGOzbA2UPVfV9FvGw8O1lXQqUKovbNMN6YrJFR0bPKKcabHTwn7F3p1m5j1acjiJyxqEsRusK3JAHvRVQxQne21wwU/SBBeMbcAG4/6m9t/GKtrX8naD/OIomWVro8rnoP3GlF6Nm7YAdZTJEBF45KPdqHSroJGmjiJl0tzmc6VlVOE92DLCrnE21IVQkVzvcj9nDyQVY4NQSz6ZqGvac5F5V2yLs10Ua+LU80Mg2UPDlMEBdUwfATNOLxPtmyc8TOj049QB6Ny69ee1JeuDcuDqwlRnoDhMfqB+P7WQiGlPV8Dj2IleOtqhhCGw6mM7To0+uP6KxT/Qpu1TdfOvrvyLEhfTnP4q9FDWbVPq1aidTbzdF+eBocQkyMGsB9APQGyi15VDZZvzUMqFPalHAgcDj6RCZpgzusziVAwFHbartRRCmwwjDcrm8vt8rJAKSvl52J1yPklt0K9iLZGSS5wxMcjeFPGcNSiaxdY7dlWznmRQ=="
+dns_label = "matetask"
+storage_account_name = "yourstorageaccount"
+container_name = "tfstate"
+storage_container_name = "task-artifacts"
diff --git a/variables.tf b/variables.tf
new file mode 100644
index 0000000..151af39
--- /dev/null
+++ b/variables.tf
@@ -0,0 +1,57 @@
+variable "resource_group_name" {
+ type = string
+}
+
+variable "location" {
+ type = string
+}
+
+variable "storage_account_name" {
+ type = string
+}
+
+variable "storage_container_name" {
+ type = string
+}
+
+
+variable "virtual_network_name" {
+ type = string
+}
+
+variable "vnet_address_prefix" {
+ type = string
+}
+
+variable "subnet_name" {
+ type = string
+}
+variable "subnet_address_prefix" {
+ type = string
+}
+variable "network_security_group_name" {
+ type = string
+}
+variable "ssh_key_public" {
+ type = string
+}
+variable "dns_label" {
+ type = string
+}
+variable "vm_name" {
+ type = string
+}
+variable "vm_size" {
+ type = string
+}
+
+variable "container_name" {
+ type = string
+}
+
+variable "public_ip_address_name" {
+ type = string
+}
+variable "storage_account_key" {
+ type = string
+}
\ No newline at end of file