タイトルの通り、Terraform使ってAzure DevOpsをプロビジョニングする方法です。
前提
組織登録
まずは、Terraform実行する前に以下の画面から組織の登録を行う必要があります。
このような画面になるはずです。
URLは https://dev.azure.com/your-org
となりますが、これを後で利用します。
Personal Access Tokenの取得
画面右上からPersonal Access Tokenを取得しておきます。
Terraform定義準備
TerraformのAzure DevOps ProviderはMSがGithubに公開しているので、これを利用します。
このようなディレクトリ構成を作ります。
. ├── main.tf ├── terraform.d │ └── plugins │ └── linux_amd64 │ └── terraform-provider-azuredevops_v0.1.0
Terraformの定義の準備
Githubのサンプルを参考に以下のように作ってみます。
variable "org_name" {} variable "personal_access_token" {} provider "azuredevops" { version = ">= 0.0.1" org_service_url = "https://dev.azure.com/${var.org_name}/" personal_access_token = var.personal_access_token } resource "azuredevops_azure_git_repository" "repository" { project_id = azuredevops_project.project.id name = "My Awesome Repo" initialization { init_type = "Clean" } } resource "azuredevops_azure_git_repository" "repository" { project_id = azuredevops_project.project.id name = "My Awesome Repo" initialization { init_type = "Clean" } } resource "azuredevops_build_definition" "build_definition" { project_id = azuredevops_project.project.id name = "My Awesome Build Pipeline" path = "\\" repository { repo_type = "TfsGit" repo_name = azuredevops_azure_git_repository.repository.name branch_name = azuredevops_azure_git_repository.repository.default_branch yml_path = "azure-pipelines.yml" } }
Azure DevOps Providerのインストール
上記の定義で使われている azuredevops
のProviderをインストールします。
以下のURLでMSがGithubで公開しています。
まずはGolangでビルドする必要があるので、Docker使ってビルドします。
ディレクトリ作成して、Golangのイメージを起動します。
$ mkdir -p terraform.d/plugins/linux_amd64 $ docker run --rm -it -v $(pwd)/terraform.d/plugins/linux_amd64:/plugin golang:buster /bin/bash root@70557c0bfefc:/go#
以下のようにビルドします。
VER=v0.1.0 mkdir -p $GOPATH/src/github.com/terraform-providers/ # ↓ -b を抜かせば最新版でビルドできます git clone https://github.com/microsoft/terraform-provider-azuredevops.git -b ${VER} --depth 1 cd ./terraform-provider-azuredevops/ go build -o /plugin/terraform-provider-azuredevops_${VER} exit
戻ったらProviderが認識されているか確認します。
$ terraform init Initializing the backend... Initializing provider plugins... Terraform has been successfully initialized! You may now begin working with Terraform. Try running "terraform plan" to see any changes that are required for your infrastructure. All Terraform commands should now work. If you ever set or change modules or backend configuration for Terraform, rerun this command to reinitialize your working directory. If you forget, other commands will detect it and remind you to do so if necessary.
Terraformの実行
まずは terraform plan
を実行してみます。パラメータを聞かれるので、最初の手順で作成した組織名と、取得したPersonal Access Tokenを入力します。
$ terraform plan var.org_name Enter a value: your-org var.personal_access_token Enter a value: xxxxxxxxxxx
成功したら同様の方法で apply していきます。
$ terraform apply
Azure DevOpsのサービスが展開できました。
スキーマの確認
スキーマの出力をすると設定できる内容を確認することができます。
$ terraform providers schema -json | jq { "format_version": "0.1", "provider_schemas": { "azuredevops": { "provider": { "version": 0, "block": { "attributes": { "org_service_url": { "type": "string", "description": "The url of the Azure DevOps instance which should be used.", "required": true }, "personal_access_token": { "type": "string", "description": "The personal access token which should be used.", "required": true, "sensitive": true } } } }, "resource_schemas": { "azuredevops_agent_pool": { "version": 0, "block": { "attributes": { "auto_provision": { "type": "bool", "optional": true }, "id": { "type": "string", "optional": true, "computed": true }, "name": { "type": "string", "required": true }, "pool_type": { "type": "string", "optional": true } } } }, "azuredevops_azure_git_repository": { "version": 0, "block": { "attributes": { "default_branch": { "type": "string", "computed": true }, "id": { "type": "string", "optional": true, "computed": true }, "is_fork": { "type": "bool", "computed": true }, "name": { "type": "string", "required": true }, "project_id": { "type": "string", "required": true }, "remote_url": { "type": "string", "computed": true }, "size": { "type": "number", "computed": true }, "ssh_url": { "type": "string", "computed": true }, "url": { "type": "string", "computed": true }, "web_url": { "type": "string", "computed": true } }, "block_types": { "initialization": { "nesting_mode": "set", "block": { "attributes": { "init_type": { "type": "string", "required": true }, "source_type": { "type": "string", "optional": true }, "source_url": { "type": "string", "optional": true } } }, "min_items": 1, "max_items": 1 } } } }, "azuredevops_build_definition": { "version": 0, "block": { "attributes": { "agent_pool_name": { "type": "string", "optional": true }, "id": { "type": "string", "optional": true, "computed": true }, "name": { "type": "string", "optional": true }, "path": { "type": "string", "optional": true }, "project_id": { "type": "string", "required": true }, "revision": { "type": "number", "computed": true }, "variable_groups": { "type": [ "set", "number" ], "optional": true } }, "block_types": { "repository": { "nesting_mode": "set", "block": { "attributes": { "branch_name": { "type": "string", "optional": true }, "repo_name": { "type": "string", "required": true }, "repo_type": { "type": "string", "required": true }, "service_connection_id": { "type": "string", "optional": true }, "yml_path": { "type": "string", "required": true } } }, "min_items": 1, "max_items": 1 } } } }, "azuredevops_group": { "version": 0, "block": { "attributes": { "description": { "type": "string", "optional": true }, "descriptor": { "type": "string", "computed": true }, "display_name": { "type": "string", "optional": true, "computed": true }, "domain": { "type": "string", "computed": true }, "id": { "type": "string", "optional": true, "computed": true }, "mail": { "type": "string", "optional": true, "computed": true }, "members": { "type": [ "set", "string" ], "optional": true, "computed": true }, "origin": { "type": "string", "computed": true }, "origin_id": { "type": "string", "optional": true, "computed": true }, "principal_name": { "type": "string", "computed": true }, "scope": { "type": "string", "optional": true }, "subject_kind": { "type": "string", "computed": true }, "url": { "type": "string", "computed": true } } } }, "azuredevops_group_membership": { "version": 0, "block": { "attributes": { "group": { "type": "string", "required": true }, "id": { "type": "string", "optional": true, "computed": true }, "members": { "type": [ "set", "string" ], "required": true }, "mode": { "type": "string", "optional": true } } } }, "azuredevops_project": { "version": 0, "block": { "attributes": { "description": { "type": "string", "optional": true }, "id": { "type": "string", "optional": true, "computed": true }, "process_template_id": { "type": "string", "computed": true }, "project_name": { "type": "string", "required": true }, "version_control": { "type": "string", "optional": true }, "visibility": { "type": "string", "optional": true }, "work_item_template": { "type": "string", "optional": true } } } }, "azuredevops_serviceendpoint_dockerhub": { "version": 0, "block": { "attributes": { "description": { "type": "string", "optional": true }, "docker_email": { "type": "string", "description": "The DockerHub email address which should be used.", "required": true }, "docker_password": { "type": "string", "description": "The DockerHub password which should be used.", "required": true, "sensitive": true }, "docker_password_hash": { "type": "string", "description": "A bcrypted hash of the attribute 'docker_password'", "computed": true, "sensitive": true }, "docker_username": { "type": "string", "description": "The DockerHub username which should be used.", "required": true }, "id": { "type": "string", "optional": true, "computed": true }, "project_id": { "type": "string", "required": true }, "service_endpoint_name": { "type": "string", "required": true } } } }, "azuredevops_serviceendpoint_github": { "version": 0, "block": { "attributes": { "description": { "type": "string", "optional": true }, "id": { "type": "string", "optional": true, "computed": true }, "project_id": { "type": "string", "required": true }, "service_endpoint_name": { "type": "string", "required": true } }, "block_types": { "auth_oath": { "nesting_mode": "set", "block": { "attributes": { "oauth_configuration_id": { "type": "string", "required": true } } }, "max_items": 1 }, "auth_personal": { "nesting_mode": "set", "block": { "attributes": { "personal_access_token": { "type": "string", "description": "The GitHub personal access token which should be used.", "required": true, "sensitive": true }, "personal_access_token_hash": { "type": "string", "description": "A bcrypted hash of the attribute 'personal_access_token'", "computed": true, "sensitive": true } } }, "max_items": 1 } } } }, "azuredevops_user_entitlement": { "version": 0, "block": { "attributes": { "account_license_type": { "type": "string", "optional": true }, "descriptor": { "type": "string", "computed": true }, "id": { "type": "string", "optional": true, "computed": true }, "origin": { "type": "string", "optional": true }, "origin_id": { "type": "string", "optional": true }, "principal_name": { "type": "string", "optional": true } } } }, "azuredevops_variable_group": { "version": 0, "block": { "attributes": { "allow_access": { "type": "bool", "optional": true }, "description": { "type": "string", "optional": true }, "id": { "type": "string", "optional": true, "computed": true }, "name": { "type": "string", "required": true }, "project_id": { "type": "string", "required": true } }, "block_types": { "variable": { "nesting_mode": "set", "block": { "attributes": { "is_secret": { "type": "bool", "optional": true }, "name": { "type": "string", "required": true }, "value": { "type": "string", "optional": true } } }, "min_items": 1 } } } } }, "data_source_schemas": { "azuredevops_group": { "version": 0, "block": { "attributes": { "descriptor": { "type": "string", "computed": true }, "id": { "type": "string", "optional": true, "computed": true }, "name": { "type": "string", "required": true }, "project_id": { "type": "string", "required": true } } } }, "azuredevops_projects": { "version": 0, "block": { "attributes": { "id": { "type": "string", "optional": true, "computed": true }, "project_name": { "type": "string", "optional": true }, "projects": { "type": [ "set", [ "object", { "name": "string", "project_id": "string", "project_url": "string", "state": "string" } ] ], "computed": true }, "state": { "type": "string", "optional": true } } } } } } } }