🗂
Bicepで使える構文と使い所をまとめてみる(1)
bicepで使える構文と使い所を整理してみようと思います。ものによっては、もっとスマートな書き方があるでしょうが、そう感じるようになったらそれはそれで良いのではないでしょうか。
Jsonファイルで外部化したパラメータを読み出す
-
loadTextContext()
でファイル読み込み - 読み込んだ文字列を
json()
でparse
※ 使ったことないが、loadJsonContent()
と書いてもよいかもしれません。bicep始めた頃にはまだ無かった関数なので、、、 - データ項目は
string
として扱われる - 数値にしたい場合は、
int()
でparseする
- 以下は、PostgreSQL Flexible Serverのパラメータ指定をJsonファイルで外部ファイル定義とした例
-
param
で指定してもよいが、今回は例として、jsonファイルから読み出し
実際には、ipアドレスリストなどを外部ファイル化する使い方が多い(例は後ほど) -
int()
の例としてpsqlのparameterをjsonから読み出し
-
var _psql_define = json(loadTextContent('../env/psql.json')).psql
// var _psql_define = loadJsonContent('./env/psql.json').psql
var _sku_name = _psql_define.sku.name
var _sku_tier = _psql_define.sku.tier
var _psql_version = _psql_define.version
var _storage_size = int(_psql_define.storageSizeGB)
- jsonファイル定義例
{
"psql": {
"version": "14",
"sku": {
"name": "Standard_B1ms",
"tier": "Burstable"
},
"storageSizeGB": "32",
}
}
for文
-
for
文を使ってデプロイ処理をループすることが可能 - デプロイ処理に限らず変数の処理でも
for
文を利用可能
- 以下は、リソースグループ名をリスト化して
for
文で作成する例- デプロイスコープを
subscription
にしているので、location
を指定 - 多くのテンプレートでは、
location
を明示的に指定するのは、リソースグループのデプロイ時だけになると思う
リソースグループのデプロイ時だけ、指定するようになるよう作成することをおすすめ
- デプロイスコープを
targetScope = 'subscription'
param location string = 'japaneast'
var _rgs = [
'rg-app-01'
'rg-db-01'
'rg-net-01'
]
resource rg 'Microsoft.Resources/resourceGroups@2022-09-01' = [for name in _rgs: {
name: name
location: location
}]
ResourceGroup関数とlocation
-
resourceGroup()
の引数なしはデプロイで指定したリソースグループの情報を取得 - リソースグループの
location
は、resourceGroup()
の変数として格納されている - デプロイするリソースの
location
をリソースグループと同じlocation
ことでlocation
をハードコードする事がなくなりテンプレートを再利用しやすくなる
- 以下は、Managed Idのデプロイ例
param location string = resourceGroup().location
param id_name string
resource id 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31'= {
name: id_name
location: location
}
三項演算子とempty関数
- bicepでは条件判定に三項演算子を使用する
※if
文は別の用途で使用 - 値、配列の空文字、空配列、null判定は
empty()
を使用する
- 以下は、ActivityLogの診断設定のデプロイテンプレートの例
- エクスポート先(Storage Account, LogAnalytics workspace)を
empty()
を使い、resourceId
が指定されたかどうかを判断し、指定されていなければ、null
を設定、指定されていれば指定した値を設定する - ActivityLogの場合は、
scope
にsubscription()
を設定
- エクスポート先(Storage Account, LogAnalytics workspace)を
targetScope = 'subscription'
param log_id string = ''
param st_id string
param logs array = [
// 省略
]
resource diag 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = {
name: 'diag-log'
scope: subscription()
properties: {
workspaceId: empty(log_id) ? null : log_id
storageAccountId: empty(st_id) ? null : st_id
logs: logs
}
}
resourceId関数
-
resourceId()
でリソースIDを取得する - 前述の通り、
for
文はデプロイ以外に変数処理でも使用可能 - 文字列の結合は
format()
を使っても良いし、${}
を使ってもどちらでも可能。読みやすい書き方をすればよいでしょう
- 以下は、key vaultのデプロイテンプレートの例
-
networkAcls
(ネットワークルール)で設定するvirtualNetworkRules
(サービスエンドポイント)のsubnetIdのid
,ignoreMissingVnetServiceEndpoint
を持ったオブジェクのトリストをfor
文で作成 -
ipRules
は外部ファイルから読み出し、ipアドレスをvalue
で持ったオブジェクトリストをfor
文で作成 -
tenantId
の指定もtenant()
を使用してハードコードを避け、テンプレートファイルを再利用しやすくする
-
param location string = resourceGroup().location
param kv_name string
var _ips = json(loadTextContent('./env/ip-list.json'))
var _allow_ip_rules = [for ip in _ips.ip_list['allow-ip-rule']: {
value: ip
}]
var _snets = [
{
vnet_rg_name: 'rg-net-01'
vnet_name: 'vnet-01'
name: 'snet-01'
}
{
vnet_rg_name: 'rg-net-02'
vnet_name: 'vnet-02'
name: 'snet-01'
}
]
var _vnet_se = [for snet in _snets: {
id: format('{0}/subnets/{1}', resourceId(snet.vnet_rg_name, 'Microsoft.Network/virtualNetworks', snet.vnet_name), snet.name)
ignoreMissingVnetServiceEndpoint: false
}]
resource kv 'Microsoft.KeyVault/vaults@2023-02-01' = {
name: kv_name
location: location
properties: {
createMode: 'default'
enableRbacAuthorization: true
enablePurgeProtection: true
softDeleteRetentionInDays: 3
networkAcls: {
defaultAction: 'Deny'
bypass: 'AzureServices'
ipRules: _allow_ip_rules
virtualNetworkRules: _vnet_se
}
sku: {
family: 'A'
name: 'standard'
}
enabledForTemplateDeployment: true
tenantId: tenant().tenantId
}
}
- jsonファイルでのipリスト定義例
{
"ip_list": {
"allow-ip-rule": [
"a.d.u.x",
"b.e.v.y",
"c.f.w.z"
]
}
}
Date関数
- 現在時刻や日時は
utcNow()
を使用して取得する - 日付・時間の計算は
dateTimeAdd()
を使用する
- 以下は、
module
構文を使ってデプロイするテンプレートの例-
module
構文でのデプロイ名に日時を付加する場合に指定するutcNow()
を使用
-
param now string = utcNow('yyyyMMdd-HHmmss')
targetScope = 'subscription'
param st_name string
param st_rg_name string
module diag_activity './modules/diag-activity.bicep' = {
name: 'diag-log-activity-${now}'
scope: subscription()
params: {
st_id: st.id
}
}
module diag_aad './modules/diag-aad.bicep' = {
name: 'diag-log-aad-${now}'
scope: subscription()
params: {
st_id: st.id
}
}
resource st 'Microsoft.Storage/storageAccounts@2021-09-01' existing = {
name: st_name
scope: resourceGroup(st_rg_name)
}
- 以下は、Automation Accountでスケジュール登録を作成するテンプレートの例から抜粋
- 日付を
utcNow()
を使って文字列として取得 -
dateTimeAdd()
を使って開始時刻の文字列を作成
- 日付を
param today string = utcNow('yyyy-MM-dd')
param start_schedule_time string
param stop_schedule_time string
var _start_schedule_time = dateTimeAdd('${today}T${start_schedule_time}', 'P1D')
var _stop_schedule_time = dateTimeAdd('${today}T${stop_schedule_time}', 'P1D')
// correction: 'Asia/Tokyo'
var _start_local_time = dateTimeAdd(_start_schedule_time, '-PT9H')
var _stop_local_time = dateTimeAdd(_stop_schedule_time, '-PT9H')
- 参考: Automation Accountでスケジュール登録するテンプレートの例
以上、ここまで。
Discussion