Azure Recovery Services Vault with Terraform local provisioner - terraform

Terraform doesn't provide options to change the Azure recovery Services Vault to use LocallyRedundant storage replication type. So I decided to use the PowerShell module to set this after the resource is provisioned. The command seems to be correct and works when it's manually invoked but doesn't when it's put in the provisioner. Any thoughts?
Terraform Version : 0.15
Azurerm Version : 2.40.0
resource "azurerm_recovery_services_vault" "RSV"{
name = "RSV"
location = "eastus"
resource_group_name = "RGTEST"
sku = "Standard"
provisioner "local-exec" {
command = "Get-AzRecoveryServicesVault -Name ${azurerm_recovery_services_vault.RSV.name} | Set-AzRecoveryServicesBackupProperty -BackupStorageRedundancy LocallyRedundant"
interpreter = ["powershell", "-Command"]
}
}

The PowerShell scripts rely on the resource "azurerm_recovery_services_vault" that is fully created. In this case, if you include the local-exec Provisioner in a null_resource, run terraform init and terraform apply again, it works.
Note that even though the resource will be fully created when the
provisioner is run, there is no guarantee that it will be in an
operable state
resource "null_resource" "script" {
provisioner "local-exec" {
command = "Get-AzRecoveryServicesVault -Name ${azurerm_recovery_services_vault.RSV.name} | Set-AzRecoveryServicesBackupProperty -BackupStorageRedundancy LocallyRedundant"
interpreter = ["powershell", "-Command"]
}
}

Related

'terraform init' returns 404 'Resource Group not found' when it does exist

Since adding backend "azurerm" to my Terraform main.tf file it's now returning a 404 on the resource group created to maintain the state file.
I'm at a bit of a loss to explain why, the session is logged in to the correct tenant and subscription using Connect-AzAccount and Set-AzContext methods in the Az PowerShell module.
Here's my setup:
main.tf
## Terraform Configuration
terraform {
# Azure Remote State
backend "azurerm" {
resource_group_name = "abc-uat-tfstate"
storage_account_name = "abcuattfstate"
container_name = "tfstate"
key = "myapp.uat.tfstate"
}
# Provider Dependencies
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0.0"
}
}
}
## Provider Configurations
# Azure
provider "azurerm" {
subscription_id = var.subscriptionId
features {}
}
...
When I run terraform init on this main.tf file I receive the following error:
However note, I can immediately run Get-AzResourceGroup and it returns the group as I see it in Azure Portal.
Until I added the backend it was creating resources correctly so I'm thinking this is a simple configuration issue but after reviewing all the docs don't see what I've got wrong.
Ok, operator error as I suspected.
Running az login --tenant '...' and then az account set --subscrption '...' resolved the problem. terraform init now works correctly.
I should have thought about this earlier.

Is there Terraform script for creating migration activity in Azure?

I have created Azure data migration service and migration project using terraform, so is there any terraform scripts available for creating migration activity in Azure?
Currently its not possible with Terraform as only Database Migration Service and Project are available for now . You can use ARM template for the same .
If you want to use Terraform , then you can use local-exec to use PowerShell or CLI and execute the Az-powershell or Az CLI commands there .
Example of Local-exec :
resource "null_resource" "example" {
provisioner "local-exec" {
command = <<Settings
$ResourceGroupName = "${data.azurerm_resource_group.example.name}"
$FunctionAppName = "${var.function_app}"
$SubscriptionId = "${var.Subscription}"
Get-AzFunctionApp -ResourceGroupName $ResourceGroupName -Name $FunctionAppName -SubscriptionId $SubscriptionId
Settings
interpreter = ["PowerShell", "-Command"]
}
}

Terraform resource lifecycle destroy_after_create?

