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