Loading...
Loading...
Convert or migrate Azure ARM (Azure Resource Manager) templates, Bicep templates, or code to Pulumi, including importing existing Azure resources. This skill MUST be loaded whenever a user requests migration, conversion, or import of ARM templates, Bicep templates, ARM code, Bicep code, or Azure resources to Pulumi.
npx skill4agent add pulumi/agent-skills pulumi-arm-to-pulumipulumi previewpulumi previewaz resource listaz resource showaz loginpulumi env run {org}/{project}/{environment} -- bash -c 'az login --service-principal -u "$ARM_CLIENT_ID" --tenant "$ARM_TENANT_ID" --federated-token "$ARM_OIDC_TOKEN"'az account showaz account list --query "[].{Name:name, SubscriptionId:id, IsDefault:isDefault}" -o tablepulumi-esc# View template structure
cat template.json | jq '.resources[] | {type: .type, name: .name}'
# View parameters
cat template.json | jq '.parameters'
# View variables
cat template.json | jq '.variables'# List all resources in a resource group
az resource list \
--resource-group <resource-group-name> \
--output json
# Get specific resource details
az resource show \
--ids <resource-id> \
--output json
# Query specific properties using JMESPath
az resource show \
--ids <resource-id> \
--query "{name:name, location:location, properties:properties}" \
--output json@pulumi/azure-native@pulumi/azure{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2023-01-01",
"name": "[parameters('storageAccountName')]",
"location": "[parameters('location')]",
"sku": {
"name": "Standard_LRS"
},
"kind": "StorageV2",
"properties": {
"supportsHttpsTrafficOnly": true
}
}import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const config = new pulumi.Config();
const storageAccountName = config.require("storageAccountName");
const location = config.require("location");
const resourceGroupName = config.require("resourceGroupName");
const storageAccount = new azure_native.storage.StorageAccount("storageAccount", {
accountName: storageAccountName,
location: location,
resourceGroupName: resourceGroupName,
sku: {
name: azure_native.storage.SkuName.Standard_LRS,
},
kind: azure_native.storage.Kind.StorageV2,
enableHttpsTrafficOnly: true,
});{
"parameters": {
"location": {
"type": "string",
"defaultValue": "eastus",
"metadata": {
"description": "Location for resources"
}
},
"instanceCount": {
"type": "int",
"defaultValue": 2,
"minValue": 1,
"maxValue": 10
},
"enableBackup": {
"type": "bool",
"defaultValue": true
},
"secretValue": {
"type": "securestring"
}
}
}const config = new pulumi.Config();
const location = config.get("location") || "eastus";
const instanceCount = config.getNumber("instanceCount") || 2;
const enableBackup = config.getBoolean("enableBackup") ?? true;
const secretValue = config.requireSecret("secretValue"); // Returns Output<string>{
"variables": {
"storageAccountName": "[concat('storage', uniqueString(resourceGroup().id))]",
"webAppName": "[concat(parameters('prefix'), '-webapp')]"
}
}import * as pulumi from "@pulumi/pulumi";
const config = new pulumi.Config();
const prefix = config.require("prefix");
const resourceGroupId = config.require("resourceGroupId");
// Simple variable
const webAppName = `${prefix}-webapp`;
// For uniqueString equivalent, use stack name or generate hash
const storageAccountName = `storage${resourceGroupId}`.toLowerCase();{
"type": "Microsoft.Network/virtualNetworks/subnets",
"apiVersion": "2023-05-01",
"name": "[concat(variables('vnetName'), '/subnet-', copyIndex())]",
"copy": {
"name": "subnetCopy",
"count": "[parameters('subnetCount')]"
},
"properties": {
"addressPrefix": "[concat('10.0.', copyIndex(), '.0/24')]"
}
}const config = new pulumi.Config();
const subnetCount = config.getNumber("subnetCount") || 3;
const subnets: azure_native.network.Subnet[] = [];
for (let i = 0; i < subnetCount; i++) {
subnets.push(new azure_native.network.Subnet(`subnet-${i}`, {
subnetName: `subnet-${i}`,
virtualNetworkName: vnet.name,
resourceGroupName: resourceGroup.name,
addressPrefix: `10.0.${i}.0/24`,
}));
}{
"type": "Microsoft.Network/publicIPAddresses",
"apiVersion": "2023-05-01",
"condition": "[parameters('createPublicIP')]",
"name": "[variables('publicIPName')]",
"location": "[parameters('location')]"
}const config = new pulumi.Config();
const createPublicIP = config.getBoolean("createPublicIP") ?? false;
let publicIP: azure_native.network.PublicIPAddress | undefined;
if (createPublicIP) {
publicIP = new azure_native.network.PublicIPAddress("publicIP", {
publicIpAddressName: publicIPName,
location: location,
resourceGroupName: resourceGroup.name,
});
}
// Handle optional references
const publicIPId = publicIP ? publicIP.id : pulumi.output(undefined);{
"type": "Microsoft.Web/sites",
"apiVersion": "2023-01-01",
"name": "[variables('webAppName')]",
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanName'))]"
]
}// Implicit dependency (preferred)
const webApp = new azure_native.web.WebApp("webApp", {
name: webAppName,
resourceGroupName: resourceGroup.name,
serverFarmId: appServicePlan.id, // Implicit dependency through property reference
});
// Explicit dependency (when needed)
const webApp = new azure_native.web.WebApp("webApp", {
name: webAppName,
resourceGroupName: resourceGroup.name,
serverFarmId: appServicePlan.id,
}, {
dependsOn: [appServicePlan], // Explicit dependency
});{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2021-04-01",
"name": "nestedTemplate",
"properties": {
"mode": "Incremental",
"template": {
"resources": [...]
}
}
}class NetworkComponent extends pulumi.ComponentResource {
public readonly vnet: azure_native.network.VirtualNetwork;
public readonly subnets: azure_native.network.Subnet[];
constructor(name: string, args: NetworkComponentArgs, opts?: pulumi.ComponentResourceOptions) {
super("custom:azure:NetworkComponent", name, {}, opts);
const defaultOptions = { parent: this };
this.vnet = new azure_native.network.VirtualNetwork(`${name}-vnet`, {
virtualNetworkName: args.vnetName,
resourceGroupName: args.resourceGroupName,
location: args.location,
addressSpace: {
addressPrefixes: [args.addressPrefix],
},
}, defaultOptions);
this.subnets = args.subnets.map((subnet, i) =>
new azure_native.network.Subnet(`${name}-subnet-${i}`, {
subnetName: subnet.name,
virtualNetworkName: this.vnet.name,
resourceGroupName: args.resourceGroupName,
addressPrefix: subnet.addressPrefix,
}, defaultOptions)
);
this.registerOutputs({
vnetId: this.vnet.id,
subnetIds: this.subnets.map(s => s.id),
});
}
}{
"outputs": {
"storageAccountName": {
"type": "string",
"value": "[variables('storageAccountName')]"
},
"storageAccountId": {
"type": "string",
"value": "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
}
}
}export const storageAccountName = storageAccount.name;
export const storageAccountId = storageAccount.id;@pulumi/azure{
"type": "Microsoft.Network/virtualNetworks",
"apiVersion": "2023-05-01",
"name": "[parameters('vnetName')]",
"location": "[parameters('location')]",
"properties": {
"addressSpace": {
"addressPrefixes": [
"10.0.0.0/16"
]
},
"subnets": [
{
"name": "default",
"properties": {
"addressPrefix": "10.0.1.0/24"
}
},
{
"name": "apps",
"properties": {
"addressPrefix": "10.0.2.0/24"
}
}
]
}
}import * as pulumi from "@pulumi/pulumi";
import * as azure from "@pulumi/azure";
const config = new pulumi.Config();
const vnetName = config.require("vnetName");
const location = config.require("location");
const resourceGroupName = config.require("resourceGroupName");
const vnet = new azure.network.VirtualNetwork("vnet", {
name: vnetName,
location: location,
resourceGroupName: resourceGroupName,
addressSpaces: ["10.0.0.0/16"],
subnets: [
{
name: "default",
addressPrefix: "10.0.1.0/24",
},
{
name: "apps",
addressPrefix: "10.0.2.0/24",
},
],
});{
"resources": [
{
"type": "Microsoft.Web/serverfarms",
"apiVersion": "2023-01-01",
"name": "[parameters('appServicePlanName')]",
"location": "[parameters('location')]",
"sku": {
"name": "B1",
"tier": "Basic",
"size": "B1",
"capacity": 1
},
"kind": "linux",
"properties": {
"reserved": true
}
},
{
"type": "Microsoft.Web/sites",
"apiVersion": "2023-01-01",
"name": "[parameters('webAppName')]",
"location": "[parameters('location')]",
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', parameters('appServicePlanName'))]"
],
"properties": {
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('appServicePlanName'))]",
"siteConfig": {
"linuxFxVersion": "NODE|18-lts",
"appSettings": [
{
"name": "WEBSITE_NODE_DEFAULT_VERSION",
"value": "~18"
}
]
}
}
}
]
}import * as pulumi from "@pulumi/pulumi";
import * as azure from "@pulumi/azure";
const config = new pulumi.Config();
const appServicePlanName = config.require("appServicePlanName");
const webAppName = config.require("webAppName");
const location = config.require("location");
const resourceGroupName = config.require("resourceGroupName");
const appServicePlan = new azure.appservice.ServicePlan("appServicePlan", {
name: appServicePlanName,
location: location,
resourceGroupName: resourceGroupName,
osType: "Linux",
skuName: "B1",
});
const webApp = new azure.appservice.LinuxWebApp("webApp", {
name: webAppName,
location: location,
resourceGroupName: resourceGroupName,
servicePlanId: appServicePlan.id,
siteConfig: {
applicationStack: {
nodeVersion: "18-lts",
},
},
appSettings: {
"WEBSITE_NODE_DEFAULT_VERSION": "~18",
},
});LinuxWebAppWindowsWebAppWebApp!.apply()// ❌ WRONG - Will cause TypeScript errors
const webAppUrl = `https://${webApp.defaultHostName!}`;
// ✅ CORRECT - Handle undefined safely
const webAppUrl = webApp.defaultHostName.apply(hostname =>
hostname ? `https://${hostname}` : ""
);name// ARM: "name": "myStorageAccount"
// Pulumi:
new azure_native.storage.StorageAccount("logicalName", {
accountName: "mystorageaccount", // Actual Azure resource name
// ...
});// ARM: "apiVersion": "2023-01-01"
// Pulumi: API version is embedded in the provider.apply()azureazure-nativeconcat()uniqueString()importpulumi-cdk-importer/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}pulumi preview# Set Azure region
pulumi config set azure-native:location eastus --stack dev
# Set application parameters
pulumi config set storageAccountName mystorageaccount --stack dev
# Set secret parameters
pulumi config set --secret adminPassword MyS3cr3tP@ssw0rd --stack devpulumi stack outputpulumi stack graphpulumi config set