Is there an option in terraform configuration that would automatically destroy the resource after its dependents have been created? I am thinking something like destroy_after_create lifecycle which doesn't exist.
I want to delete all Lambda archives (s3 objects) after the Lambda Functions get created. Obviously I can create a script to run "terraform destroy -target" after "apply" completes, however I am looking for something within terraform configuration itself.
To hack your way in Terraform, you can use the following combination:
local-exec provisioner
null-resource
AWS CLI - aws s3api delete-object
Terraform depends_on
Like this
resource "aws_s3_bucket" "my_bucket" {
bucket = "my-bucket"
}
resource "null_resource" "delete_lambda" {
depends_on = [
aws_s3_bucket.my_bucket,
# other dependencies ...
]
provisioner "local-exec" {
command = "aws s3api delete-object --bucket my-bucket --key lambda.zip"
}
}

Running Powershell script in Terraform module

Am currently running some Terraform to create resources in Azure. We have a module we have written to create a resource group with a bunch of variables. The provider currently does not allow the creation of budgets and cost alerts but the Powershell modules do. I thought we could then add a Powershell script to carry out the settings. I seem to be hitting a snag where I cannot quite work out how to address the Powershell script. I have the following:
resource "null_resource" "PowerShellScriptRunAlways" {
triggers = {
always_run = "${timestamp()}"
}
provisioner "local-exec" {
command = ".'${path.module}//pwsh//costalert.ps1 -subscriptionID \"${var.azure_subscription_id}\" -tenantID \"${var.azure_tenant_id}\" -clientID \"${var.azure_client_id}\" -clientSecret \"${var.azure_client_secret}\" -budgetAmount \"${var.budgetAmount}\" -rgName \"${azurerm_resource_group.this.name}\" -emailAddresses \"${var.emailAddresses}\"'"
interpreter = ["pwsh", "-Command"]
}
}
using pwsh as this is running on a Linux Jenkins agent. This is part of a module where the ps1 file is under "root module directory/pwsh" but it seems to yield the following:
Error: Error running command '.'.terraform/modules/rg_test\pwsh\costalert.ps1 -subscriptionID "xxxxx" -tenantID "xxxxxxx" -clientID "xxxxxx" -clientSecret "xxxxx" -budgetAmount "1000" -rgName "rg-da_test-sbxeng-001" -emailAddresses "xxxxxx"'': exit status 1. Output: . : The module '.terraform/modules/rg_test' could not be loaded. For more information, run 'Import-Module .terraform/modules/rg_test
+ .'.terraform/modules/rg_test\pwsh\costalert.ps1 -subscriptionID
It seems to be switching the path but cannot seem to make it pick up the script and run it. Does anyone have any suggestions?
Isn't this a quoting issue?
I can successfully execute this pwsh null resource from a terraform module in an Azure DevOps linux agent. Note that only the script path is single quoted, while in your example you've got the whole command single quoted.
resource "null_resource" "create_sql_user" {
provisioner "local-exec" {
command = ".'${path.module}\\scripts\\create-sql-user.ps1' -password \"${random_password.sql_password.result}\" -username \"${var.sql_username}\" -sqlSaConnectionString \"${var.sql_server_connectionstring}\" -databaseName \"${azurerm_sql_database.db.name}\" "
interpreter = ["pwsh", "-Command"]
}
depends_on = [azurerm_sql_database.db]
}

Delay of 10mn between resource creation with Terraform Vsphere provider

Is there a way to delay module resource creation with the Terraform Vsphere provider. I want to introduce a 10mn delay due to infrastructure impediments between each VM instance creation. Each one is created by a module occurrence.
At the moment, Terraform is doing its best to deploy at maximum speed!
I tried depends_on with module: no way.
Versions used:
vsphere 6.0
terraform 0.11.3
provider.vsphere v 1.3.2
You could use a provisioner within the instance and have some kind of sleep command there, before the next VM instance is created.
resource "vsphere_virtual_machine" "vpshere_build_machine" {
provisioner "local-exec" {
command = "ping 127.0.0.1 -n 10 > nul" #or sleep 10
}
In my case I could solve it by doing this trick:
"sleep [s] && command"
For example:
provisioner "local-exec" {
command = "sleep 30 && ansible-playbook -i ..."
}

Resources