Skip to content

Instantly share code, notes, and snippets.

@daveneeley
Created March 18, 2023 12:35
Show Gist options
  • Save daveneeley/bd69228cb8ae9f848c0295a5973805a6 to your computer and use it in GitHub Desktop.
Save daveneeley/bd69228cb8ae9f848c0295a5973805a6 to your computer and use it in GitHub Desktop.
Failed Retry on GET before PUT with terraform-provider-azapi
// This terraform script attempts to create function API Keys
// against an empty windows function app with no code deployed.
// WARNING: the script will print function keys to stdout for testing.
//
// The script fails the first time, but succeeeds the second time.
//
// The error is like the following. It occurs for both the primary and staging slots.
// The error states that GET is not allowed (presumably because the resource is new?).
// However, there is no GET method configured in this code.
//
// Error: performing action host/default/functionKeys/tf_key of
// "Resource: (ResourceId \"/subscriptions/redacted/resourceGroups/redacted/providers/Microsoft.Web/sites/redacted/slots/staging\" / Api Version \"2022-03-01\")": <break>
// GET https://management.azure.com/subscriptions/redacted/resourceGroups/redacted/providers/Microsoft.Web/sites/redacted/slots/staging/host/default/functionKeys/tf_key
// │ --------------------------------------------------------------------------------
// │ RESPONSE 405: 405 Method Not Allowed
// │ ERROR CODE UNAVAILABLE
// │ --------------------------------------------------------------------------------
// │ <Error><Message>The requested resource does not support http method 'GET'.</Message></Error>
// │ --------------------------------------------------------------------------------
// │
// │
// │ with azapi_resource_action.tf_staging_set_keys,
// │ on main.tf line 169, in resource "azapi_resource_action" "tf_staging_set_keys":
// │ 169: resource "azapi_resource_action" "tf_staging_set_keys" {
terraform {
required_version = ">= 1.2.3"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "3.20.0"
}
azapi = {
source = "Azure/azapi"
version = "1.4.0"
}
}
}
provider "azurerm" {
features {}
}
provider "azapi" {
}
// It's good idea to make resource name Human friendly as well
// as adding some randomness to them, especially for global resources
// due to avoid some interference
resource "random_string" "name" {
length = 5
special = false
upper = false
}
// For Generic tags
resource "random_uuid" "stack_id" {}
module "project" {
source = "cloudposse/label/null"
# Cloud Posse recommends pinning every module to a specific version
# version = "x.x.x"
namespace = "my_namespace"
stage = "dev"
name = "tf"
attributes = ["poc"]
delimiter = "-"
tags = {
stackid = "tf-${random_uuid.stack_id.result}"
}
}
data "azurerm_resource_group" "tf" {
name = "my_rg"
}
resource "azurerm_storage_account" "tf" {
name = replace(module.project.id, "-", "")
resource_group_name = data.azurerm_resource_group.tf.name
location = data.azurerm_resource_group.tf.location
account_tier = "Standard"
account_replication_type = "LRS"
tags = module.project.tags
}
resource "azurerm_service_plan" "tf" {
name = module.project.id
resource_group_name = data.azurerm_resource_group.tf.name
location = data.azurerm_resource_group.tf.location
os_type = "Windows"
sku_name = "Y1"
tags = module.project.tags
}
resource "azurerm_windows_function_app" "tf" {
name = module.project.id
resource_group_name = data.azurerm_resource_group.tf.name
location = data.azurerm_resource_group.tf.location
service_plan_id = azurerm_service_plan.tf.id
storage_account_name = azurerm_storage_account.tf.name
storage_account_access_key = azurerm_storage_account.tf.primary_access_key
site_config {}
tags = module.project.tags
app_settings = {
"FUNCTIONS_WORKER_RUNTIME" = "powershell"
"FUNCTIONS_WORKER_RUNTIME_VERSION" = "~7"
}
}
resource "azurerm_windows_function_app_slot" "tf" {
name = "staging"
function_app_id = azurerm_windows_function_app.tf.id
storage_account_name = azurerm_storage_account.tf.name
storage_account_access_key = azurerm_storage_account.tf.primary_access_key
site_config {}
tags = module.project.tags
app_settings = {
"FUNCTIONS_WORKER_RUNTIME" = "powershell"
"FUNCTIONS_WORKER_RUNTIME_VERSION" = "~7"
}
}
locals {
secret_version = 1
}
resource "random_password" "tf_key" {
length = 32
special = false
keepers = {
key = local.secret_version
}
}
resource "random_password" "tf_staging_key" {
length = 32
special = false
keepers = {
key = local.secret_version
}
}
resource "azapi_resource_action" "tf_set_keys" {
type = "Microsoft.Web/sites@2022-03-01"
resource_id = azurerm_windows_function_app.tf.id
action = "host/default/functionKeys/tf_key"
method = "PUT"
response_export_values = ["*"]
body = jsonencode({
properties = {
name = "tf_key"
value = random_password.tf_key.result
}
})
}
resource "azapi_resource_action" "tf_staging_set_keys" {
type = "Microsoft.Web/sites/slots@2022-03-01"
resource_id = azurerm_windows_function_app_slot.tf.id
action = "host/default/functionKeys/tf_key"
method = "PUT"
response_export_values = ["*"]
body = jsonencode({
properties = {
name = "tf_key"
value = random_password.tf_staging_key.result
}
})
}
output "output1_post" {
value = jsondecode(azapi_resource_action.tf_set_keys.output)
}
output "output2_post" {
value = jsondecode(azapi_resource_action.tf_staging_set_keys.output)
}
data "azapi_resource_action" "tf_list_keys" {
type = "Microsoft.Web/sites@2022-03-01"
resource_id = azurerm_windows_function_app.tf.id
action = "host/default/listkeys"
response_export_values = ["*"]
depends_on = [
azapi_resource_action.tf_set_keys
]
}
data "azapi_resource_action" "tf_staging_list_keys" {
type = "Microsoft.Web/sites/slots@2022-03-01"
resource_id = azurerm_windows_function_app_slot.tf.id
action = "host/default/listkeys"
response_export_values = ["*"]
depends_on = [
azapi_resource_action.tf_staging_set_keys
]
}
locals {
tf_staging_app_key = sensitive(jsondecode(data.azapi_resource_action.tf_staging_list_keys.output).functionKeys.default)
tf_app_key = sensitive(jsondecode(data.azapi_resource_action.tf_list_keys.output).functionKeys.default)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment