Azure Resource Manager テンプレートスペックに Bicep ファイルを格納してデプロイする

## TL;DR
何か特殊なことをやればできる感じのタイトルに見えますが、特段の設定等は必要なく Azure Resource Manager テンプレートスペックには Bicep ファイルも格納できます。Bicepファイルがそのまま格納されるわけではなく、格納する際にJSONに変換されているようです。


## Azure Resource Manager テンプレートスペック
> テンプレート スペックは、Azure に Azure Resource Manager テンプレート (ARM テンプレート) を格納するためのリソースの種類です。 このリソースの種類を使用すると、ARM テンプレートを組織内の他のユーザーと共有できます。 他の Azure リソースと同じように、Azure ロールベースのアクセス制御 (Azure RBAC) を使用してテンプレート スペックを共有できます。
https://docs.microsoft.com/ja-jp/azure/azure-resource-manager/templates/template-specs

要は ARM テンプレートを後でデプロイしたり、反復デプロイのために保存しておくリソースです。


## Bicep
> Bicep は、宣言型の構文を使用して簡潔な構文、信頼性の高いタイプ セーフ、およびコードの再利用のサポートが提供されます。
https://docs.microsoft.com/ja-jp/azure/azure-resource-manager/bicep/overview

要は`「ARMテンプレート(JSON)は人が読み書きするもんじゃねぇ！」`ってことでプログラミングチックにARMデプロイのための定義を書ける言語です。
ARM テンプレートは Bicep と互換性があり Bicep を ARM テンプレートに変換したりもできます。


## やりたいこと
ARM テンプレートスペックに Bicep で記述したファイルをそのまま格納しデプロイまでしてみます。
**ARM テンプレートスペックというサービスの名前から ARM テンプレートしか格納できないのかなと思われるかもしれませんが ~~Bicep ファイルもそのまま格納できます。~~ Bicepファイルをアップロードする際にJSONに変換されて格納してくれるようです。(後述)**


## やってみる

### 適当なBicepファイルを作る
以下の構文を見ていただければ JSON と比べて Bicep の方が人間にとって書きやすいということがお分かりいただけるかと思います。（入力を補助するための[VS Code拡張機能](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-bicep)もあります）

```main.bicep
@minLength(3)
@maxLength(24)
@description('Provide a name for the storage account. Use only lower case letters and numbers. The name must be unique across Azure.')
param storageName string

resource virtualNetwork 'Microsoft.Network/virtualNetworks@2021-05-01' = {
  name: 'examplevnet'
  location: resourceGroup().location
  properties: {
    addressSpace: {
      addressPrefixes: [
        '10.0.0.0/16'
      ]
    }
    subnets: [
      {
        name: 'Subnet-1'
        properties: {
          addressPrefix: '10.0.0.0/24'
        }
      }
      {
        name: 'Subnet-2'
        properties: {
          addressPrefix: '10.0.1.0/24'
        }
      }
    ]
  }
}

resource exampleStorage 'Microsoft.Storage/storageAccounts@2021-06-01' = {
  name: storageName
  location: 'eastus'
  sku: {
    name: 'Standard_LRS'
  }
  kind: 'StorageV2'
}

```

### テンプレートスペックのデプロイ
PowerShell(azコマンドも用意されてます)でテンプレートスペックを作成します。この時にローカルで作成したBicepファイルを指定します。

```
New-AzTemplateSpec -Name testSpec -Version 1.0a -ResourceGroupName IaCTest -Location westus2 -TemplateFile ./main.bicep
```

作成に成功すると「テンプレートの仕様」という種類でリソースが作成されます。(スペック=仕様ってことですかね)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149212/44351d13-be58-bc1e-9812-5c70d7d2b6c0.png)

ちなみにテンプレートスペックの「概要」→「メインテンプレート」を見るとARMテンプレートがプレビューできます。この時点ですでにJSON化されてメタデータのgeneratorがbicepになっているのが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149212/7a73515f-4e6d-3a97-1347-eb5571bed044.png)
 

PowerShellの応答としては以下のようなレスポンスが返ってきます（Idは後で使います）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149212/7b01009f-b78f-5d6f-83fd-e68844e5a98a.png)

### テンプレートスペックを使用してリソースデプロイ
デプロイはテンプレートスペックを指定して `New-AzResourceGroupDeployment` コマンドを実行します。storageNameパラメータを聞かれるので一意の名前を入力します。

```
New-AzResourceGroupDeployment -TemplateSpecId "{テンプレートスペックのId}/versions/1.0a" -ResourceGroupName IacTest
```

デプロイ成功すると以下のPowerShellの応答が返されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149212/fefd3a08-91b7-39c9-126e-e75b4cb9edd8.png)

### 確認
Azure portalで確認すると正常にリソースができているのが見れます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149212/0011ad2a-69d9-5f76-30b1-14d6b060b7e6.png)