# Infrastructure as Code

# Terraform

# Terraform Top Commands

- **[Terraform CLI Guide](https://developer.hashicorp.com/terraform/cli/commands)**

**Инициализация рабочего каталога**

```ruby
terraform init
```

**Валидация конфигурационных файлов**

```ruby
terraform validate
```

**Просмотр плана выполнения**

```ruby
terraform plan
```

**Применение изменений** (авто подтверждение)

```ruby
terraform apply -auto-approve
```

**Уничтожение всей управляемой инфраструктуры** (авто подтверждение)

```ruby
terraform destroy -auto-approve
```

**Поиск ssh-ключа по NAME**

```ruby
curl -X GET \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <do_key>' \
  'https://api.digitalocean.com/v2/account/keys' \
  -G \
  --data-urlencode 'page=1' \
  --data-urlencode 'per_page=999' \
  | jq '.ssh_keys[] | select(.name=="xeonmp22_key1") | .id'
```

**Удаление ключа оп ID**

```ruby
curl -X DELETE \
  -H 'Authorization: Bearer <do_key>' \
  "https://api.digitalocean.com/v2/account/keys/<key_id>"
```

**Создание/Удаление заданного ресурса**

```ruby
terraform apply -target=digitalocean_droplet.web2 -auto-approve
terraform apply -target=aws_route53_record.www2 -auto-approve
terraform destroy -target=digitalocean_droplet.web2 -auto-approve
```

# Terraform HandBook

- **[Установка Terraform](https://developer.hashicorp.com/terraform/install#linux)**
- **Terraform Guides:** **[Official](https://developer.hashicorp.com/terraform)** [<span style="color: rgb(22, 145, 121);">**+Yandex.Cloud**</span>](https://yandex.cloud/ru/docs/tutorials/infrastructure-management/terraform-quickstart)

<p class="callout info">**Terraform Providers: [<span style="color: rgb(224, 62, 45);">Official</span>](https://registry.terraform.io/browse/providers)** [**+Github**](https://github.com/shuaibiyy/awesome-tf#providers) **<span style="color: rgb(22, 145, 121);">[+Yandex.Cloud](https://yandex.cloud/ru/docs/terraform/quickstart#configure-provider)</span>**</p>

<table border="1" id="bkmrk-%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5-%D1%80%D0%B5%D0%BF%D0%BE%D0%B7%D0%B8%D1%82%D0%BE%D1%80%D0%B8%D1%8F" style="border-collapse: collapse; width: 56.4286%; height: 320.89px;"><colgroup><col style="width: 50.3171%;"></col><col style="width: 49.6829%;"></col></colgroup><tbody><tr style="height: 35.375px;"><td style="height: 35.375px;">**PROVIDER**

</td><td style="height: 35.375px;">**API**

</td></tr><tr style="height: 35.3906px;"><td style="height: 35.3906px;">[**GitLab** Repo](https://gitlab.com/gitlab-org/terraform-provider-gitlab/-/tree/main/docs?ref_type=heads)

</td><td style="height: 35.3906px;">[GitLab API](https://docs.gitlab.com/api/packages/terraform-modules/)</td></tr><tr style="height: 35.3906px;"><td style="height: 35.3906px;">[<span style="color: rgb(185, 106, 217);">**Yandex Cloud**</span>](https://wiki-docs.ru/books/cloud-providers/page/yc-provider-handbook "YC Provider Handbook")

</td><td style="height: 35.3906px;">[Yandex API](https://yandex.cloud/ru-kz/docs/api-design-guide/concepts/standard-methods)

</td></tr><tr style="height: 41.3906px;"><td style="height: 41.3906px;">[**Digital Ocean**\_droplet](https://docs.digitalocean.com/reference/terraform/reference/resources/droplet/)</td><td style="height: 41.3906px;">[Digital Ocean\_API](https://developers.digitalocean.com/documentation/v2/#list-all-droplets)

</td></tr><tr style="height: 57.7812px;"><td style="height: 57.7812px;">[**Vscale**\_compute instance](https://docs.selectel.ru/terraform/examples/cloud-networks/create-servers/create-server-with-public-subnet/#create-server)[<span style="color: rgb(22, 145, 121);">**+Official**</span>](https://developer.hashicorp.com/vagrant)

</td><td style="height: 57.7812px;">[Vscale\_API](https://developers.vscale.io/documentation/api/v1/#api-Servers-GetScalet)</td></tr><tr style="height: 35.3906px;"><td style="height: 35.3906px;">[<span style="color: rgb(224, 62, 45);">**Hetzner Cloud** server</span>](https://www.terraform.io/docs/providers/hcloud/r/server.html)</td><td style="height: 35.3906px;"><span style="color: rgb(224, 62, 45);">[Hetzner Cloud\_API](https://docs.hetzner.com/cloud/api/getting-started/using-api/)</span></td></tr><tr style="height: 80.1719px;"><td style="height: 80.1719px;">[**AWS**\_instance](https://developer.hashicorp.com/terraform/tutorials/aws-get-started/aws-create#configuration-blocks)

[AWS\_Route53\_record](https://github.com/hashicorp/terraform-provider-aws/blob/main/website/docs/r/route53_record.html.markdown)

[AWS\_Route53\_zone](https://github.com/hashicorp/terraform-provider-aws/blob/main/website/docs/d/route53_zone.html.markdown#data-source-aws_route53_zone)

</td><td style="height: 80.1719px;">[HTTP API + API Gatewa](https://developer.hashicorp.com/terraform/tutorials/aws/lambda-api-gateway#create-an-http-api-with-api-gateway)  
</td></tr></tbody></table>

<p class="callout info">**Источник [developer.hashicorp.com](https://developer.hashicorp.com)**</p>

- [Environment variables](https://developer.hashicorp.com/terraform/cli/config/environment-variables)
- [Variables](https://developer.hashicorp.com/terraform/language/values/variables)
- [<span class="YPkS7KbdpWfGdYKd3QB9" data-src-align="0:7">External</span> <span class="YPkS7KbdpWfGdYKd3QB9" data-src-align="8:9">provider</span>](https://support.hashicorp.com/hc/en-us/articles/4547786359571-Reading-and-using-environment-variables-in-Terraform-runs)
- [Functions](https://developer.hashicorp.com/terraform/language/functions)
- [Count](https://developer.hashicorp.com/terraform/language/meta-arguments/count#usage)
- [Output Values](https://developer.hashicorp.com/terraform/language/values/outputs#define-outputs)
- [Interpolation Syntax](https://developer.hashicorp.com/terraform/language/v1.13.x/expressions/strings#directives)
- [Provisioner remote-exec](https://developer.hashicorp.com/terraform/language/provisioners#run-provisioners-without-a-resource)
- [Provisioner local-exec](https://developer.hashicorp.com/terraform/language/provisioners#run-commands-on-the-local-machine)

<p class="callout info">**Другие источники**</p>

- [Google Load Balancers](https://docs.cloud.google.com/load-balancing/docs/https/ext-http-lb-tf-module-examples)
- <span style="color: rgb(185, 106, 217);">[Import JSON Code from API+jq](https://wiki-docs.ru/books/infrastructure-as-code/page/import-json-code-from-apijq "Import JSON Code from API+jq")</span>
- [Утилита curl](https://curl.se/docs/httpscripting.html)
- [Утилита jq](https://stedolan.github.io/jq/manual/)

# Import JSON Code from API+jq

##### <span style="color: rgb(53, 152, 219);">Создаём скрипт запроса ключа</span>

<p class="callout success">В обратных кавычках Curl запрос с отфильтрованным fingerprint-ом ключа</p>

```ruby
sudo tee ~/key_convert << 'EOF'
#!/bin/bash
echo "{
\"fingerprint\": `curl -X GET \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <key>' \
  'https://api.digitalocean.com/v2/account/keys?page=1&per_page=999' \
  | jq '.ssh_keys[] | select(.name=="REBRAIN.SSH.PUB.KEY") | .fingerprint'`
}"
EOF
```

##### <span style="color: rgb(53, 152, 219);">Доставляем ключ в конфигурацию terraform</span>

<p class="callout success">Функция <span style="color: rgb(35, 111, 161);">**[lookup](https://developer.hashicorp.com/terraform/language/functions/lookup)**</span> извлекает значение указанного ключа из набора</p>

```ruby
data "external" "key_conv" {
  program = ["bash", "${path.root}/key_convert"]
}

resource "digitalocean_droplet" "ubuntu01" {
  ***
  ssh_keys = [
    "${lookup(data.external.key_conv.result, "fingerprint", "what?")}"
  ]
}
```

##### <span style="color: rgb(53, 152, 219);">Пример jq-запросов вывода ключей</span>

**Выгрузка значения <span style="color: rgb(53, 152, 219);">fingerprint </span>конкретного ключа по его <span style="color: rgb(53, 152, 219);">name</span>:**

```ruby
curl -X GET \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <key>' \
  'https://api.digitalocean.com/v2/account/keys?page=1&per_page=999' \
  | jq '.ssh_keys[] | select(.name=="REBRAIN.SSH.PUB.KEY") | .fingerprint'
```

**Выгрузка значений <span style="color: rgb(53, 152, 219);">name </span>всех ключей:**

```ruby
curl -X GET \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <key>' \
  'https://api.digitalocean.com/v2/account/keys?page=1&per_page=999' \
  | jq '.ssh_keys[] | .name'
```

# Vagrant

# Vagrant HandBook

##### <span style="color: rgb(53, 152, 219);">Установка Vagrnat </span>

- **[Установка Vagrant](https://developer.hashicorp.com/vagrant/install#linux)**
- [**Plugins**](https://github.com/hashicorp/vagrant/wiki/Available-Vagrant-Plugins)
- [**Boxes**](https://developer.hashicorp.com/vagrant/docs/boxes#official-boxes)
- [**Vagrantfile**](https://github.com/devopsgroup-io/vagrant-digitalocean#install)
- [External **Script**](https://www.vagrantup.com/docs/provisioning/shell#external-script)
- [Vagrant **Host Script**](https://github.com/phinze/vagrant-host-shell#vagrant-host-shell-plugin)
- [Ansible **Provisioner**](https://www.vagrantup.com/docs/provisioning/ansible.html#simplest-configuration)

##### <span style="color: rgb(53, 152, 219);">Digital Ocean Droplet Example</span>

**Предварительная настройка Plugins/BOX**

```ruby
vagrant plugin install vagrant-host-shell
vagrant plugin install vagrant-digitalocean
vagrant box add digital_ocean https://github.com/devopsgroup-io/vagrant-digitalocean/raw/master/box/digital_ocean.box
```

**Vagrantfile**

```ruby
Vagrant.configure('2') do |config|
  config.vm.define "droplet1" do |config|
      config.vm.provider :digital_ocean do |provider, override|
        override.ssh.private_key_path = '~/.ssh/id_rsa'
        override.vm.box = 'digital_ocean'
        override.vm.box_url = "https://github.com/devopsgroup-io/vagrant-digitalocean/raw/master/box/digital_ocean.box"
        override.nfs.functional = false
        override.vm.allowed_synced_folder_types = :rsync
        provider.token = 'YOUR TOKEN'
        provider.image = 'ubuntu-18-04-x64'
        provider.region = 'nyc1'
        provider.size = 's-1vcpu-1gb'
        provider.backups_enabled = false
        provider.private_networking = false
        provider.ipv6 = false
        provider.monitoring = false
      end
  end
```

##### <span style="color: rgb(53, 152, 219);">Vagrant Top Commands</span>

**Режимы работы Vagrant:**

```ruby
vagrant up
vagrant destroy
vagrant ssh
vagrant status
```

**Удаление кэша старых машин:**

```ruby
vagrant global-status --prune
```

**Запуска/rebuild машин с LOGированием:**

```ruby
VAGRANT_LOG=info vagrant up
VAGRANT_LOG=info vagrant rebuild
```