PageSourceSearch

https://www.infracost.io/docs/assets/js/1fa064cd.fa934907.js

js infracost.io collected 2026-10-02 05:47:56 UTC 25,477 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunkinfracost_docs=self.webpackChunkinfracost_docs||[]).push([[2182],{39525(e,s,r){r.r(s),r.d(s,{assets:()=>o,contentTitle:()=>t,default:()=>h,frontMatter:()=>c,metadata:()=>n,toc:()=>l});const n=JSON.parse('{"id":"features/arm","title":"ARM Templates","description":"Overview","source":"@site/docs/features/arm.md","sourceDirName":"features","slug":"/features/arm","permalink":"/docs/features/arm","draft":false,"unlisted":false,"tags":[],"version":"current","frontMatter":{"slug":"arm","title":"ARM Templates"},"sidebar":"someSidebar","previous":{"title":"CDK","permalink":"/docs/features/cdk"},"next":{"title":"Environment variables","permalink":"/docs/features/environment_variables"}}');var d=r(74848),i=r(28453);const c={slug:"arm",title:"ARM Templates"},t=void 0,o={},l=[{value:"Overview",id:"overview",level:2},{value:"Bicep",id:"bicep",level:2},{value:"Function support",id:"function-support",level:2},{value:"Deployment scope context",id:"deployment-scope-context",level:2},{value:"Parameters",id:"parameters",level:2},{value:"Nested and linked templates",id:"nested-and-linked-templates",level:2},{value:"Usage-based resources",id:"usage-based-resources",level:2},{value:"Limitations",id:"limitations",level:2},{value:"Template Specs",id:"template-specs",level:3},{value:"Tagging policies",id:"tagging-policies",level:3}];function a(e){const s={a:"a",admonition:"admonition",code:"code",em:"em",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,i.R)(),...e.components};return(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)(s.h2,{id:"overview",children:"Overview"}),"\n",(0,d.jsxs)(s.p,{children:["Infracost supports Azure Resource Manager (ARM) deployment templates in JSON. Templates are detected automatically by their ",(0,d.jsx)(s.code,{children:"$schema"})," (any ",(0,d.jsx)(s.code,{children:"\u2026/deploymentTemplate.json#"})," URL, covering resource-group, subscription, management-group and tenant scopes), and, as a fallback for nested templates that omit the schema, by resources whose ",(0,d.jsx)(s.code,{children:"type"})," starts with ",(0,d.jsx)(s.code,{children:"Microsoft."})]}),"\n",(0,d.jsxs)(s.p,{children:["Bicep is supported by transpiling to ARM JSON first \u2014 see ",(0,d.jsx)(s.a,{href:"#bicep",children:"Bicep"})," below. The following outlines support for the various ARM template features:"]}),"\n",(0,d.jsxs)(s.table,{children:[(0,d.jsx)(s.thead,{children:(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.th,{children:"Feature"}),(0,d.jsx)(s.th,{children:"Support"})]})}),(0,d.jsxs)(s.tbody,{children:[(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:"Resources (array form)"}),(0,d.jsx)(s.td,{children:"\u2705"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:"Resources (symbolic-name object form)"}),(0,d.jsx)(s.td,{children:"\u2705"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsxs)(s.td,{children:["Parameters and ",(0,d.jsx)(s.code,{children:"defaultValue"})]}),(0,d.jsx)(s.td,{children:"\u2705"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsxs)(s.td,{children:["Parameters files (",(0,d.jsx)(s.code,{children:"*.parameters.json"}),")"]}),(0,d.jsx)(s.td,{children:"\u2705"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:"Inline parameter overrides"}),(0,d.jsx)(s.td,{children:"\u2705"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:"Variables"}),(0,d.jsx)(s.td,{children:"\u2705"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:"Outputs"}),(0,d.jsx)(s.td,{children:"\u2705"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:"Template functions (expressions)"}),(0,d.jsx)(s.td,{children:"\u2705"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsxs)(s.td,{children:[(0,d.jsx)(s.code,{children:"copy"})," loops (resource, property, variable)"]}),(0,d.jsx)(s.td,{children:"\u2705"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsxs)(s.td,{children:[(0,d.jsx)(s.code,{children:"copy"})," loops (output)"]}),(0,d.jsx)(s.td,{children:"\u2705"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:(0,d.jsx)(s.code,{children:"condition"})}),(0,d.jsx)(s.td,{children:"\u2705"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsxs)(s.td,{children:[(0,d.jsx)(s.code,{children:"dependsOn"})," and implicit dependencies"]}
1),(0,d.jsx)(s.td,{children:"\u2705"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:(0,d.jsx)(s.code,{children:"reference()"})}),(0,d.jsx)(s.td,{children:"\u2705"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:"Nested templates"}),(0,d.jsx)(s.td,{children:"\u2705"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:"Linked templates (local / relative path)"}),(0,d.jsx)(s.td,{children:"\u2705"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:"Linked templates (remote HTTP/HTTPS)"}),(0,d.jsx)(s.td,{children:"\u2705"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsxs)(s.td,{children:["User-defined functions (",(0,d.jsx)(s.code,{children:"functions"}),")"]}),(0,d.jsx)(s.td,{children:"\u2705"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:"Deployment scopes (RG / sub / MG / tenant)"}),(0,d.jsx)(s.td,{children:"\u2705"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:"Template Specs"}),(0,d.jsx)(s.td,{children:"\u274c"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:"Bicep (direct)"}),(0,d.jsx)(s.td,{children:"\u274c"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsxs)(s.td,{children:["Bicep ",(0,d.jsx)(s.code,{children:"@metadata"})," / expected load"]}),(0,d.jsx)(s.td,{children:"\u274c"})]})]})]}),"\n",(0,d.jsxs)(s.p,{children:["Resources may be written either as an array (",(0,d.jsx)(s.code,{children:'"resources": [ \u2026 ]'}),") or, using the newer symbolic-name syntax, as an object keyed by symbolic name (",(0,d.jsx)(s.code,{children:'"resources": { "myVm": { \u2026 } }'}),"). Both are supported."]}),"\n",(0,d.jsx)(s.p,{children:"Where a template omits an optional cost-relevant property (an SKU capacity, a node count, a load-balancer SKU), Infracost applies Azure's documented default for that property rather than pricing it as zero, and marks the value as a default so policies can tell inferred values from authored ones."}),"\n",(0,d.jsx)(s.h2,{id:"bicep",children:"Bicep"}),"\n",(0,d.jsxs)(s.p,{children:["The parser consumes ",(0,d.jsx)(s.strong,{children:"ARM JSON only"})," \u2014 it does not parse ",(0,d.jsx)(s.code,{children:".bicep"})," files directly, and it does not run the Bicep transpiler for you. This mirrors how the CLI handles ",(0,d.jsx)(s.a,{href:"/docs/features/cdk/",children:"CDK"}),": parse the generated template, don't run the toolchain (which can have side effects and requires the relevant CLI to be installed)."]}),"\n",(0,d.jsx)(s.p,{children:"To cost a Bicep file, transpile it to ARM JSON first, then point Infracost at the output:"}),"\n",(0,d.jsx)(s.pre,{children:(0,d.jsx)(s.code,{className:"language-shell",children:"# Compile Bicep to an ARM JSON template\nbicep build main.bicep --outfile main.json\n# or, via the Azure CLI\naz bicep build --file main.bicep --outfile main.json\n\n# Then scan the directory containing the generated JSON\ninfracost scan .\n"})}),"\n",(0,d.jsxs)(s.p,{children:["This requires the ",(0,d.jsxs)(s.a,{href:"https://learn.microsoft.com/azure/azure-resource-manager/bicep/install",children:[(0,d.jsx)(s.code,{children:"bicep"})," CLI"]})," on your ",(0,d.jsx)(s.code,{children:"PATH"}),". If you point Infracost at a ",(0,d.jsx)(s.code,{children:".bicep"})," file directly, it returns an actionable error telling you to transpile first rather than a cryptic JSON parse failure."]}),"\n",(0,d.jsx)(s.admonition,{type:"note",children:(0,d.jsxs)(s.p,{children:["Any Bicep ",(0,d.jsx)(s.code,{children:"@metadata"})," decorators (including expected-load metadata) are not read. ",(0,d.jsx)(s.code,{children:"expectedLoad"})," is stripped when Bicep compiles to ARM JSON, and the parser does not extract it."]})}),"\n",(0,d.jsx)(s.h2,{id:"function-support",children:"Function support"}),"\n",(0,d.jsxs)(s.p,{children:["ARM template expressions (",(0,d.jsx)(s.code,{children:'"[ \u2026 ]"'}),") are evaluated during the scan. The following built-in functions are supported:"]}),"\n",(0,d.jsxs)(s.table,{children:[(0,d.jsx)(s.thead,{children:(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.th,{children:"Category"}),(0,d.jsx)(s.th,{children:"Functions"}),(0,d.jsx)(s.th,{children:"Support"})]})}),(0,d.jsxs)(s.tbody,{children:[(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:"Numeric"}),(0,d.jsxs)(s.td,{children:[(0,d.jsx)(s.code,{children:"add"}),", ",(0,d.jsx)(s.code,{children:"sub"}),", ",(0,d.jsx)(s.code,{children:"mul"}),", ",(0,d.jsx)(s.code,{children:"div"}),", ",(0,d.jsx)(s.code,{children:"mod"}),", ",(0,d.jsx)(s.code,{children:"min"}),", ",(0,d.jsx)(s.code,{children:"max"}),", ",(0,d.jsx)(s.code,{children:"range"}),", ",(0,d.jsx)(s.code,{children:"int"}),", ",(0,d.jsx)(s.code,{children:"float"})]}),(0,d.jsx)(s.td,{children:"\u2705"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:"Logical & comparison"}),(0,d.jsxs)(s.td,{children:[(0,d.jsx)(s.code,{children:"equals"}),", ",(0,d.jsx)(s.code,{children:"less"}),", ",(0,d.jsx)(s.code,{children:"lessOrEquals"}),", ",(0,d.jsx)(s.code,{children:"greater"}),", ",(0,d.jsx)(s.code,{children:"greaterOrEquals"}),", ",(0,d.jsx)(s.code,{children:"if"}),", ",(0,d.jsx)(s.code,{children:"and"}),", ",(0,d.jsx)(s.code,{children:"or"}),", ",(0,d.jsx)(s.code,{children:"not"}),", ",(0,d.jsx)(s.code,{children:"bool"}),", ",(0,d.jsx)(s.code,{children:"true"}),", ",(0,d.jsx)(s.code,{children:"false"}),", ",(0,d.jsx)(s.code,{children:"null"})]}),(0,d.jsx)(s.td,{children:"\u2705"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:"String"}),(0,d.jsxs)(s.td,{children:[(0,d.jsx)(s.code,{children:"concat"}),", ",(0,d.jsx)(s.code,{children:"format"}),", ",(0,d.jsx)(s.code,{children:"substring"}),", ",(0,d.jsx)(s.code,{children:"replace"}),", ",(0,d.jsx)(s.code,{children:"trim"}),", ",(0,d.jsx)(s.code,{children:"split"}),", ",(0,d.jsx)(s.code,{children:"join"}),", ",(0,d.jsx)(s.code,{children:"toLower"}),", ",(0,d.jsx)(s.code,{children:"toUpper"}),", ",(0,d.jsx)(s.code,{children:"startsWith"}),", ",(0,d.jsx)(s.code,{children:"endsWith"}),", ",(0,d.jsx)(s.code,{children:"indexOf"}),", ",(0,d.jsx)(s.code,{children:"lastIndexOf"}),", ",(0,d.jsx)(s.code,{children:"padLeft"}),", ",(0,d.jsx)(s.code,{children:"string"}),", ",(0,d.jsx)(s.code,{children:"base64"}),", ",(0,d.jsx)(s.code,{children:"base64ToString"}),", ",(0,d.jsx)(s.code,{children:"base64ToJson"}),", ",(0,d.jsx)(s.code,{children:"dataUri"}),", ",(0,d.jsx)(s.code,{children:"dataUriToString"}),", ",(0,d.jsx)(s.code,{children:"uri"}),", ",(0,d.jsx)(s.code,{children:"uriComponent"}),", ",(0,d.jsx)(s.code,{children:"uriComponentToString"}),", ",(0,d.jsx)(s.code,{children:"uniqueString"}),", ",(0,d.jsx)(s.code,{children:"guid"}),", ",(0,d.jsx)(s.code,{children:"newGuid"})]}),(0,d.jsx)(s.td,{children:"\u2705"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:"Array & object"}),(0,d.jsxs)(s.td,{children:[(0,d.jsx)(s.code,{children:"array"}),", ",(0,d.jsx)(s.code,{children:"createArray"}),", ",(0,d.jsx)(s.code,{children:"createObject"}),", ",(0,d.jsx)(s.code,{children:"coalesce"}),", ",(0,d.jsx)(s.code,{children:"contains"}),", ",(0,d.jsx)(s.code,{children:"empty"}),", ",(0,d.jsx)(s.code,{children:"length"}),", ",(0,d.jsx)(s.code,{children:"first"}),", ",(0,d.jsx)(s.code,{children:"last"}),", ",(0,d.jsx)(s.code,{children:"take"}),", ",(0,d.jsx)(s.code,{children:"skip"}),", ",(0,d.jsx)(s.code,{children:"union"}),", ",(0,d.jsx)(s.code,{children:"intersection"}),", ",(0,d.jsx)(s.code,{children:"flatten"}),", ",(0,d.jsx)(s.code,{children:"shallowMerge"}),", ",(0,d.jsx)(s.code,{children:"items"}),", ",(0,d.jsx)(s.code,{children:"objectKeys"}),", ",(0,d.jsx)(s.code,{children:"tryGet"}),", ",(0,d.jsx)(s.code,{children:"json"})]}),(0,d.jsx)(s.td,{children:"\u2705"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:"Lambda (higher-order)"}),(0,d.jsxs)(s.td,{children:[(0,d.jsx)(s.code,{children:"lambda"}),", ",(0,d.jsx)(s.code,{children:"lambdaVariables"}),", ",(0,d.jsx)(s.code,{children:"map"}),", ",(0,d.jsx)(s.code,{children:"mapValues"}),", ",(0,d.jsx)(s.code,{children:"filter"}),", ",(0,d.jsx)(s.code,{children:"reduce"}),", ",(0,d.jsx)(s.code,{children:"sort"}),", ",(0,d.jsx)(s.code,{children:"toObject"}),", ",(0,d.jsx)(s.code,{children:"groupBy"})]}),(0,d.jsx)(s.td,{children:"\u2705"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:"Date"}),(0,d.jsxs)(s.td,{children:[(0,d.jsx)(s.code,{children:"dateTimeAdd"}),", ",(0,d.jsx)(s.code,{children:"dateTimeFromEpoch"}),", ",(0,d.jsx)(s.code,{children:"dateTimeToEpoch"}),", ",(0,d.jsx)(s.code,{children:"utcNow"})]}),(0,d.jsx)(s.td,{children:"\u2705"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:"Networking (CIDR)"}),(0,d.jsxs)(s.td,{children:[(0,d.jsx)(s.code,{children:"cidrSubnet"}),", ",(0,d.jsx)(s.code,{children:"cidrHost"}),", ",(0,d.jsx)(s.code,{children:"parseCidr"})]}),(0,d.jsx)(s.td,{children:"\u2705"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:"Copy"}),(0,d.jsx)(s.td,{children:(0,d.jsx)(s.code,{children:"copyIndex"})}),(0,d.jsx)(s.td,{children:"\u2705"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:"Parameters & variables"}),(0,d.jsxs)(s.td,{children:[(0,d.jsx)(s.code,{children:"parameters"}),", ",(0,d.jsx)(s.code,{children:"variables"})]}),(0,d.jsx)(s.td,{children:"\u2705"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:"Deployment & scope"}),(0,d.jsxs)(s.td,{children:[(0,d.jsx)(s.code,{children:"resourceGroup"}),", ",(0,d.jsx)(s.code,{children:"subscription"}),", ",(0,d.jsx)(s.code,{children:"tenant"}),", ",(0,d.jsx)(s.code,{children:"managementGroup"}),", ",(0,d.jsx)(s.code,{children:"deployment"}),", ",(0,d.jsx)(s.code,{children:"environment"}),", ",(0,d.jsx)(s.code,{children:"pickZones"})]}),(0,d.jsx)(s.td,{children:"\u2705"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:"Resource"}),(0,d.jsxs)(s.td,{children:[(0,d.jsx)(s.code,{children:"resourceId"}),", ",(0,d.jsx)(s.code,{children:"subscriptionResourceId"}),", ",(0,d.jsx)(s.code,{children:"tenantResourceId"}),", ",(0,d.jsx)(s.code,{children:"managementGroupResourceId"}),", ",(0,d.jsx)(s.code,{children:"extensionResourceId"}),", ",(0,d.jsx)(s.code,{children:"reference"}),", ",(0,d.jsx)(s.code,{children:"listKeys"}),", ",(0,d.jsx)(s.code,{children:"listSas"}),", ",(0,d.jsx)(s.code,{children:"listAccountSas"}),", ",(0,d.jsx)(s.code,{children:"listCallbackUrl"}),", ",(0,d.jsx)(s.code,{children:"listSecrets"}),", ",(0,d.jsx)(s.code,{children:"deployer"})]}),(0,d.jsx)(s.td,{children:"\u2705"})]})]})]}),"\n",(0,d.jsxs)(s.p,{children:[(0,d.jsx)(s.strong,{children:"User-defined functions"})," declared in the template's ",(0,d.jsx)(s.code,{children:"functions"})," section are also supported and evaluated like built-ins."]}),"\n",(0,d.jsxs)(s.p,{children:["Function, parameter, variable and object-property names are resolved ",(0,d.jsx)(s.strong,{children:"case-insensitively"}),", matching ARM \u2014 so ",(0,d.jsx)(s.code,{children:"parameters('VmSize')"})," resolves a ",(0,d.jsx)(s.code,{children:"vmSize"})," declaration and ",(0,d.jsx)(s.code,{children:"sku.name"})," reads a ",(0,d.jsx)(s.code,{children:'"Sku": { "Name": \u2026 }'})," block. ",(0,d.jsx)(s.code,{children:"format()"})," honors .NET numeric format specifiers (for example ",(0,d.jsx)(s.code,{children:"format('{0:D3}', 5)"})," \u2192 ",(0,d.jsx)(s.code,{children:"005"}),"), and string functions such as ",(0,d.jsx)(s.code,{children:"substring"})," and ",(0,d.jsx)(s.code,{children:"length"})," count Unicode characters rather than bytes."]}),"\n",(0,d.jsxs)(s.admonition,{type:"note",children:[(0,d.jsxs)(s.p,{children:[(0,d.jsx)(s.code,{children:"reference"}),", ",(0,d.jsx)(s.code,{children:"listKeys"}),", the ",(0,d.jsx)(s.code,{children:"list*"})," family (",(0,d.jsx)(s.code,{children:"listSas"}),", ",(0,d.jsx)(s.code,{children:"listAccountSas"}),", ",(0,d.jsx)(s.code,{children:"listCallbackUrl"}),", ",(0,d.jsx)(s.code,{children:"listSecrets"}),"), ",(0,d.jsx)(s.code,{children:"deployer"}),", ",(0,d.jsx)(s.code,{children:"environment"})," and ",(0,d.jsx)(s.code,{children:"deployment"})," depend on deployment-time state that isn't available during static analysis. Their results are treated as ",(0,d.jsx)(s.strong,{children:"open objects"}),": fields we do know (for example ",(0,d.jsx)(s.code,{children:"environment()"}
1),"'s Azure public-cloud suffixes, or a ",(0,d.jsx)(s.code,{children:"reference()"}),"d resource's authored properties) resolve to their real values, and any field we can't know resolves to an \"unknown\" that keeps a deeper property chain evaluating instead of failing. A ",(0,d.jsx)(s.code,{children:"reference()"})," to a resource stands in with that resource's id, so composed values stay distinct. Values that only exist in live Azure state \u2014 secrets, connection strings, generated endpoints \u2014 are not real."]}),(0,d.jsx)(s.p,{children:"A call to an unrecognized function produces a non-critical warning and is left unresolved rather than failing the scan; this is rare in practice and seldom affects the cost estimate."})]}),"\n",(0,d.jsx)(s.h2,{id:"deployment-scope-context",children:"Deployment scope context"}),"\n",(0,d.jsxs)(s.p,{children:["ARM functions like ",(0,d.jsx)(s.code,{children:"resourceGroup()"}),", ",(0,d.jsx)(s.code,{children:"subscription()"})," and ",(0,d.jsx)(s.code,{children:"tenant()"})," resolve against the deployment scope. Infracost fills these with synthetic defaults (for example ",(0,d.jsx)(s.code,{children:"location"})," defaults to ",(0,d.jsx)(s.code,{children:"eastus"}),") so templates evaluate without a live Azure connection. Display-form locations (",(0,d.jsx)(s.code,{children:'"East US"'}),") are normalized to their canonical form (",(0,d.jsx)(s.code,{children:"eastus"}),") for price lookups."]}),"\n",(0,d.jsxs)(s.p,{children:["When a resource's region comes from one of these synthetic defaults \u2014 the ubiquitous ",(0,d.jsx)(s.code,{children:'"location": "[resourceGroup().location]"'})," pattern with no configured ",(0,d.jsx)(s.code,{children:"location"})," \u2014 it is marked as synthetic, so region-specific FinOps recommendations are not made from a region the template never stated. Set ",(0,d.jsx)(s.code,{children:"location"})," in the config below to price against your real region. You can override the scope values per project in an ",(0,d.jsxs)(s.a,{href:"/docs/features/config_file/",children:[(0,d.jsx)(s.code,{children:"infracost.yml"})," config file"]}),":"]}),"\n",(0,d.jsx)(s.pre,{children:(0,d.jsx)(s.code,{className:"language-yaml",children:"version: 0.1\nprojects:\n  - path: .\n    azure:\n      subscription_id: 00000000-0000-0000-0000-000000000000\n      tenant_id: 00000000-0000-0000-0000-000000000000\n      resource_group_name: my-rg\n      location: westeurope\n      management_group_id: my-mg\n"})}),"\n",(0,d.jsx)(s.h2,{id:"parameters",children:"Parameters"}),"\n",(0,d.jsxs)(s.p,{children:["Parameter values are resolved in this order, matching ",(0,d.jsx)(s.code,{children:"az deployment"})," precedence (later wins):"]}),"\n",(0,d.jsxs)(s.ol,{children:["\n",(0,d.jsxs)(s.li,{children:["The parameter's ",(0,d.jsx)(s.code,{children:"defaultValue"})," in the template."]}),"\n",(0,d.jsxs)(s.li,{children:["A parameters file. Infracost auto-discovers a sibling parameters file next to the root template \u2014 ",(0,d.jsx)(s.code,{children:"<template>.parameters.json"}),", ",(0,d.jsx)(s.code,{children:"<template>.params.json"}),", or a bare ",(0,d.jsx)(s.code,{children:"parameters.json"})," / ",(0,d.jsx)(s.code,{children:"params.json"})," \u2014 and recognizes per-environment files in the common shapes (",(0,d.jsx)(s.code,{children:"<template>.<env>.parameters.json"}),", ",(0,d.jsx)(s.code,{children:"<template>.parameters.<env>.json"}),", ",(0,d.jsx)(s.code,{children:"parameters.<env>.json"}),", \u2026). Environment names come from your configured environments, falling back to the standard set (",(0,d.jsx)(s.code,{children:"dev"}),", ",(0,d.jsx)(s.code,{children:"staging"}),", ",(0,d.jsx)(s.code,{children:"prod"}),", \u2026); each environment is priced separately with its own parameter values. You can also point at a file explicitly."]}),"\n",(0,d.jsx)(s.li,{children:"Inline parameter overrides supplied to the scan."}),"\n"]}),"\n",(0,d.jsx)(s.h2,{id:"nested-and-linked-templates",children:"Nested and linked templates"}),"\n",(0,d.jsxs)(s.ul,{children:["\n",(0,d.jsxs)(s.li,{children:[(0,d.jsx)(s.strong,{children:"Nested templates"})," (",(0,d.jsx)(s.code,{children:"Microsoft.Resources/deployments"})," with an inline ",(0,d.jsx)(s.code,{children:"template"}),") are expanded and priced, in both outer- and inner-scope evaluation modes. This includes ",(0,d.jsx)(s.code,{children:"copy"})," loops over deployments and copy loops declared ",(0,d.jsx)(s.em,{children:"inside"})," an inner-scope nested template."]}),"\n",(0,d.jsxs)(s.li,{children:[(0,d.jsx)(s.strong,{children:"Linked templates"})," referenced by a local ",(0,d.jsx)(s.code,{children:"relativePath"})," or ",(0,d.jsx)(s.code,{children:"file://"})," URI are resolved and priced, provided the target stays within the scanned directory."]}),"\n",(0,d.jsxs)(s.li,{children:[(0,d.jsxs)(s.strong,{children:["Linked templates referenced by an ",(0,d.jsx)(s.code,{children:"http"}),"/",(0,d.jsx)(s.code,{children:"https"})," URL whose file ships in the scanned directory"]})," are resolved from the local copy \u2014 no network access. This covers the ubiquitous ",(0,d.jsx)(s.code,{children:"_artifactsLocation"})," staging pattern, including the ",(0,d.jsx)(s.code,{children:"_artifactsLocation"})," default of ",(0,d.jsx)(s.code,{children:"[deployment().properties.templateLink.uri]"}),", where templates compose sibling paths with ",(0,d.jsx)(s.code,{children:"uri(...)"})," even though the files live in the repo."]}),"\n",(0,d.jsxs)(s.li,{children:[(0,d.jsx)(s.strong,{children:"Genuinely-remote linked templates"})," (an ",(0,d.jsx)(s.code,{children:"http"}),"/",(0,d.jsx)(s.code,{children:"https"})," ",(0,d.jsx)(s.code,{children:"templateLink.uri"})," with no local copy) are fetched over the network. Fetching is on by default and can be disabled; it is SSRF-guarded (connections to loopback, private, link-local and cloud-metadata addresses are refused at dial time), size-capped, and bounded by a per-request timeout."]}),"\n",(0,d.jsxs)(s.li,{children:["Parameters passed to a nested or linked deployment are resolved from either inline ",(0,d.jsx)(s.code,{children:"properties.parameters"})," or an external parameters file referenced by ",(0,d.jsx)(s.code,{children:"properties.parametersLink"})," (resolved through the same local/remote loader as ",(0,d.jsx)(s.code,{children:"templateLink"}),")."]}),"\n"]}),"\n",(0,d.jsx)(s.h2,{id:"usage-based-resources",children:"Usage-based resources"}),"\n",(0,d.jsxs)(s.p,{children:[(0,d.jsx)(s.a,{href:"/docs/features/usage_based_resources/",children:"Usage values"})," are matched to ARM resources by address. An ARM resource's address is its type followed by its evaluated name, for example ",(0,d.jsx)(s.code,{children:"Microsoft.Web/sites/my-function-app"})," or ",(0,d.jsx)(s.code,{children:"Microsoft.Storage/storageAccounts/mystorageacct"}),". Use those addresses as keys in ",(0,d.jsx)(s.code,{children:"infracost-usage.yml"}),"; usage values written against a Terraform address (",(0,d.jsx)(s.code,{children:"azurerm_linux_function_app.my_app"}),") do not carry over."]}),"\n",(0,d.jsx)(s.h2,{id:"limitations",children:"Limitations"}),"\n",(0,d.jsx)(s.h3,{id:"template-specs",children:"Template Specs"}),"\n",(0,d.jsxs)(s.p,{children:["Template Specs (",(0,d.jsx)(s.code,{children:"Microsoft.Resources/templateSpecs"}),") are not expanded. Resources defined inside a Template Spec are not priced."]}),"\n",(0,d.jsx)(s.h3,{id:"tagging-policies",children:"Tagging policies"}),"\n",(0,d.jsxs)(s.p,{children:["Tags declared on a ",(0,d.jsx)(s.code,{children:"Microsoft.Resources/resourceGroups"})," resource ",(0,d.jsx)(s.strong,{children:"within the scanned template"})," (common in subscription-scope deployments) are inherited by the resources deployed into that resource group, mirroring how provider ",(0,d.jsx)(s.code,{children:"default_tags"})," work in Terraform \u2014 a resource's own tags win on conflict. This means resource-group-level tagging that lives in your templates is visible to tagging policies."]}),"\n",(0,d.jsx)(s.p,{children:"As with CloudFormation, Infracost tagging policies flag resources whose tag values are invalid, but do not flag missing tags on ARM resources. Tags applied entirely outside the template \u2014 at the subscription level, on pre-existing resource groups, or via Azure Policy \u2014 are invisible to static analysis, so missing tags are not checked in order to avoid false positives."})]})}function h(e={}){const{wrapper:s}={...(0,i.R)(),...e.components};return s?(0,d.jsx)(s,{...e,children:(0,d.jsx)(a,{...e})}):a(e)}},28453(e,s,r){r.d(s,{R:()=>c,x:()=>t});var n=r(96540);const d={},i=n.createContext(d);function c(e){const s=n.useContext(i);return n.useMemo(function(){return"function"==typeof e?e(s):{...s,...e}},[s,e])}function t(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(d):e.components||d:c(e.components),n.createElement(i.Provider,{value:s},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.