2
votes

I am applying following configuration in Terraform:

resource "azurerm_resource_group" "rg" {
  name     = var.resourceGroupName
  location = var.location
}

resource "azurerm_app_service_plan" "app_plan" {
  name                = var.appServicePlanName
  location            = var.location
  resource_group_name = azurerm_resource_group.rg.name

  sku {
    tier = "Free"
    size = "F1"
  }
}

resource "azurerm_app_service" "app_service" {
  name                = var.appServiceName
  location            = var.location
  resource_group_name = azurerm_resource_group.rg.name
  app_service_plan_id = azurerm_app_service_plan.app_plan.id

  app_settings = {
    "SOME_KEY" = "some-value"
  }
}

The first time I run 'terraform apply', the result is the one I would expect. The resources are created. If I will run the same configuration again, I will recieve: Error: The name "xxx" used for the App Service needs to be globally unique and isn't available: Hostname 'xxx' already exists. Please select a different name.

I am a bit confused since I would expect Terraform to skip any changes and just let me know that nothing has been changed, what am I missing? My provider(provider.tf) configuration is the following:

provider "azurerm" {
  skip_provider_registration = "true"
  subscription_id = var.subscriptionId
  tenant_id       = var.tenantId
  client_id       = var.clientId
  client_secret   = var.clientSecret
}

Besides, I have terraform.tfvars

resourceGroupName = "xxx-poc1-rg"
location = "eastus"
appServicePlanName = "xxx-poc1-asp01"
appServiceName = "xxx-poc1-apsvc01"
subscriptionId = ""
tenantId = ""
clientId = ""
clientSecret = ""

and variables.tf files

variable "appServiceName" {
  type        = string
  description = "The name of app service"
}

variable "appServicePlanName" {
  type        = string
  description = "The name of app service plan"
}

variable "resourceGroupName" {
  type        = string
  description = "The name of resource group"
}

variable "location" {
  type        = string
  description = "Location"
}

variable "subscriptionId" {
  type        = string
  description = "Subscription id"
}

variable "tenantId" {
  type        = string
  description = "Tenant id"
}

variable "clientId" {
  type        = string
  description = "Client id"
}

variable "clientSecret" {
  type        = string
  description = "Client secret"
}

P.S. If I am trying to modify app service configuration by adding a connection_string section or modifying app_settings, the result is the same, exception thrown saying "Error: The name "xxx" used for the App Service needs to be globally unique and isn't available: Hostname 'xxx' already exists. Please select a different name."

Here is the terraform state output: D:\alexus-git\TerraformAppServicePlanTest [master ≡]> terraform plan Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be persisted to local or remote state storage.

azurerm_resource_group.rg: Refreshing state... [id=/subscriptions/0f1c414a-...-a351876ecd47/resourceGroups/xxx-poc1-rg] azurerm_app_service_plan.app_plan: Refreshing state... [id=/subscriptions/0f1c414a-...-a351876ecd47/resourceGroups/xxx-poc1-rg/providers/Microsoft.Web/serverfarms/xxx-poc1-asp01]


An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + create

Terraform will perform the following actions:

