Azure 中級Bicep

今更ながらBicepの勉強第二弾。ただのMSLearnのまとめです。
※Gitの説明は省略。

https://learn.microsoft.com/ja-jp/training/paths/intermediate-bicep/

第一弾はこちら

https://qiita.com/smr1/items/47e509f62b131cbccb64

第三弾DevOps piplelineからはこちら。

https://qiita.com/smr1/items/fac36c9b34fadb546021

# 子リソース
リソースIDの構造
```
/subscriptions/f0750bbe-ea75-4ae5-b24d-a92ca601da2c/resourceGroups/ToyDevelopment/providers/Microsoft.Storage/storageAccounts/secrettoys
```
リソースIDは以下のような階層構造になる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/6374963d-0470-8f27-200c-715eb9f7bf8b.png)

親リソースに対して子リソースがある。子リソースは単独では存在できない。
VNetのSubnet、StorageAccountのコンテナなど。
## parentプロパティ
基本的にこれが推奨。
```
resource vm 'Microsoft.Compute/virtualMachines@2020-06-01' = {
  name: vmName
  location: location
  properties: {
    // ...
  }
}

// 親のリソース種別を継承できないためすべて記載が必要
resource installCustomScriptExtension 'Microsoft.Compute/virtualMachines/extensions@2020-06-01' = {
  parent: vm
  name: 'InstallCustomScript'
  location: location
  properties: {
    // ...
  }
}
```

## 入れ子
```
resource vm 'Microsoft.Compute/virtualMachines@2020-06-01' = {
  name: vmName
  location: location
  properties: {
    // ...
  }

  // 種類はMicrosoft.Compute/virtualMachines/extensionsだが、前半を親から継承するため省略可能
  // APIバージョンは指定不要
  resource installCustomScriptExtension 'extensions' = {
    name: 'InstallCustomScript'
    location: location
    properties: {
      // ...
    }
  }
}

// 子を参照するには::を利用する
output childResourceId string = vm::installCustomScriptExtension.id
```

## dependsOn＋階層構造のリソース名を採用
forループ内等で親リソースが動的に変わる場合に使う。順番にデプロイしてくれる。
```
resource vm 'Microsoft.Compute/virtualMachines@2020-06-01' = {
  name: vmName
  location: location
  properties: {
    // ...
  }
}

resource installCustomScriptExtension 'Microsoft.Compute/virtualMachines/extensions@2020-06-01' = {
  // nameが親/子になっている
  name: '${vmName}/InstallCustomScript'
  // dependsOnで親を指定
  dependsOn: [
    vm
  ]
  //...
}
```

ただしdependsOnは積極的に利用を推奨するものではない。
> Bicep で dependsOn プロパティを使用して依存関係を明示的に指定することができます。 ただし、ほとんどの場合、Bicep で依存関係を自動的に検出することができます。 あるリソースのシンボリック名を別のリソースのプロパティ内で使用すると、Bicep でその関係が検出されます。 可能な限り、Bicep 自体にこれらを管理させることをお勧めします。

なお、この場合、Deployは1つしかできないが、概要から複数のリソースが作られているのが見える。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/66afae51-1710-2be2-8a62-899447a3ada5.png)


# 拡張機能
子とは違って、もっと汎用的に他のリソースにアタッチされるもの。
ロールの割り当て、リソースロック、診断設定等。

resource idはproviderが2重になる。
```
/subscriptions/f0750bbe-ea75-4ae5-b24d-a92ca601da2c/resourceGroups/ToyDevelopment/providers/Microsoft.DocumentDB/databaseAccounts/toyrnd/providers/Microsoft.Authorization/locks/DontDelete
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/3f1555d5-7184-4d72-56b9-6034a7c7004e.png)


## scopeで対象を設定
```
resource cosmosDBAccount 'Microsoft.DocumentDB/databaseAccounts@2020-04-01' = {
  name: cosmosDBAccountName
  location: location
  properties: {
    // ...
  }
}

resource lockResource 'Microsoft.Authorization/locks@2016-09-01' = {
  // scopeで対象のリソースを特定する
  scope: cosmosDBAccount
  name: 'DontDelete'
  properties: {
    level: 'CanNotDelete'
    notes: 'Prevents deletion of the toy data Cosmos DB account.'
  }
}
```

# 既存のリソースの参照
bicepの中から既存のリソースの情報を取得したい。
```
resource vnet 'Microsoft.Network/virtualNetworks@2020-11-01' existing = {
  name: 'toy-design-vnet'

  resource managementSubnet 'subnets' existing = {
    name: 'management'
  }
}
// 入れ子になっているので、Subnetの情報は::で取得
output managementSubnetResourceId string = vnet::managementSubnet.id
```

## 既存リソースへ子リソースの追加
SQL ServerにSQL Databaseを追加。
```
resource server 'Microsoft.Sql/servers@2020-11-01-preview' existing = {
  name: serverName
}

