diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..c95757d4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +# Virtual environment +venv/ + +# Python compiled files +*.pyc +__pycache__/ + +# Flask specific files +flask/ + +*.terraform/ +*terraform.tfstate \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..75768fe8 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,38 @@ +# TODO: Step 1 - Use an official Python runtime as a parent image. +FROM --platform=linux/amd64 public.ecr.aws/docker/library/python:3.9.10-slim-buster + +# TODO: Step 2 - Set the working directory in the container +# Set it to /app, a commonly used directory for web applications. +WORKDIR /app + +# TODO: Step 3 - Copy the application files in the container +# Copy the contents of your local directory into the container's /app directory. +COPY . /app + +# Install system dependencies and ODBC driver +RUN apt-get update && apt-get install -y \ + unixodbc unixodbc-dev odbcinst odbcinst1debian2 libpq-dev gcc && \ + apt-get install -y gnupg && \ + apt-get install -y wget && \ + wget -qO- https://packages.microsoft.com/keys/microsoft.asc | apt-key add - && \ + wget -qO- https://packages.microsoft.com/config/debian/10/prod.list > /etc/apt/sources.list.d/mssql-release.list && \ + apt-get update && \ + ACCEPT_EULA=Y apt-get install -y msodbcsql18 && \ + apt-get purge -y --auto-remove wget && \ + apt-get clean + +# Install pip and setuptools +RUN pip install --upgrade pip setuptools + + +# TODO: Step 4 - Install Python packages specified in requirements.txt +# Assuming your requirements.txt is in the same directory as your Dockerfile. +RUN pip install --trusted-host pypi.python.org -r requirements.txt + +# TODO: Step 5 - Expose port 5000 +EXPOSE 5000 + +# TODO: Step 6 - Define Startup Command +# Specify the command that should be executed when the container launches. +# This command should run the file that starts the Flask application. +CMD ["python", "app.py"] diff --git a/README.md b/README.md index 08407749..acd8f2ba 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,8 @@ Welcome to the Web App DevOps Project repo! This application allows you to effic - **Data Validation:** Ensure data accuracy and completeness with required fields, date restrictions, and card number validation. +- **Delivery Date Column:** An additional field is available to capture the Delivery Date of an order. While the feature is currently inactive, it can be activated by merging the changes from the "feature/add-delivery-date" branch into the main branch. + ## Getting Started ### Prerequisites @@ -53,6 +55,51 @@ To run the application, you simply need to run the `app.py` script in this repos - **Database:** The application employs an Azure SQL Database as its database system to store order-related data. +### Docker containerization + +**1. Dockerfile Creation:** +We utilized an official Python runtime as our parent image, specifically public.ecr.aws/docker/library/python:3.9.10-slim-buster. The working directory in the container was set to /app, and the application files were copied into the container's /app directory. +**2. System Dependencies and ODBC Driver Installation:** +System dependencies and the ODBC driver were installed to support the application. The installation process involved updating the package manager, installing necessary dependencies, and configuring the Microsoft ODBC driver. +**3. Pip and Python Package Installation:** +We upgraded pip and setuptools before installing Python packages specified in the requirements.txt file. +**4. Port Exposure and Startup Command:** +The Dockerfile exposed port 5000, which is the port the Flask application runs on. The startup command was set to launch the Flask application. + + +**Usage Instructions:** + +**Docker Image Name:** nmohamed436/azure-end-to-end-devops +Tags: Latest +Ensure Docker is installed on your system. +Build the image using the provided Dockerfile. docker build -t nmohamed436/azure-end-to-end-devops:latest . +Run the container, exposing port 5000. +Access the application on http://localhost:5000. + +**Deployment and Service Manifests:** + +Created Deployment and Service manifests in the application-manifest.yaml file. +Deployment defines the desired state for the application pods, including image, ports, and replicas. +Service defines a ClusterIP service for internal communication within the AKS cluster. +**Deployment Strategy:** + +Chose a RollingUpdate deployment strategy for its gradual and controlled rollout. +Configured a maximum surge and maximum unavailable percentage to manage the deployment process. +This strategy ensures minimal downtime and allows for easy rollback if issues arise during deployment. +**Testing and Validation:** + +Conducted tests to ensure pods are created, containers are running, and the service is accessible. +Validated the application's functionality within the AKS cluster, focusing on critical features. +Monitored pod logs and used kubectl commands to troubleshoot and verify the health of pods. + +**Distribution Plan:** + +For internal users, no port forwarding is needed; users can access the service within the AKS cluster. +External users will require secure access; consider using Ingress controllers for HTTPS traffic. +Utilize RBAC and Network Policies to control access and enhance security. +Deploy the application in a namespace and control access through proper RBAC configurations. + + ## Contributors - [Maya Iuga]([https://github.com/yourusername](https://github.com/maya-a-iuga)) diff --git a/aks-terraform/.terraform.lock.hcl b/aks-terraform/.terraform.lock.hcl new file mode 100644 index 00000000..4f88e89a --- /dev/null +++ b/aks-terraform/.terraform.lock.hcl @@ -0,0 +1,22 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/azurerm" { + version = "3.91.0" + constraints = ">= 3.0.0" + hashes = [ + "h1:8hMFuaTQsZIV69D0J/W+6hSlhRRDzYSpC0Eg9yWYF0o=", + "zh:13928b71b1235783f3f877a799e28fb91e50512b051eb8ccb370500fc140cf3f", + "zh:3264341657e9ff3963d69b0fa088f64665349e2a29b2f3aeb4deee6d9d7584b7", + "zh:467a2ddd2eee26353db65e949bfbe533481ca0fb53c152724380b63a308f11b9", + "zh:6133e57087167b163180df3a77fab0c63b3e11609d139d39db8d3be3d6ec7ccd", + "zh:6df24730bc9247647ffb44832c3c64e45ab731dd83a3592d33d28235a453235a", + "zh:775aae148223a4a86e2dd25533a95a5fea4817085b6c5e643a7192453270cd68", + "zh:89d51148c7c123685d3e2f7e291888a3af009656e5c0ad66235a7c686ecb19d2", + "zh:9c89552051226eeb7c0fc66ad5aa57d1d0f5acc1d56afad06b6596707ae6c85e", + "zh:c4f3bc269837fa3b6ad803de2c7d1125dd791d78a521dcad2e7a63b905a13a53", + "zh:e48f05de1ffdcc998c5ff915570fb0557c7ac1d3af971dd76aff82e66d45bf06", + "zh:f1945716c7b9c23c25ca9fb4a68f27b6cfa25f5d235112c31f9412eba47f93c6", + "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", + ] +} diff --git a/aks-terraform/aks-cluster-module/main.tf b/aks-terraform/aks-cluster-module/main.tf new file mode 100644 index 00000000..4e648389 --- /dev/null +++ b/aks-terraform/aks-cluster-module/main.tf @@ -0,0 +1,26 @@ +resource "azurerm_kubernetes_cluster" "aks_cluster" { + name = var.aks_cluster_name + location = var.cluster_location + resource_group_name = var.resource_group_name + dns_prefix = var.dns_prefix + + default_node_pool { + name = "default" + node_count = 1 + vm_size = "Standard_DS2_v2" + } + + service_principal { + client_id = var.service_principal_client_id + client_secret = var.service_principal_secret + } + + network_profile { + network_plugin = "azure" + network_policy = "calico" + } + tags = { + Terraform = "true" + Environment = "dev" + } +} diff --git a/aks-terraform/aks-cluster-module/outputs.tf b/aks-terraform/aks-cluster-module/outputs.tf new file mode 100644 index 00000000..2f17c1f2 --- /dev/null +++ b/aks-terraform/aks-cluster-module/outputs.tf @@ -0,0 +1,14 @@ +output "aks_cluster_name" { + value = azurerm_kubernetes_cluster.aks_cluster.name + description = "Name of the provisioned AKS cluster" +} + +output "aks_cluster_id" { + value = azurerm_kubernetes_cluster.aks_cluster.id + description = "ID of the provisioned AKS cluster" +} + +output "aks_kubeconfig" { + value = azurerm_kubernetes_cluster.aks_cluster.kube_config_raw + description = "The Kubernetes configuration file for managing the AKS cluster with kubectl." +} \ No newline at end of file diff --git a/aks-terraform/aks-cluster-module/variables.tf b/aks-terraform/aks-cluster-module/variables.tf new file mode 100644 index 00000000..76c4abf1 --- /dev/null +++ b/aks-terraform/aks-cluster-module/variables.tf @@ -0,0 +1,50 @@ +variable "aks_cluster_name" { + type = string + description = "Name of the AKS cluster" +} + +variable "cluster_location" { + type = string + description = "Azure region where the AKS cluster will be deployed" +} + +variable "dns_prefix" { + type = string + description = "DNS prefix of the cluster" +} + +variable "kubernetes_version" { + type = string + description = "Kubernetes version for the AKS cluster" +} + +variable "service_principal_client_id" { + type = string + description = "Client ID for the service principal associated with the cluster" +} + +variable "service_principal_secret" { + type = string + description = "Client Secret for the service principal associated with the cluster" +} + +# Input variables from the networking module +variable "resource_group_name" { + type = string + description = "Name of the Azure Resource Group for networking resources" +} + +variable "vnet_id" { + type = string + description = "ID of the Virtual Network (VNet) created by the networking module" +} + +variable "control_plane_subnet_id" { + type = string + description = "ID of the control plane subnet created by the networking module" +} + +variable "worker_node_subnet_id" { + type = string + description = "ID of the worker node subnet created by the networking module" +} diff --git a/aks-terraform/main.tf b/aks-terraform/main.tf new file mode 100644 index 00000000..8a759fb1 --- /dev/null +++ b/aks-terraform/main.tf @@ -0,0 +1,43 @@ +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = ">=3.0.0" + } + } +} + + +provider "azurerm" { + features {} + + client_id = var.client_id + client_secret = var.client_secret + subscription_id = var.subscription_id + tenant_id = var.tenant_id +} + +module "networking" { + source = "./networking-module" + + resource_group_name = "my-resource-group" + location = "UK South" + vnet_address_space = ["10.0.0.0/16"] +} + +module "aks_cluster" { + source = "./aks-cluster-module" + + aks_cluster_name = "my-resource-group" + cluster_location = "UK South" + dns_prefix = "webapps" + kubernetes_version = "1.28.4" + service_principal_client_id = var.client_id + service_principal_secret = var.client_secret + + resource_group_name = module.networking.resource_group_name + vnet_id = module.networking.vnet_id + control_plane_subnet_id = module.networking.control_plane_subnet_id + worker_node_subnet_id = module.networking.worker_node_subnet_id + +} \ No newline at end of file diff --git a/aks-terraform/networking-module/main.tf b/aks-terraform/networking-module/main.tf new file mode 100644 index 00000000..e3959dd2 --- /dev/null +++ b/aks-terraform/networking-module/main.tf @@ -0,0 +1,59 @@ + resource "azurerm_resource_group" "network" { + name = var.resource_group_name + location = var.location +} + +resource "azurerm_virtual_network" "aks_vnet" { + name = "aks-vnet" + resource_group_name = azurerm_resource_group.network.name + location = var.location + address_space = var.vnet_address_space +} + +resource "azurerm_subnet" "control_plane_subnet" { + name = "control-plane-subnet" + resource_group_name = azurerm_resource_group.network.name + virtual_network_name = azurerm_virtual_network.aks_vnet.name + address_prefixes = ["10.0.1.0/24"] # Replace with the desired subnet address space +} + +resource "azurerm_subnet" "worker_node_subnet" { + name = "worker-node-subnet" + resource_group_name = azurerm_resource_group.network.name + virtual_network_name = azurerm_virtual_network.aks_vnet.name + address_prefixes = ["10.0.2.0/24"] # Replace with the desired subnet address space +} + +resource "azurerm_network_security_group" "aks_nsg" { + name = "aks-nsg" + location = var.location + resource_group_name = azurerm_resource_group.network.name +} + +resource "azurerm_network_security_rule" "kube_apiserver_rule" { + name = "kube-apiserver-rule" + priority = 1001 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_port_range = "*" + destination_port_range = "6443" + source_address_prefix = "92.19.71.227/32" # Replace with your public IP address + destination_address_prefix = "*" + resource_group_name = azurerm_resource_group.network.name + network_security_group_name = azurerm_network_security_group.aks_nsg.name +} + +resource "azurerm_network_security_rule" "ssh_rule" { + name = "ssh-rule" + priority = 1002 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_port_range = "*" + destination_port_range = "22" + source_address_prefix = "92.19.71.227/32" # Replace with your public IP address + destination_address_prefix = "*" + resource_group_name = azurerm_resource_group.network.name + network_security_group_name = azurerm_network_security_group.aks_nsg.name +} diff --git a/aks-terraform/networking-module/outputs.tf b/aks-terraform/networking-module/outputs.tf new file mode 100644 index 00000000..b84ce33b --- /dev/null +++ b/aks-terraform/networking-module/outputs.tf @@ -0,0 +1,24 @@ +output "vnet_id" { + description = "ID of the Virtual Network (VNet)" + value = azurerm_virtual_network.aks_vnet.id +} + +output "control_plane_subnet_id" { + description = "ID of the control plane subnet within the VNet" + value = azurerm_subnet.control_plane_subnet.id +} + +output "worker_node_subnet_id" { + description = "ID of the worker node subnet within the VNet" + value = azurerm_subnet.worker_node_subnet.id +} + +output "resource_group_name" { + description = "Name of the Azure Resource Group for networking resources" + value = azurerm_resource_group.network.name +} + +output "aks_nsg_id" { + description = "ID of the Network Security Group (NSG)" + value = azurerm_network_security_group.aks_nsg.id +} diff --git a/aks-terraform/networking-module/variables.tf b/aks-terraform/networking-module/variables.tf new file mode 100644 index 00000000..67824182 --- /dev/null +++ b/aks-terraform/networking-module/variables.tf @@ -0,0 +1,18 @@ +variable "resource_group_name" { + description = "Name of the Azure Resource Group" + type = string + default = "my-resource-group" +} + +variable "location" { + description = "Azure region for networking resources" + type = string + default = "UK South" +} + +variable "vnet_address_space" { + description = "Address space for the Virtual Network (VNet)" + type = list(string) + default = ["10.0.0.0/16"] +} + diff --git a/aks-terraform/terraform.tfstate.backup b/aks-terraform/terraform.tfstate.backup new file mode 100644 index 00000000..28d6c2ed --- /dev/null +++ b/aks-terraform/terraform.tfstate.backup @@ -0,0 +1,467 @@ +{ + "version": 4, + "terraform_version": "1.7.2", + "serial": 17, + "lineage": "88eec9bf-9edd-e874-0f12-82a581de4c64", + "outputs": {}, + "resources": [ + { + "module": "module.aks_cluster", + "mode": "managed", + "type": "azurerm_kubernetes_cluster", + "name": "aks_cluster", + "provider": "provider[\"registry.terraform.io/hashicorp/azurerm\"]", + "instances": [ + { + "schema_version": 2, + "attributes": { + "aci_connector_linux": [], + "api_server_access_profile": [], + "api_server_authorized_ip_ranges": [], + "auto_scaler_profile": [], + "automatic_channel_upgrade": "", + "azure_active_directory_role_based_access_control": [], + "azure_policy_enabled": null, + "confidential_computing": [], + "custom_ca_trust_certificates_base64": [], + "default_node_pool": [ + { + "capacity_reservation_group_id": "", + "custom_ca_trust_enabled": false, + "enable_auto_scaling": false, + "enable_host_encryption": false, + "enable_node_public_ip": false, + "fips_enabled": false, + "gpu_instance": "", + "host_group_id": "", + "kubelet_config": [], + "kubelet_disk_type": "OS", + "linux_os_config": [], + "max_count": 0, + "max_pods": 30, + "message_of_the_day": "", + "min_count": 0, + "name": "default", + "node_count": 1, + "node_labels": {}, + "node_network_profile": [], + "node_public_ip_prefix_id": "", + "node_taints": [], + "only_critical_addons_enabled": false, + "orchestrator_version": "1.27.7", + "os_disk_size_gb": 128, + "os_disk_type": "Managed", + "os_sku": "Ubuntu", + "pod_subnet_id": "", + "proximity_placement_group_id": "", + "scale_down_mode": "Delete", + "snapshot_id": "", + "tags": {}, + "temporary_name_for_rotation": "", + "type": "VirtualMachineScaleSets", + "ultra_ssd_enabled": false, + "upgrade_settings": [], + "vm_size": "Standard_DS2_v2", + "vnet_subnet_id": "", + "workload_runtime": "", + "zones": [] + } + ], + "disk_encryption_set_id": "", + "dns_prefix": "webapps", + "dns_prefix_private_cluster": "", + "edge_zone": "", + "enable_pod_security_policy": false, + "fqdn": "webapps-g3tbby17.hcp.uksouth.azmk8s.io", + "http_application_routing_enabled": null, + "http_application_routing_zone_name": null, + "http_proxy_config": [], + "id": "/subscriptions/d394a330-57cd-464c-aa69-f9ec5551d2c8/resourceGroups/my-resource-group/providers/Microsoft.ContainerService/managedClusters/my-resource-group", + "identity": [], + "image_cleaner_enabled": false, + "image_cleaner_interval_hours": 48, + "ingress_application_gateway": [], + "key_management_service": [], + "key_vault_secrets_provider": [], + "kube_admin_config": [], + "kube_admin_config_raw": "", + "kube_config": [ + { + "client_certificate": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZIakNDQXdhZ0F3SUJBZ0lSQUxHVEVvUnZyZUUxNkU5SGw2UlUydU13RFFZSktvWklodmNOQVFFTEJRQXcKRFRFTE1Ba0dBMVVFQXhNQ1kyRXdIaGNOTWpRd01qQTRNVFl6TURFM1doY05Nall3TWpBNE1UWTBNREUzV2pBdwpNUmN3RlFZRFZRUUtFdzV6ZVhOMFpXMDZiV0Z6ZEdWeWN6RVZNQk1HQTFVRUF4TU1iV0Z6ZEdWeVkyeHBaVzUwCk1JSUNJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBZzhBTUlJQ0NnS0NBZ0VBNTdFVTZoV0ZvVkpUdUkzeXhPaU0KMWxtMXJwNWlNSGpRYkVuU0RvRlI5alY1R2NCcC9wTnF1UDNXQ3E3VlVEbGViTlBXQ1BiR2wzdzVXRUdBYUdHOApwU3Z4OVFSU0xYUkpGMWFxb0NOQTlPbHkraGhLeWFKbGNIaEVxbmkxRHBEWDRmQjJhVHVMV2dnbGZ3cjZOVnhtCmJMbFErdlFmRmNCNGxZN1ViRVNOQ0g4djU0UDNrMmt1M1VRSjBzWlVWZ05VVVB0SzRMeXJzWThqMkxFR0FocXkKV0JmNjNpbnNnc2ZKSmxleWJKeUw3TEk2SWxDcU5XL2JEL3NTRllsaW1YeEhYaTQwYlpSOWlPNndUNXFtS1BvYwpDNExEenpCV1FHZ2VmbWplSytDblhlRmQ5dkJGeVQ2bGRaNUhQb0xMUGZUUnZzckg1T3pDRy8xck9oMXFMS0hoCmkxZk5iQURZWHBqWkVyNnY5Ym1YRGpNV2VNNzZobjRydE5zNDlvOE1SUHVYb2QwN2RCdmtOUGJrb1czVkRvUm8Kcm4raHdGbFBFUlNXdC9tOFhTOGU1YStuRnh4N0N2UmpLcWVBdzVPRWZvNDNYeVd5MlR1Y2h6djM5SS9seXhLVgpZZEpuRjRCL015RjBDRXpIaWl2QUZ0MEVuenkyUXJNNFBUTGhWUlJHeU9vMy9ZU2tzWnZwNWJDa1FmR0lCWDBPClRveDNvZ3VLRFhobWg5N1A0R3N4VE00L3hSbDVFUkJCTFo5TXZKL1IvT2pKVkhxU1F5VHpYUXkrdVpSSE1mM2cKTk0zMks2Ris4aHZXNTE0WXpTWUdRL01TT3liNklBS1JpeXZ0cG5Rc0UyUi9vdmFOc29UY0k4MEhlT09QYXdsdQpZS2k5aHI4VmtUQ1pVQzIwL3BPMExiY0NBd0VBQWFOV01GUXdEZ1lEVlIwUEFRSC9CQVFEQWdXZ01CTUdBMVVkCkpRUU1NQW9HQ0NzR0FRVUZCd01DTUF3R0ExVWRFd0VCL3dRQ01BQXdId1lEVlIwakJCZ3dGb0FVR0dmMDVaSDYKT215UGx5akZ1VzBkalQ5bzBlc3dEUVlKS29aSWh2Y05BUUVMQlFBRGdnSUJBRWNWclVUMjAwVlFkcEV6QlFiVQppSlZVdUpYcTk2SHpWVHBGeFFvc2Z5b2YySEZrcFh4Y2M4VWZldEdncWdmMFlxN2laMG54cjhyMU53NExsdjFzCkFiZHNCb2tZZHgzZFlCUmROcXNUdFhNbFNsdHp0ZnFDMjhmTStxV2p4WUhiR09IczI3YnFYWVA1ZHlONjhUb1AKc3VBUnFoUHFNTmRWbUFXUHNTZWZpSDNSRE9JRFZSRzY3emVjWXdEZGpxM1N6cTc0eUYyZWh2THQ5YTRBTjJBegpLMWpPK253dW5kSkFmbWlFa1BXZlRUZ0lTUjZ1V0c0VEExSEJYYzNTR0I3LytteCtzbDJoY202YVpBc04yMTl5CjFKUkUvTS9IOFp4cWRJOVpYc1JldVUrY1IzQXlOQ2ZGUkI1YXdSNks2OFRPZHBQcTA3RnU2VkxxUWlveENDd1AKbVpNek9kTlVRZzVveEJ4TENsRzNoUmZMY25iemIzcE5rb0RMNy9CbHBHRkZlU3Z3MGVRcWI5d2tPMmhIbkxLTQo2SGpRdmJjOTFjQnN6SEwzUFo4N3lGdGs4UGFGWkk0bjF4S2p3d2hxVnNMM1BlbmtHUnNpMU8yempVVVk2ZWI0Clgyc3BhYVplcFVxQmpzWHJ4ZDNRUnFqZEJxQ0x3aWZYK1VFb1JaYnlEKzFIQTZjckZ3UEo5QVRWM0U0VWUxUWQKMWZFWDNmMkRBbk5sNmlyR3d0K3Y0bUxvTHRXK2lkZGR0ODhhdC9ydXdYOXFjeHEvbmQrUFZOMzFlSVhmWlVregpCcGFCd3RQaFJpUytsdDhhMDJoOEtrdGRQNHR6NzA0eUt1T3FaUUJlTzJzdksvNDB6aGNwa3VtOGp6MlVLT3BGCktUcGhxd1ZmUDFXZXBzNkNSQXlwc0xrUgotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==", + "client_key": "LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlKSndJQkFBS0NBZ0VBNTdFVTZoV0ZvVkpUdUkzeXhPaU0xbG0xcnA1aU1IalFiRW5TRG9GUjlqVjVHY0JwCi9wTnF1UDNXQ3E3VlVEbGViTlBXQ1BiR2wzdzVXRUdBYUdHOHBTdng5UVJTTFhSSkYxYXFvQ05BOU9seStoaEsKeWFKbGNIaEVxbmkxRHBEWDRmQjJhVHVMV2dnbGZ3cjZOVnhtYkxsUSt2UWZGY0I0bFk3VWJFU05DSDh2NTRQMwprMmt1M1VRSjBzWlVWZ05VVVB0SzRMeXJzWThqMkxFR0FocXlXQmY2M2luc2dzZkpKbGV5Ykp5TDdMSTZJbENxCk5XL2JEL3NTRllsaW1YeEhYaTQwYlpSOWlPNndUNXFtS1BvY0M0TER6ekJXUUdnZWZtamVLK0NuWGVGZDl2QkYKeVQ2bGRaNUhQb0xMUGZUUnZzckg1T3pDRy8xck9oMXFMS0hoaTFmTmJBRFlYcGpaRXI2djlibVhEak1XZU03NgpobjRydE5zNDlvOE1SUHVYb2QwN2RCdmtOUGJrb1czVkRvUm9ybitod0ZsUEVSU1d0L204WFM4ZTVhK25GeHg3CkN2UmpLcWVBdzVPRWZvNDNYeVd5MlR1Y2h6djM5SS9seXhLVllkSm5GNEIvTXlGMENFekhpaXZBRnQwRW56eTIKUXJNNFBUTGhWUlJHeU9vMy9ZU2tzWnZwNWJDa1FmR0lCWDBPVG94M29ndUtEWGhtaDk3UDRHc3hUTTQveFJsNQpFUkJCTFo5TXZKL1IvT2pKVkhxU1F5VHpYUXkrdVpSSE1mM2dOTTMySzZGKzhodlc1MTRZelNZR1EvTVNPeWI2CklBS1JpeXZ0cG5Rc0UyUi9vdmFOc29UY0k4MEhlT09QYXdsdVlLaTlocjhWa1RDWlVDMjAvcE8wTGJjQ0F3RUEKQVFLQ0FnQWxtQncycDJ0WmM4eFY0K0tDaE9GbFhvVVdZbWk0U01JNDcvbC9sUWhCbFFlallBOVMyWVMxbzZwNQpiVWo3alhOKzRSaVh0OE1kalhDWW0zaEVkNmR1ZmFUekJ0SjJ3YW1pZWRPUnpHYWIxczFyTzBuWFVkeDMxV3YrCjVUc3JzK0R6cmxyb1ZGc1dMc0EyendjdVpXSFJQbmlmWDhFemZGbVVtdXBvN3U2YmRGZkhqeWc2NlJSTG51Q2gKTE1FK2U2ZlF4Qld3UmF6dVVMV1dVWk1TQUZiejZHQXljRWNLS1hUQUhmYTduT012Y3ZQdjRYcmMxTnVNeWtaeQo3Q250a2JiYTExQjJmMk9uTm1PeFp2eVRKWklyWS9wMXdmZ2MxMGdyWnNTMkJldmlWZEV6WW1WUWREUFEwKy9uCmVyMlR2Z2ZTbDRDNzZwYk1oK0JBTzhtZ21GdktPMW5ZSmtPVjdzSFBLOWJUMjVyaVAxNGZWYjNqbkhhNU5aUEoKS0gyRmFYOTVPUldrMHhVc0YwemdKaXZaUG9FY0ZQc01LZmRSZlhYdXA5VmhPemZMZWVpbzh4SWlXOW9XNVduYgpORzMzejRvT1Rob3YzQ2ZrMWVBSi8wQnFUZXJPVzRIcWJLbXBDc1RSYUxEY3dzK1l1OXNsTDhOZE9BdjdHM3RNCnU1cGMvUllsNmVuNWJqbkxQMUdDZXdYVWVxRzlGMFhiY0t5U1BCVWhZR0tERjVyL0MzZk9IbkwrS01XbmtsS20KTzJnOERZQlJJOWU2a0EzUVBmVGo1eWUxTUFQaWUzYm5kS3UzRjdYZ2k1cUNnY3FiYkdtbUl5cVZsUFlZeG4xVApLRFZrVzZmRloza0NYcDlXOGtzaU10azN2QytCSzNTNkFiWndHY1MrMFJQTGRVQXFBUUtDQVFFQTlEZllyeEIvCnIzU0Z0bEhXb01jUkQ3cm1DSWIvUWwrNDZ6VDdBaUpTOGlDOUdBdkkzL1d5YmUwRElaK3ZQUGFHVU91STdMdTQKZCtLNHd0TzZpbzhGTXlZcCtmMmxPcVJWaWFEUGhKdTZXZFVGSkQybmZra0NmR2R1YnFydHNucWpEZnMvR1poQgpQbzg1a2ZCZ3k0TDlpK3MzOGR2K01heVJrckxZemxuUGFvMUpmUUxpbHRxL3EvVUoxV21TQ2dVeWw2NFV2ZSt0Cnh1T215NmM4YWhOajY3WTlHQ21YSEI4Tit2aTdWV1VSRDF2OGt3Z2JyRVRPUWM2NlRTVHNIbTRrUEZGL1VFYXUKeGdVdmpKcU1FcmtsTUZPTmRITUZTemZvNUYrN0ErSnRCaVMwTzFON1VqL3h3WWo2QmkvazU4ZkJ2Tm1aeVhVOAp0dVZQb01ndG9yY2hnUUtDQVFFQTh0Nkg1K2t2SGZuYm5pZUhrUVRQWkZrTmdaNTl5Y2FOSkoza2J0cCtFc2loCmNsb0tjOGhsb3B0STZEVE8rUUZWVjdUSzdHdGxsOXFvRXIvSDJLNVdhQlg0WEF4UUR6NlpDbWUyMng5Y0h5ZUUKNXJsZk93dVArT01aa3dwa0ZYOVJqN0YzMmphV2Zmcm5Kd1Z4ekMwNG9EVmFJRk05RHE5ZU43RWF0R1hQZXE0bApVYnZTOW9tTlVPSTJVTWpucW90YXovcldlWGNQVWM4MHQvaGNnS2hGRTN1VUZZRndWRzdFSFRpWWhVQWI2Q2ErCmFCS0wwT0VDV2lZZVNLTEZMbTRDSSs0VGFVUHJuOWk5elJZYnpWRHhWVWVsRHpHNGpmTjRxbjYycmlUYUFXMXgKblVVTmRuVDNON0VKM2VxMFJXVUM1b3hvRDlzZlhTR2VxOFhhSE1ON053S0NBUUE5d0IwMjdzb0tXRUV5LzNCdwppTVVrb0JKb0Y1SlZleFNyekdLbmdIeE9vcjZOWlBWdXc1WlJPenV1ZGN6K2NpczJMTWdiYTcvUitHN1ZQR29QCmZPaElyWjZ4aWxRTUJ0OW1CRlpVWm5meEhPN0c0aHdHejNra2NaYTN2dHFKWlg3ekd4TXlhcEFjdkdSSEpXdWsKS2NQb2JCcGlPa2tFMEdpaW1qdzl1UEc4Tkd0Zmc2bzlrS1FrVzdvWHp6RFEvYzEwRXQxRnhXUEFSWEc0VHRuMAp6R0JZaW1UYVJqSGlOMnYyaUl2OXBLZHlwY1N3ZkwxYWlxOUlibmdtNTI0WXA2cmI0Wk42ZmRUVlZ4eFZ4Z0lpCi9kT01hNlA1ek5lSzFHRTcxWVRaRDVpWGxCSkthZXBsdXF0clR6SkEvRDA1NmdWdnRlbXZ5Y2dIU3VZZWRsOHIKcEhpQkFvSUJBQXJYNEoxOERieDY0VkZJVm9jay9kVnZIR2xER0Q2Zi9NRTd3MjBubUNWaWk4SzlQbVk0OWtDeQpTaWtENHBHL2UzMzA5bkpqd1I5c2hjQ0FpMzJqR3Z4K3JwMzlkcjJYZitHMUM3Ynd5WDRpbDQ1dGpGRG9qVDhCCmRLelo4K241eXp4dElmcStJUzN5dTh0RU5QWjJ0bWFBdTB0aUxBR3gxclVKMVRWa3JrUzk3YkNlZ0NhOXNXK0IKQ2dmRlVJS093amt5Njh4MGdseVdzYlhkQXRSRHJ3SFZyS0RoTEpDNGVVME1yOUtUTUN2SFB3MEtkdStXZkRKbQpMVWYwN0hUTU9KQStHdVBDUW96YWNtN3JvOFlnN1FWdnMzRGdPV3N0Q2FBakZDam1RRTE4QTJ5UUhxL0JQU0JoCmFSMWRVenNkN1drNXI1TzFwc3JUcTIvajMzOFZRelVDZ2dFQVVxTmw0RVRBVUtSUFd0bDhrYjAzWnFscmVGbE0KWWo5aXYrNWIya0U0SVl6OUs4NkpiQjQwdHJVYmU5aUh1UFJkZEEvVlBqMUJpbCsvT2VBMUZ3NVBmMnJYZXNiSApUamdralRqa0ZUQjR4Yjk0MkVNakRRVGNGU0k1ZkFYL0xkdFN6Y214a0xPOXlkb3hqQUhzK25jNUlPcTFFVXVICkd2aGx1SHpVV05aVkNNNjJVaHR5cGNUT2M4UWtZRXNrdjRjb0RvVmxvS0pKWXhSSmdqb2J0bjBHSENmWTdRREgKOWhEWTNtYm5DTXdDS1VDWm1pU2JIemtCWjZLQ2FHZW1vRC9PcEJHZlAvUmNwUkJLc1pxdVpZUVQrWUZadENqMgpxZnRGOFlpZHhqNUUrUm4zMEF4Vi90SjV2QzJPUXNWTDIrUmViemREbUNlVnY4NGtnbWIvN0NDNW53PT0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0K", + "cluster_ca_certificate": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUU2RENDQXRDZ0F3SUJBZ0lRTmxaSEVHL0QrN2RjV0dUWk0vOXNXREFOQmdrcWhraUc5dzBCQVFzRkFEQU4KTVFzd0NRWURWUVFERXdKallUQWdGdzB5TkRBeU1EZ3hOak13TVRkYUdBOHlNRFUwTURJd09ERTJOREF4TjFvdwpEVEVMTUFrR0ExVUVBeE1DWTJFd2dnSWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUNEd0F3Z2dJS0FvSUNBUURZCmlCYzZ3bmIvWjB2Q3ZybnBsWVNXaUdJeTQ1UXhXQVZRMnNmcGJMZ2tRN1JkR3NlNXJUZU9BU0VSbWkzcUxiZWEKUzRydDlveUM2Q3RUTEgyc0s2L2pyUkdYWmFtT2RvSXBxTFVQN1FpVk5aLzhteXYxSkx6NkM3MW96SHhQSElhTworWktmYUwxT2MrYnVMS2NCK1Y5ZVBsUm5mZGlOOHRTTmN5MFdUbTE2bHdQZHU5SWJLRGwreFhSQmNTL0F4S2htCnhnTTZxcUdvR25qM0dCTWJPK0FSS0ZEdW5QbGkrNFlVQ0lCb3E1TU9DM3NYVnBJREV1NHhvaWJaWndLbUVYcm4KdkNvSElSaDBzN1d5OTl3RjF4bzlOdlpOYkhlR0NmcVhyNEc0a3pQMElKRU9Kd1FUZ0VNWEVDMGVxQUlIWjlvNwpPZEQzY3cwb0pyUXEwUGxsVitOMWRBMXhyZ2k0RmpFTFlVdEVyTmJJWlRYUzhmUHJxVDBaWHBVc0NYQTlDcHZhCmFlMCt2UzROSkJhSDAxTUZNQ0dUS3ZVYWdMRTMzS3hPSU8vNzltVm9DSFZvN2lVVjc2NlVQdVBpeUF4VUVDbCsKU1lJMTR0MkREQU9uNE55NGVyRFdRYnFtNENxYnIwODRkOFl5d0pkd1NkQUozazNLanI4bEJHZldHQzI0MHEwaQpERGUwY0dVL0t1WlBzckp4bVRybDBZVDJXdGlUdDZVOGZ2cHBZUVVHY2VrUUhIVVJnQW04eVo4UzdpRkRwUmhiCmRQT0JOc0Zubzl3RnNaV2lTd1E3K2g2Tk1oTE5tN2dJbmpFYXhLWVgzUDVHVmN4VFBnellDM21rRG1YZmZYWVMKSElVaExIekFVUDBCYmx5SHdrbXVkbXFWdU50YjZoL3BIeUhYSnFWTWl3SURBUUFCbzBJd1FEQU9CZ05WSFE4QgpBZjhFQkFNQ0FxUXdEd1lEVlIwVEFRSC9CQVV3QXdFQi96QWRCZ05WSFE0RUZnUVVHR2YwNVpINk9teVBseWpGCnVXMGRqVDlvMGVzd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dJQkFEKzZDS1JRQVhiNnRrblc2dThYZ2VNY3lPbzUKWlR6SVg4cEJCeDRJMHNXblFKN3QyRUlPNWJnaC8wY1RLUUYzeXAwWnNTMjdLb1ZhWEUzTFZiWHZaSU15VzBZRAoyMnlsWUViRUNIRC9TSWhCdlRjS3ZsckxDc1o0MWhiUStQdktBQjByUGVNcEg4aEVXU3J2dmVqa0lHako0MTFQCkNxMDgvd0ZkbkF1SVRFWFMxUXJKUmdOTk1WTVlYTmdyVE9zbzZBbW4zTE9FMi82YXJ6aGV5WHBDakRmU3BHTUMKbTI2SnZUKzUwaEZSM1VqQ0dwZTN0dERVbWVaTnl3UGpjRDcwZytVL294cmxZb1h2Tjd6WVFtRDBCWEEwN0kvegp4ajRhTkcrQ0pacXp6aU1BdXBsb2xNMjh4bHhiVzNldWtPVUQyQmtyK2lVVXIyTXpyK0dranptUXF0Yi8wdFFjCmN6bStrMHl5SXQ5OUZEV1hXZ3dxN1dMM1dvajZYSVNySVB0R1MxSVpZS0lsRXQ3SzltTTk0WHN6VzRnbGNUN3EKcHFXdTlPbDJ6TUZVZ3NCMVZhSUJBRDJoU091RWhmSjhPYnM5TStsckdLTTk3L2dadXliMTh5L0YwNXEvRllOWAplZHB6aFgyN1Q5azJpcWhxUnJjOC8vWk8wOU5QVjJkamsrZFh2Yjdac016ZHdMTkpheStaUGJNclJHaVIzeVR2CjRUSkRwNnNIUE5JaDFXNG5QdTBWbzBQTFRWZEV2Y2ZtT0F4enlnby9VaHZMcXFXbDJhU0hqdEJYb3hkNTk4RG8KY2kvTnRsdHhYMitRcHpvdjJscWlYN2gxUG1UUDZiTnp1ZHc1SzM4VU9KYlU4eE1NQk5KYklCSmc1dUNkeW1Sdwpveks0M21lQ1JPczBZRjAyCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K", + "host": "https://webapps-g3tbby17.hcp.uksouth.azmk8s.io:443", + "password": "3ht7yaabofxzel0letgciuqv4tbvbbbxoeugfvkjo5n56145dqb4wy47rkofyer9jg56hdapagsx4620delw0j5h00yfn9xca6zfdbu42g0ejie2ca61u4par6qm1bku", + "username": "clusterUser_my-resource-group_my-resource-group" + } + ], + "kube_config_raw": "apiVersion: v1\nclusters:\n- cluster:\n certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUU2RENDQXRDZ0F3SUJBZ0lRTmxaSEVHL0QrN2RjV0dUWk0vOXNXREFOQmdrcWhraUc5dzBCQVFzRkFEQU4KTVFzd0NRWURWUVFERXdKallUQWdGdzB5TkRBeU1EZ3hOak13TVRkYUdBOHlNRFUwTURJd09ERTJOREF4TjFvdwpEVEVMTUFrR0ExVUVBeE1DWTJFd2dnSWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUNEd0F3Z2dJS0FvSUNBUURZCmlCYzZ3bmIvWjB2Q3ZybnBsWVNXaUdJeTQ1UXhXQVZRMnNmcGJMZ2tRN1JkR3NlNXJUZU9BU0VSbWkzcUxiZWEKUzRydDlveUM2Q3RUTEgyc0s2L2pyUkdYWmFtT2RvSXBxTFVQN1FpVk5aLzhteXYxSkx6NkM3MW96SHhQSElhTworWktmYUwxT2MrYnVMS2NCK1Y5ZVBsUm5mZGlOOHRTTmN5MFdUbTE2bHdQZHU5SWJLRGwreFhSQmNTL0F4S2htCnhnTTZxcUdvR25qM0dCTWJPK0FSS0ZEdW5QbGkrNFlVQ0lCb3E1TU9DM3NYVnBJREV1NHhvaWJaWndLbUVYcm4KdkNvSElSaDBzN1d5OTl3RjF4bzlOdlpOYkhlR0NmcVhyNEc0a3pQMElKRU9Kd1FUZ0VNWEVDMGVxQUlIWjlvNwpPZEQzY3cwb0pyUXEwUGxsVitOMWRBMXhyZ2k0RmpFTFlVdEVyTmJJWlRYUzhmUHJxVDBaWHBVc0NYQTlDcHZhCmFlMCt2UzROSkJhSDAxTUZNQ0dUS3ZVYWdMRTMzS3hPSU8vNzltVm9DSFZvN2lVVjc2NlVQdVBpeUF4VUVDbCsKU1lJMTR0MkREQU9uNE55NGVyRFdRYnFtNENxYnIwODRkOFl5d0pkd1NkQUozazNLanI4bEJHZldHQzI0MHEwaQpERGUwY0dVL0t1WlBzckp4bVRybDBZVDJXdGlUdDZVOGZ2cHBZUVVHY2VrUUhIVVJnQW04eVo4UzdpRkRwUmhiCmRQT0JOc0Zubzl3RnNaV2lTd1E3K2g2Tk1oTE5tN2dJbmpFYXhLWVgzUDVHVmN4VFBnellDM21rRG1YZmZYWVMKSElVaExIekFVUDBCYmx5SHdrbXVkbXFWdU50YjZoL3BIeUhYSnFWTWl3SURBUUFCbzBJd1FEQU9CZ05WSFE4QgpBZjhFQkFNQ0FxUXdEd1lEVlIwVEFRSC9CQVV3QXdFQi96QWRCZ05WSFE0RUZnUVVHR2YwNVpINk9teVBseWpGCnVXMGRqVDlvMGVzd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dJQkFEKzZDS1JRQVhiNnRrblc2dThYZ2VNY3lPbzUKWlR6SVg4cEJCeDRJMHNXblFKN3QyRUlPNWJnaC8wY1RLUUYzeXAwWnNTMjdLb1ZhWEUzTFZiWHZaSU15VzBZRAoyMnlsWUViRUNIRC9TSWhCdlRjS3ZsckxDc1o0MWhiUStQdktBQjByUGVNcEg4aEVXU3J2dmVqa0lHako0MTFQCkNxMDgvd0ZkbkF1SVRFWFMxUXJKUmdOTk1WTVlYTmdyVE9zbzZBbW4zTE9FMi82YXJ6aGV5WHBDakRmU3BHTUMKbTI2SnZUKzUwaEZSM1VqQ0dwZTN0dERVbWVaTnl3UGpjRDcwZytVL294cmxZb1h2Tjd6WVFtRDBCWEEwN0kvegp4ajRhTkcrQ0pacXp6aU1BdXBsb2xNMjh4bHhiVzNldWtPVUQyQmtyK2lVVXIyTXpyK0dranptUXF0Yi8wdFFjCmN6bStrMHl5SXQ5OUZEV1hXZ3dxN1dMM1dvajZYSVNySVB0R1MxSVpZS0lsRXQ3SzltTTk0WHN6VzRnbGNUN3EKcHFXdTlPbDJ6TUZVZ3NCMVZhSUJBRDJoU091RWhmSjhPYnM5TStsckdLTTk3L2dadXliMTh5L0YwNXEvRllOWAplZHB6aFgyN1Q5azJpcWhxUnJjOC8vWk8wOU5QVjJkamsrZFh2Yjdac016ZHdMTkpheStaUGJNclJHaVIzeVR2CjRUSkRwNnNIUE5JaDFXNG5QdTBWbzBQTFRWZEV2Y2ZtT0F4enlnby9VaHZMcXFXbDJhU0hqdEJYb3hkNTk4RG8KY2kvTnRsdHhYMitRcHpvdjJscWlYN2gxUG1UUDZiTnp1ZHc1SzM4VU9KYlU4eE1NQk5KYklCSmc1dUNkeW1Sdwpveks0M21lQ1JPczBZRjAyCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K\n server: https://webapps-g3tbby17.hcp.uksouth.azmk8s.io:443\n name: my-resource-group\ncontexts:\n- context:\n cluster: my-resource-group\n user: clusterUser_my-resource-group_my-resource-group\n name: my-resource-group\ncurrent-context: my-resource-group\nkind: Config\npreferences: {}\nusers:\n- name: clusterUser_my-resource-group_my-resource-group\n user:\n client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZIakNDQXdhZ0F3SUJBZ0lSQUxHVEVvUnZyZUUxNkU5SGw2UlUydU13RFFZSktvWklodmNOQVFFTEJRQXcKRFRFTE1Ba0dBMVVFQXhNQ1kyRXdIaGNOTWpRd01qQTRNVFl6TURFM1doY05Nall3TWpBNE1UWTBNREUzV2pBdwpNUmN3RlFZRFZRUUtFdzV6ZVhOMFpXMDZiV0Z6ZEdWeWN6RVZNQk1HQTFVRUF4TU1iV0Z6ZEdWeVkyeHBaVzUwCk1JSUNJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBZzhBTUlJQ0NnS0NBZ0VBNTdFVTZoV0ZvVkpUdUkzeXhPaU0KMWxtMXJwNWlNSGpRYkVuU0RvRlI5alY1R2NCcC9wTnF1UDNXQ3E3VlVEbGViTlBXQ1BiR2wzdzVXRUdBYUdHOApwU3Z4OVFSU0xYUkpGMWFxb0NOQTlPbHkraGhLeWFKbGNIaEVxbmkxRHBEWDRmQjJhVHVMV2dnbGZ3cjZOVnhtCmJMbFErdlFmRmNCNGxZN1ViRVNOQ0g4djU0UDNrMmt1M1VRSjBzWlVWZ05VVVB0SzRMeXJzWThqMkxFR0FocXkKV0JmNjNpbnNnc2ZKSmxleWJKeUw3TEk2SWxDcU5XL2JEL3NTRllsaW1YeEhYaTQwYlpSOWlPNndUNXFtS1BvYwpDNExEenpCV1FHZ2VmbWplSytDblhlRmQ5dkJGeVQ2bGRaNUhQb0xMUGZUUnZzckg1T3pDRy8xck9oMXFMS0hoCmkxZk5iQURZWHBqWkVyNnY5Ym1YRGpNV2VNNzZobjRydE5zNDlvOE1SUHVYb2QwN2RCdmtOUGJrb1czVkRvUm8Kcm4raHdGbFBFUlNXdC9tOFhTOGU1YStuRnh4N0N2UmpLcWVBdzVPRWZvNDNYeVd5MlR1Y2h6djM5SS9seXhLVgpZZEpuRjRCL015RjBDRXpIaWl2QUZ0MEVuenkyUXJNNFBUTGhWUlJHeU9vMy9ZU2tzWnZwNWJDa1FmR0lCWDBPClRveDNvZ3VLRFhobWg5N1A0R3N4VE00L3hSbDVFUkJCTFo5TXZKL1IvT2pKVkhxU1F5VHpYUXkrdVpSSE1mM2cKTk0zMks2Ris4aHZXNTE0WXpTWUdRL01TT3liNklBS1JpeXZ0cG5Rc0UyUi9vdmFOc29UY0k4MEhlT09QYXdsdQpZS2k5aHI4VmtUQ1pVQzIwL3BPMExiY0NBd0VBQWFOV01GUXdEZ1lEVlIwUEFRSC9CQVFEQWdXZ01CTUdBMVVkCkpRUU1NQW9HQ0NzR0FRVUZCd01DTUF3R0ExVWRFd0VCL3dRQ01BQXdId1lEVlIwakJCZ3dGb0FVR0dmMDVaSDYKT215UGx5akZ1VzBkalQ5bzBlc3dEUVlKS29aSWh2Y05BUUVMQlFBRGdnSUJBRWNWclVUMjAwVlFkcEV6QlFiVQppSlZVdUpYcTk2SHpWVHBGeFFvc2Z5b2YySEZrcFh4Y2M4VWZldEdncWdmMFlxN2laMG54cjhyMU53NExsdjFzCkFiZHNCb2tZZHgzZFlCUmROcXNUdFhNbFNsdHp0ZnFDMjhmTStxV2p4WUhiR09IczI3YnFYWVA1ZHlONjhUb1AKc3VBUnFoUHFNTmRWbUFXUHNTZWZpSDNSRE9JRFZSRzY3emVjWXdEZGpxM1N6cTc0eUYyZWh2THQ5YTRBTjJBegpLMWpPK253dW5kSkFmbWlFa1BXZlRUZ0lTUjZ1V0c0VEExSEJYYzNTR0I3LytteCtzbDJoY202YVpBc04yMTl5CjFKUkUvTS9IOFp4cWRJOVpYc1JldVUrY1IzQXlOQ2ZGUkI1YXdSNks2OFRPZHBQcTA3RnU2VkxxUWlveENDd1AKbVpNek9kTlVRZzVveEJ4TENsRzNoUmZMY25iemIzcE5rb0RMNy9CbHBHRkZlU3Z3MGVRcWI5d2tPMmhIbkxLTQo2SGpRdmJjOTFjQnN6SEwzUFo4N3lGdGs4UGFGWkk0bjF4S2p3d2hxVnNMM1BlbmtHUnNpMU8yempVVVk2ZWI0Clgyc3BhYVplcFVxQmpzWHJ4ZDNRUnFqZEJxQ0x3aWZYK1VFb1JaYnlEKzFIQTZjckZ3UEo5QVRWM0U0VWUxUWQKMWZFWDNmMkRBbk5sNmlyR3d0K3Y0bUxvTHRXK2lkZGR0ODhhdC9ydXdYOXFjeHEvbmQrUFZOMzFlSVhmWlVregpCcGFCd3RQaFJpUytsdDhhMDJoOEtrdGRQNHR6NzA0eUt1T3FaUUJlTzJzdksvNDB6aGNwa3VtOGp6MlVLT3BGCktUcGhxd1ZmUDFXZXBzNkNSQXlwc0xrUgotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==\n client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlKSndJQkFBS0NBZ0VBNTdFVTZoV0ZvVkpUdUkzeXhPaU0xbG0xcnA1aU1IalFiRW5TRG9GUjlqVjVHY0JwCi9wTnF1UDNXQ3E3VlVEbGViTlBXQ1BiR2wzdzVXRUdBYUdHOHBTdng5UVJTTFhSSkYxYXFvQ05BOU9seStoaEsKeWFKbGNIaEVxbmkxRHBEWDRmQjJhVHVMV2dnbGZ3cjZOVnhtYkxsUSt2UWZGY0I0bFk3VWJFU05DSDh2NTRQMwprMmt1M1VRSjBzWlVWZ05VVVB0SzRMeXJzWThqMkxFR0FocXlXQmY2M2luc2dzZkpKbGV5Ykp5TDdMSTZJbENxCk5XL2JEL3NTRllsaW1YeEhYaTQwYlpSOWlPNndUNXFtS1BvY0M0TER6ekJXUUdnZWZtamVLK0NuWGVGZDl2QkYKeVQ2bGRaNUhQb0xMUGZUUnZzckg1T3pDRy8xck9oMXFMS0hoaTFmTmJBRFlYcGpaRXI2djlibVhEak1XZU03NgpobjRydE5zNDlvOE1SUHVYb2QwN2RCdmtOUGJrb1czVkRvUm9ybitod0ZsUEVSU1d0L204WFM4ZTVhK25GeHg3CkN2UmpLcWVBdzVPRWZvNDNYeVd5MlR1Y2h6djM5SS9seXhLVllkSm5GNEIvTXlGMENFekhpaXZBRnQwRW56eTIKUXJNNFBUTGhWUlJHeU9vMy9ZU2tzWnZwNWJDa1FmR0lCWDBPVG94M29ndUtEWGhtaDk3UDRHc3hUTTQveFJsNQpFUkJCTFo5TXZKL1IvT2pKVkhxU1F5VHpYUXkrdVpSSE1mM2dOTTMySzZGKzhodlc1MTRZelNZR1EvTVNPeWI2CklBS1JpeXZ0cG5Rc0UyUi9vdmFOc29UY0k4MEhlT09QYXdsdVlLaTlocjhWa1RDWlVDMjAvcE8wTGJjQ0F3RUEKQVFLQ0FnQWxtQncycDJ0WmM4eFY0K0tDaE9GbFhvVVdZbWk0U01JNDcvbC9sUWhCbFFlallBOVMyWVMxbzZwNQpiVWo3alhOKzRSaVh0OE1kalhDWW0zaEVkNmR1ZmFUekJ0SjJ3YW1pZWRPUnpHYWIxczFyTzBuWFVkeDMxV3YrCjVUc3JzK0R6cmxyb1ZGc1dMc0EyendjdVpXSFJQbmlmWDhFemZGbVVtdXBvN3U2YmRGZkhqeWc2NlJSTG51Q2gKTE1FK2U2ZlF4Qld3UmF6dVVMV1dVWk1TQUZiejZHQXljRWNLS1hUQUhmYTduT012Y3ZQdjRYcmMxTnVNeWtaeQo3Q250a2JiYTExQjJmMk9uTm1PeFp2eVRKWklyWS9wMXdmZ2MxMGdyWnNTMkJldmlWZEV6WW1WUWREUFEwKy9uCmVyMlR2Z2ZTbDRDNzZwYk1oK0JBTzhtZ21GdktPMW5ZSmtPVjdzSFBLOWJUMjVyaVAxNGZWYjNqbkhhNU5aUEoKS0gyRmFYOTVPUldrMHhVc0YwemdKaXZaUG9FY0ZQc01LZmRSZlhYdXA5VmhPemZMZWVpbzh4SWlXOW9XNVduYgpORzMzejRvT1Rob3YzQ2ZrMWVBSi8wQnFUZXJPVzRIcWJLbXBDc1RSYUxEY3dzK1l1OXNsTDhOZE9BdjdHM3RNCnU1cGMvUllsNmVuNWJqbkxQMUdDZXdYVWVxRzlGMFhiY0t5U1BCVWhZR0tERjVyL0MzZk9IbkwrS01XbmtsS20KTzJnOERZQlJJOWU2a0EzUVBmVGo1eWUxTUFQaWUzYm5kS3UzRjdYZ2k1cUNnY3FiYkdtbUl5cVZsUFlZeG4xVApLRFZrVzZmRloza0NYcDlXOGtzaU10azN2QytCSzNTNkFiWndHY1MrMFJQTGRVQXFBUUtDQVFFQTlEZllyeEIvCnIzU0Z0bEhXb01jUkQ3cm1DSWIvUWwrNDZ6VDdBaUpTOGlDOUdBdkkzL1d5YmUwRElaK3ZQUGFHVU91STdMdTQKZCtLNHd0TzZpbzhGTXlZcCtmMmxPcVJWaWFEUGhKdTZXZFVGSkQybmZra0NmR2R1YnFydHNucWpEZnMvR1poQgpQbzg1a2ZCZ3k0TDlpK3MzOGR2K01heVJrckxZemxuUGFvMUpmUUxpbHRxL3EvVUoxV21TQ2dVeWw2NFV2ZSt0Cnh1T215NmM4YWhOajY3WTlHQ21YSEI4Tit2aTdWV1VSRDF2OGt3Z2JyRVRPUWM2NlRTVHNIbTRrUEZGL1VFYXUKeGdVdmpKcU1FcmtsTUZPTmRITUZTemZvNUYrN0ErSnRCaVMwTzFON1VqL3h3WWo2QmkvazU4ZkJ2Tm1aeVhVOAp0dVZQb01ndG9yY2hnUUtDQVFFQTh0Nkg1K2t2SGZuYm5pZUhrUVRQWkZrTmdaNTl5Y2FOSkoza2J0cCtFc2loCmNsb0tjOGhsb3B0STZEVE8rUUZWVjdUSzdHdGxsOXFvRXIvSDJLNVdhQlg0WEF4UUR6NlpDbWUyMng5Y0h5ZUUKNXJsZk93dVArT01aa3dwa0ZYOVJqN0YzMmphV2Zmcm5Kd1Z4ekMwNG9EVmFJRk05RHE5ZU43RWF0R1hQZXE0bApVYnZTOW9tTlVPSTJVTWpucW90YXovcldlWGNQVWM4MHQvaGNnS2hGRTN1VUZZRndWRzdFSFRpWWhVQWI2Q2ErCmFCS0wwT0VDV2lZZVNLTEZMbTRDSSs0VGFVUHJuOWk5elJZYnpWRHhWVWVsRHpHNGpmTjRxbjYycmlUYUFXMXgKblVVTmRuVDNON0VKM2VxMFJXVUM1b3hvRDlzZlhTR2VxOFhhSE1ON053S0NBUUE5d0IwMjdzb0tXRUV5LzNCdwppTVVrb0JKb0Y1SlZleFNyekdLbmdIeE9vcjZOWlBWdXc1WlJPenV1ZGN6K2NpczJMTWdiYTcvUitHN1ZQR29QCmZPaElyWjZ4aWxRTUJ0OW1CRlpVWm5meEhPN0c0aHdHejNra2NaYTN2dHFKWlg3ekd4TXlhcEFjdkdSSEpXdWsKS2NQb2JCcGlPa2tFMEdpaW1qdzl1UEc4Tkd0Zmc2bzlrS1FrVzdvWHp6RFEvYzEwRXQxRnhXUEFSWEc0VHRuMAp6R0JZaW1UYVJqSGlOMnYyaUl2OXBLZHlwY1N3ZkwxYWlxOUlibmdtNTI0WXA2cmI0Wk42ZmRUVlZ4eFZ4Z0lpCi9kT01hNlA1ek5lSzFHRTcxWVRaRDVpWGxCSkthZXBsdXF0clR6SkEvRDA1NmdWdnRlbXZ5Y2dIU3VZZWRsOHIKcEhpQkFvSUJBQXJYNEoxOERieDY0VkZJVm9jay9kVnZIR2xER0Q2Zi9NRTd3MjBubUNWaWk4SzlQbVk0OWtDeQpTaWtENHBHL2UzMzA5bkpqd1I5c2hjQ0FpMzJqR3Z4K3JwMzlkcjJYZitHMUM3Ynd5WDRpbDQ1dGpGRG9qVDhCCmRLelo4K241eXp4dElmcStJUzN5dTh0RU5QWjJ0bWFBdTB0aUxBR3gxclVKMVRWa3JrUzk3YkNlZ0NhOXNXK0IKQ2dmRlVJS093amt5Njh4MGdseVdzYlhkQXRSRHJ3SFZyS0RoTEpDNGVVME1yOUtUTUN2SFB3MEtkdStXZkRKbQpMVWYwN0hUTU9KQStHdVBDUW96YWNtN3JvOFlnN1FWdnMzRGdPV3N0Q2FBakZDam1RRTE4QTJ5UUhxL0JQU0JoCmFSMWRVenNkN1drNXI1TzFwc3JUcTIvajMzOFZRelVDZ2dFQVVxTmw0RVRBVUtSUFd0bDhrYjAzWnFscmVGbE0KWWo5aXYrNWIya0U0SVl6OUs4NkpiQjQwdHJVYmU5aUh1UFJkZEEvVlBqMUJpbCsvT2VBMUZ3NVBmMnJYZXNiSApUamdralRqa0ZUQjR4Yjk0MkVNakRRVGNGU0k1ZkFYL0xkdFN6Y214a0xPOXlkb3hqQUhzK25jNUlPcTFFVXVICkd2aGx1SHpVV05aVkNNNjJVaHR5cGNUT2M4UWtZRXNrdjRjb0RvVmxvS0pKWXhSSmdqb2J0bjBHSENmWTdRREgKOWhEWTNtYm5DTXdDS1VDWm1pU2JIemtCWjZLQ2FHZW1vRC9PcEJHZlAvUmNwUkJLc1pxdVpZUVQrWUZadENqMgpxZnRGOFlpZHhqNUUrUm4zMEF4Vi90SjV2QzJPUXNWTDIrUmViemREbUNlVnY4NGtnbWIvN0NDNW53PT0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0K\n token: 3ht7yaabofxzel0letgciuqv4tbvbbbxoeugfvkjo5n56145dqb4wy47rkofyer9jg56hdapagsx4620delw0j5h00yfn9xca6zfdbu42g0ejie2ca61u4par6qm1bku\n", + "kubelet_identity": [], + "kubernetes_version": "1.27.7", + "linux_profile": [], + "local_account_disabled": false, + "location": "uksouth", + "maintenance_window": [], + "maintenance_window_auto_upgrade": [], + "maintenance_window_node_os": [], + "microsoft_defender": [], + "monitor_metrics": [], + "name": "my-resource-group", + "network_profile": [ + { + "dns_service_ip": "10.0.0.10", + "docker_bridge_cidr": "", + "ebpf_data_plane": "", + "ip_versions": [ + "IPv4" + ], + "load_balancer_profile": [ + { + "effective_outbound_ips": [ + "/subscriptions/d394a330-57cd-464c-aa69-f9ec5551d2c8/resourceGroups/MC_my-resource-group_my-resource-group_uksouth/providers/Microsoft.Network/publicIPAddresses/3fe5ac48-ed48-4584-adf1-4dcf8c9be6f5" + ], + "idle_timeout_in_minutes": 0, + "managed_outbound_ip_count": 1, + "managed_outbound_ipv6_count": 0, + "outbound_ip_address_ids": [], + "outbound_ip_prefix_ids": [], + "outbound_ports_allocated": 0 + } + ], + "load_balancer_sku": "standard", + "nat_gateway_profile": [], + "network_mode": "", + "network_plugin": "azure", + "network_plugin_mode": "", + "network_policy": "calico", + "outbound_type": "loadBalancer", + "pod_cidr": "", + "pod_cidrs": [], + "service_cidr": "10.0.0.0/16", + "service_cidrs": [ + "10.0.0.0/16" + ] + } + ], + "node_os_channel_upgrade": null, + "node_resource_group": "MC_my-resource-group_my-resource-group_uksouth", + "node_resource_group_id": "/subscriptions/d394a330-57cd-464c-aa69-f9ec5551d2c8/resourceGroups/MC_my-resource-group_my-resource-group_uksouth", + "oidc_issuer_enabled": false, + "oidc_issuer_url": "", + "oms_agent": [], + "open_service_mesh_enabled": null, + "portal_fqdn": "webapps-g3tbby17.portal.hcp.uksouth.azmk8s.io", + "private_cluster_enabled": false, + "private_cluster_public_fqdn_enabled": false, + "private_dns_zone_id": null, + "private_fqdn": "", + "public_network_access_enabled": true, + "resource_group_name": "my-resource-group", + "role_based_access_control_enabled": true, + "run_command_enabled": true, + "service_mesh_profile": [], + "service_principal": [ + { + "client_id": "80d99f9c-d41d-4088-ac76-a68e75238956", + "client_secret": "1478Q~JJADkzAXjzGT7Ucmqku2XdLZhUV2ETkcli" + } + ], + "sku_tier": "Free", + "storage_profile": [], + "support_plan": "KubernetesOfficial", + "tags": { + "Environment": "dev", + "Terraform": "true" + }, + "timeouts": null, + "web_app_routing": [], + "windows_profile": [ + { + "admin_password": "", + "admin_username": "azureuser", + "gmsa": [], + "license": "" + } + ], + "workload_autoscaler_profile": [], + "workload_identity_enabled": false + }, + "sensitive_attributes": [], + "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjo1NDAwMDAwMDAwMDAwLCJkZWxldGUiOjU0MDAwMDAwMDAwMDAsInJlYWQiOjMwMDAwMDAwMDAwMCwidXBkYXRlIjo1NDAwMDAwMDAwMDAwfSwic2NoZW1hX3ZlcnNpb24iOiIyIn0=", + "dependencies": [ + "module.networking.azurerm_resource_group.network" + ] + } + ] + }, + { + "module": "module.networking", + "mode": "managed", + "type": "azurerm_network_security_group", + "name": "aks_nsg", + "provider": "provider[\"registry.terraform.io/hashicorp/azurerm\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "id": "/subscriptions/d394a330-57cd-464c-aa69-f9ec5551d2c8/resourceGroups/my-resource-group/providers/Microsoft.Network/networkSecurityGroups/aks-nsg", + "location": "uksouth", + "name": "aks-nsg", + "resource_group_name": "my-resource-group", + "security_rule": [ + { + "access": "Allow", + "description": "", + "destination_address_prefix": "*", + "destination_address_prefixes": [], + "destination_application_security_group_ids": [], + "destination_port_range": "22", + "destination_port_ranges": [], + "direction": "Inbound", + "name": "ssh-rule", + "priority": 1002, + "protocol": "Tcp", + "source_address_prefix": "92.19.71.227/32", + "source_address_prefixes": [], + "source_application_security_group_ids": [], + "source_port_range": "*", + "source_port_ranges": [] + }, + { + "access": "Allow", + "description": "", + "destination_address_prefix": "*", + "destination_address_prefixes": [], + "destination_application_security_group_ids": [], + "destination_port_range": "6443", + "destination_port_ranges": [], + "direction": "Inbound", + "name": "kube-apiserver-rule", + "priority": 1001, + "protocol": "Tcp", + "source_address_prefix": "92.19.71.227/32", + "source_address_prefixes": [], + "source_application_security_group_ids": [], + "source_port_range": "*", + "source_port_ranges": [] + } + ], + "tags": {}, + "timeouts": null + }, + "sensitive_attributes": [], + "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxODAwMDAwMDAwMDAwLCJkZWxldGUiOjE4MDAwMDAwMDAwMDAsInJlYWQiOjMwMDAwMDAwMDAwMCwidXBkYXRlIjoxODAwMDAwMDAwMDAwfSwic2NoZW1hX3ZlcnNpb24iOiIwIn0=", + "dependencies": [ + "module.networking.azurerm_resource_group.network" + ] + } + ] + }, + { + "module": "module.networking", + "mode": "managed", + "type": "azurerm_network_security_rule", + "name": "kube_apiserver_rule", + "provider": "provider[\"registry.terraform.io/hashicorp/azurerm\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "access": "Allow", + "description": "", + "destination_address_prefix": "*", + "destination_address_prefixes": [], + "destination_application_security_group_ids": [], + "destination_port_range": "6443", + "destination_port_ranges": [], + "direction": "Inbound", + "id": "/subscriptions/d394a330-57cd-464c-aa69-f9ec5551d2c8/resourceGroups/my-resource-group/providers/Microsoft.Network/networkSecurityGroups/aks-nsg/securityRules/kube-apiserver-rule", + "name": "kube-apiserver-rule", + "network_security_group_name": "aks-nsg", + "priority": 1001, + "protocol": "Tcp", + "resource_group_name": "my-resource-group", + "source_address_prefix": "92.19.71.227/32", + "source_address_prefixes": [], + "source_application_security_group_ids": [], + "source_port_range": "*", + "source_port_ranges": [], + "timeouts": null + }, + "sensitive_attributes": [], + "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxODAwMDAwMDAwMDAwLCJkZWxldGUiOjE4MDAwMDAwMDAwMDAsInJlYWQiOjMwMDAwMDAwMDAwMCwidXBkYXRlIjoxODAwMDAwMDAwMDAwfSwic2NoZW1hX3ZlcnNpb24iOiIwIn0=" + } + ] + }, + { + "module": "module.networking", + "mode": "managed", + "type": "azurerm_network_security_rule", + "name": "ssh_rule", + "provider": "provider[\"registry.terraform.io/hashicorp/azurerm\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "access": "Allow", + "description": "", + "destination_address_prefix": "*", + "destination_address_prefixes": [], + "destination_application_security_group_ids": [], + "destination_port_range": "22", + "destination_port_ranges": [], + "direction": "Inbound", + "id": "/subscriptions/d394a330-57cd-464c-aa69-f9ec5551d2c8/resourceGroups/my-resource-group/providers/Microsoft.Network/networkSecurityGroups/aks-nsg/securityRules/ssh-rule", + "name": "ssh-rule", + "network_security_group_name": "aks-nsg", + "priority": 1002, + "protocol": "Tcp", + "resource_group_name": "my-resource-group", + "source_address_prefix": "92.19.71.227/32", + "source_address_prefixes": [], + "source_application_security_group_ids": [], + "source_port_range": "*", + "source_port_ranges": [], + "timeouts": null + }, + "sensitive_attributes": [], + "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxODAwMDAwMDAwMDAwLCJkZWxldGUiOjE4MDAwMDAwMDAwMDAsInJlYWQiOjMwMDAwMDAwMDAwMCwidXBkYXRlIjoxODAwMDAwMDAwMDAwfSwic2NoZW1hX3ZlcnNpb24iOiIwIn0=" + } + ] + }, + { + "module": "module.networking", + "mode": "managed", + "type": "azurerm_resource_group", + "name": "network", + "provider": "provider[\"registry.terraform.io/hashicorp/azurerm\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "id": "/subscriptions/d394a330-57cd-464c-aa69-f9ec5551d2c8/resourceGroups/my-resource-group", + "location": "uksouth", + "managed_by": "", + "name": "my-resource-group", + "tags": {}, + "timeouts": null + }, + "sensitive_attributes": [], + "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjo1NDAwMDAwMDAwMDAwLCJkZWxldGUiOjU0MDAwMDAwMDAwMDAsInJlYWQiOjMwMDAwMDAwMDAwMCwidXBkYXRlIjo1NDAwMDAwMDAwMDAwfSwic2NoZW1hX3ZlcnNpb24iOiIwIn0=" + } + ] + }, + { + "module": "module.networking", + "mode": "managed", + "type": "azurerm_subnet", + "name": "control_plane_subnet", + "provider": "provider[\"registry.terraform.io/hashicorp/azurerm\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "address_prefixes": [ + "10.0.1.0/24" + ], + "delegation": [], + "enforce_private_link_endpoint_network_policies": false, + "enforce_private_link_service_network_policies": false, + "id": "/subscriptions/d394a330-57cd-464c-aa69-f9ec5551d2c8/resourceGroups/my-resource-group/providers/Microsoft.Network/virtualNetworks/aks-vnet/subnets/control-plane-subnet", + "name": "control-plane-subnet", + "private_endpoint_network_policies_enabled": true, + "private_link_service_network_policies_enabled": true, + "resource_group_name": "my-resource-group", + "service_endpoint_policy_ids": [], + "service_endpoints": [], + "timeouts": null, + "virtual_network_name": "aks-vnet" + }, + "sensitive_attributes": [], + "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxODAwMDAwMDAwMDAwLCJkZWxldGUiOjE4MDAwMDAwMDAwMDAsInJlYWQiOjMwMDAwMDAwMDAwMCwidXBkYXRlIjoxODAwMDAwMDAwMDAwfSwic2NoZW1hX3ZlcnNpb24iOiIwIn0=" + } + ] + }, + { + "module": "module.networking", + "mode": "managed", + "type": "azurerm_subnet", + "name": "worker_node_subnet", + "provider": "provider[\"registry.terraform.io/hashicorp/azurerm\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "address_prefixes": [ + "10.0.2.0/24" + ], + "delegation": [], + "enforce_private_link_endpoint_network_policies": false, + "enforce_private_link_service_network_policies": false, + "id": "/subscriptions/d394a330-57cd-464c-aa69-f9ec5551d2c8/resourceGroups/my-resource-group/providers/Microsoft.Network/virtualNetworks/aks-vnet/subnets/worker-node-subnet", + "name": "worker-node-subnet", + "private_endpoint_network_policies_enabled": true, + "private_link_service_network_policies_enabled": true, + "resource_group_name": "my-resource-group", + "service_endpoint_policy_ids": [], + "service_endpoints": [], + "timeouts": null, + "virtual_network_name": "aks-vnet" + }, + "sensitive_attributes": [], + "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxODAwMDAwMDAwMDAwLCJkZWxldGUiOjE4MDAwMDAwMDAwMDAsInJlYWQiOjMwMDAwMDAwMDAwMCwidXBkYXRlIjoxODAwMDAwMDAwMDAwfSwic2NoZW1hX3ZlcnNpb24iOiIwIn0=" + } + ] + }, + { + "module": "module.networking", + "mode": "managed", + "type": "azurerm_virtual_network", + "name": "aks_vnet", + "provider": "provider[\"registry.terraform.io/hashicorp/azurerm\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "address_space": [ + "10.0.0.0/16" + ], + "bgp_community": "", + "ddos_protection_plan": [], + "dns_servers": [], + "edge_zone": "", + "encryption": [], + "flow_timeout_in_minutes": 0, + "guid": "24936242-4fb9-4b89-9806-439e6251b078", + "id": "/subscriptions/d394a330-57cd-464c-aa69-f9ec5551d2c8/resourceGroups/my-resource-group/providers/Microsoft.Network/virtualNetworks/aks-vnet", + "location": "uksouth", + "name": "aks-vnet", + "resource_group_name": "my-resource-group", + "subnet": [ + { + "address_prefix": "10.0.1.0/24", + "id": "/subscriptions/d394a330-57cd-464c-aa69-f9ec5551d2c8/resourceGroups/my-resource-group/providers/Microsoft.Network/virtualNetworks/aks-vnet/subnets/control-plane-subnet", + "name": "control-plane-subnet", + "security_group": "" + }, + { + "address_prefix": "10.0.2.0/24", + "id": "/subscriptions/d394a330-57cd-464c-aa69-f9ec5551d2c8/resourceGroups/my-resource-group/providers/Microsoft.Network/virtualNetworks/aks-vnet/subnets/worker-node-subnet", + "name": "worker-node-subnet", + "security_group": "" + } + ], + "tags": {}, + "timeouts": null + }, + "sensitive_attributes": [], + "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxODAwMDAwMDAwMDAwLCJkZWxldGUiOjE4MDAwMDAwMDAwMDAsInJlYWQiOjMwMDAwMDAwMDAwMCwidXBkYXRlIjoxODAwMDAwMDAwMDAwfSwic2NoZW1hX3ZlcnNpb24iOiIwIn0=", + "dependencies": [ + "module.networking.azurerm_resource_group.network" + ] + } + ] + } + ], + "check_results": null +} diff --git a/aks-terraform/variables.tf b/aks-terraform/variables.tf new file mode 100644 index 00000000..638c2ded --- /dev/null +++ b/aks-terraform/variables.tf @@ -0,0 +1,18 @@ +variable "client_id" { + description = "The Client ID for the Azure Service Principal" +} + +variable "client_secret" { + description = "The Client Secret for the Azure Service Principal" +} + + + +variable "subscription_id" { + description = "The Azure Subscription ID" + +} +variable "tenant_id" { + description = " The tenant ID for the Azure Service Principal" + +} \ No newline at end of file diff --git a/app.py b/app.py index 50f4e29d..fbaa3b51 100644 --- a/app.py +++ b/app.py @@ -5,16 +5,29 @@ from sqlalchemy import create_engine import pyodbc import os +from azure.identity import DefaultAzureCredential +from azure.keyvault.secrets import SecretClient + # Initialise Flask App app = Flask(__name__) # database connection -server = 'devops-project-server.database.windows.net' -database = 'orders-db' -username = 'maya' -password = 'AiCore1237' -driver= '{ODBC Driver 18 for SQL Server}' + +# Replace these values with your Key Vault details +key_vault_url = "https://secretKey02.vault.azure.net/" + +# Set up Azure Key Vault client with Managed Identity +credential = DefaultAzureCredential() +secret_client = SecretClient(vault_url=key_vault_url, credential=credential) + + +# Access the secret values +server = secret_client.get_secret("server").value +database = secret_client.get_secret("database").value +username = secret_client.get_secret("username").value +password = secret_client.get_secret("password").value +driver = '{ODBC Driver 18 for SQL Server}' # Create the connection string connection_string=f'Driver={driver};\ @@ -85,7 +98,8 @@ def add_order(): product_quantity = request.form.get('product_quantity') order_date = request.form.get('order_date') shipping_date = request.form.get('shipping_date') - + + # Create a session to interact with the database session = Session() diff --git a/application-manifest.yaml b/application-manifest.yaml new file mode 100644 index 00000000..416b7846 --- /dev/null +++ b/application-manifest.yaml @@ -0,0 +1,32 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: flask-app-deployment +spec: + replicas: 2 + selector: + matchLabels: + app: flask-app + template: + metadata: + labels: + app: flask-app + spec: + containers: + - name: flask-app-container + image: nmohamed436/azure-end-to-end-devops:latest + ports: + - containerPort: 5000 +--- +apiVersion: v1 +kind: Service +metadata: + name: flask-app-service +spec: + selector: + app: flask-app + ports: + - protocol: TCP + port: 80 + targetPort: 5000 + type: LoadBalancer diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 00000000..de328604 --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,29 @@ +# Starter pipeline +# Start with a minimal pipeline that you can customize to build and deploy your code. +# Add steps that build, run tests, deploy, and more: +# https://aka.ms/yaml + +trigger: +- main + +pool: + vmImage: ubuntu-latest + +steps: +- task: Docker@2 + displayName: 'Build and Push Docker Image' + inputs: + containerRegistry: 'pipelineConnection2' + repository: 'nasiima/web-app-devops-project' + command: 'buildAndPush' + Dockerfile: '**/Dockerfile' + tags: 'latest' + +- task: KubernetesManifest@1 + inputs: + action: 'deploy' + connectionType: 'azureResourceManager' + azureSubscriptionConnection: 'azureConnection' + azureResourceGroup: 'my-resource-group' + kubernetesCluster: 'my-resource-group' + manifests: 'application-manifest.yaml' \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 47ec762e..cb57a0db 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,6 @@ +azure-identity +azure-keyvault-secrets flask==2.2.2 -pyodbc==4.0.39 +pyodbc --no-binary=pyodbc==4.0.35 SQLAlchemy==2.0.21 -werkzeug===2.2.3 \ No newline at end of file +werkzeug===2.2.3