# azurerm_app_service.app_service will be created + resource "azurerm_app_service" "app_service" { + app_service_plan_id = "/subscriptions/0f1c414a-...-a351876ecd47/resourceGroups/xxx-poc1-rg/providers/Microsoft.Web/serverfarms/xxx-poc1-asp01" + app_settings = { + "SOME_KEY" = "some-value" } + client_affinity_enabled = (known after apply) + default_site_hostname = (known after apply) + enabled = true + https_only = false + id = (known after apply) + location = "eastus" + name = "xxx-poc1-apsvc01" + outbound_ip_addresses = (known after apply) + possible_outbound_ip_addresses = (known after apply) + resource_group_name = "xxx-poc1-rg" + site_credential = (known after apply) + source_control = (known after apply) + tags = (known after apply)

  + auth_settings {
      + additional_login_params        = (known after apply)
      + allowed_external_redirect_urls = (known after apply)
      + default_provider               = (known after apply)
      + enabled                        = (known after apply)
      + issuer                         = (known after apply)
      + runtime_version                = (known after apply)
      + token_refresh_extension_hours  = (known after apply)
      + token_store_enabled            = (known after apply)
      + unauthenticated_client_action  = (known after apply)

      + active_directory {
          + allowed_audiences = (known after apply)
          + client_id         = (known after apply)
          + client_secret     = (sensitive value)
        }

      + facebook {
          + app_id       = (known after apply)
          + app_secret   = (sensitive value)
          + oauth_scopes = (known after apply)
        }

      + google {
          + client_id     = (known after apply)
          + client_secret = (sensitive value)
          + oauth_scopes  = (known after apply)
        }

      + microsoft {
          + client_id     = (known after apply)
          + client_secret = (sensitive value)
          + oauth_scopes  = (known after apply)
        }

      + twitter {
          + consumer_key    = (known after apply)
          + consumer_secret = (sensitive value)
        }
    }

  + connection_string {
      + name  = (known after apply)
      + type  = (known after apply)
      + value = (sensitive value)
    }

  + identity {
      + identity_ids = (known after apply)
      + principal_id = (known after apply)
      + tenant_id    = (known after apply)
      + type         = (known after apply)
    }

  + logs {
      + application_logs {
          + azure_blob_storage {
              + level             = (known after apply)
              + retention_in_days = (known after apply)
              + sas_url           = (sensitive value)
            }
        }

      + http_logs {
          + azure_blob_storage {
              + retention_in_days = (known after apply)
              + sas_url           = (sensitive value)
            }

          + file_system {
              + retention_in_days = (known after apply)
              + retention_in_mb   = (known after apply)
            }
        }
    }

  + site_config {
      + always_on                 = (known after apply)
      + app_command_line          = (known after apply)
      + auto_swap_slot_name       = (known after apply)
      + default_documents         = (known after apply)
      + dotnet_framework_version  = (known after apply)
      + ftps_state                = (known after apply)
      + http2_enabled             = (known after apply)
      + ip_restriction            = (known after apply)
      + java_container            = (known after apply)
      + java_container_version    = (known after apply)
      + java_version              = (known after apply)
      + linux_fx_version          = (known after apply)
      + local_mysql_enabled       = (known after apply)
      + managed_pipeline_mode     = (known after apply)
      + min_tls_version           = (known after apply)
      + php_version               = (known after apply)
      + python_version            = (known after apply)
      + remote_debugging_enabled  = (known after apply)
      + remote_debugging_version  = (known after apply)
      + scm_type                  = (known after apply)
      + use_32_bit_worker_process = (known after apply)
      + virtual_network_name      = (known after apply)
      + websockets_enabled        = (known after apply)
      + windows_fx_version        = (known after apply)

      + cors {
          + allowed_origins     = (known after apply)
          + support_credentials = (known after apply)
        }
    }

  + storage_account {
      + access_key   = (sensitive value)
      + account_name = (known after apply)
      + mount_path   = (known after apply)
      + name         = (known after apply)
      + share_name   = (known after apply)
      + type         = (known after apply)
    }
}

Plan: 1 to add, 0 to change, 0 to destroy.

1
How are you configuring state? What does the plan look like after the first apply?ydaetskcoR
It seems the error shows you need to change the app name with another unique one which is not used in your Azure subscription. Please try it.Charles Xu
@CharlesXu - that exactly the point, I would expect the tool to be idempotent, meaning I can run the same configuration multiple times and if there are any changes it would apply those if there are non it should simple notify me that there are non.Alexey Auslender
@ydaetskcoR - the state is local state, and the plan generated correctly.Alexey Auslender
By generated correctly what do you mean? It shouldn't show any changes required after a successful apply and no changes being made. If that's not the case then you're doing something wrong with your state. You might want to read up on how state is meant to work and is managed in Terraform and if you have a specific question either edit this one or create a new one and close this.ydaetskcoR

1 Answers

2
votes

The problem is that you don't provide backed to use azurerm so your state file doesn't get saved. To fix this you can add backend in an existing .tf file or create a new e.g. backend.tf with content:

terraform { backend "azurerm" { } }