resource database 'Microsoft.Sql/servers/databases@2020-11-01-preview' = {
  // 普通にparentで既存リソースを指定してやればよい
  parent: server
  name: databaseName
  location: location
  sku: {
    name: 'Standard'
    tier: 'Standard'
  }
}
```
拡張機能も同じようにできる。

## 既存リソースのプロパティを参照
単純な値の受け渡し。（InsightsのInstrumentationKeyは実は機密データではない。。）
```
resource applicationInsights 'Microsoft.Insights/components@2018-05-01-preview' existing = {
  name: applicationInsightsName
}

resource functionApp 'Microsoft.Web/sites@2020-06-01' = {
  name: functionAppName
  location: location
  kind: 'functionapp'
  properties: {
    siteConfig: {
      appSettings: [
        // ...
        {
          name: 'APPINSIGHTS_INSTRUMENTATIONKEY'
          value: applicationInsights.properties.InstrumentationKey
        }
      ]
    }
  }
}
```

機密データのキーを取得したい場合はこのように受け渡す。（アクセス権が必要。）
シークレットの受け渡しにOutputを利用するのは推奨されない。
```
resource storageAccount 'Microsoft.Storage/storageAccounts@2019-06-01' existing = {
  name: storageAccountName
}

resource functionApp 'Microsoft.Web/sites@2020-06-01' = {
  name: functionAppName
  location: location
  kind: 'functionapp'
  properties: {
    siteConfig: {
      appSettings: [
        // ...
        {
          name: 'StorageAccountKey'
          // listKeysを利用する
          value: storageAccount.listKeys().keys[0].value
        }
      ]
    }
  }
}
```

# 外部リソースグループのリソースを参照
```
resource vnet 'Microsoft.Network/virtualNetworks@2020-11-01' existing = {
  scope: resourceGroup('networking-rg')
  name: 'toy-design-vnet'
}
```

# What If
デプロイ前の事前チェック。
```
az deployment group what-if \
  --resource-group ToyStorage \
  --template-file $templateFile \
  --result-format FullResourcePayloads
```
What Ifを実行する。
- 紫：変更
- 緑：新規リソース
- オレンジ：削除

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/4f8486e8-bc64-4567-e966-9f491fb1e0b3.png)


## Deployモード
### 増分
既定。不足している分を追加するだけ。それ以外は削除せずそのまま残す。段階的な更新に適する。

### 完全
テンプレートで宣言されている状態に強制的にする。それ以外の既存リソースは原則削除。完全な新規作成に適する。スコープはリソースグループのみ。


# ARM Templateからの変換
## 流れ
Portalから手動でリソースをデプロイした場合、以下のステップでbicepに変換する。


```
az bicep decompile --file template.json
```

### 変換
Portalから取得したARM Templateをbicepに逆コンパイル。
注意点として、
- データが含まれない（コントロールプレーンのみ、データプレーンなし）
- ProvisioningState等読み取り専用のプロパティがゴミとして残る
- パラメータがハードコーディングされている
- エクスポートできないもの（拡張機能等）がありえる
　
### 移行
- デプロイ可能なbicepファイルを作成する
    1. 新しい空の Bicep ファイルを作成する
    1. 逆コンパイルされたテンプレートから各リソースをコピーする
    1. 不足しているリソースを特定して再作成する（エクスポート時の警告を確認）
　
- Resource Explorerを使うと、ARMTemplateを確認するのに役立つかもしれない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/9de37bb1-9e12-3260-03b1-a39bb9dd48a3.png)

- お役たちサイト（ARMTemplate Reference、Azure Quick Start Template）を確認する

https://learn.microsoft.com/ja-jp/samples/browse/?expanded=azure&products=azure-openai%2Cazure-resource-manager&languages=bicep
    
https://learn.microsoft.com/ja-jp/samples/browse/?expanded=azure&products=azure-resource-manager

### リファクタリング
https://learn.microsoft.com/ja-jp/training/modules/migrate-azure-resources-bicep/4-refactor-bicep-file

### テスト
- What If操作を実行
- テストデプロイ

### デプロイ  
- 運用環境に対してWhat If
- ロールバック方法を確認
- デプロイ
- スモークテスト