Ресурсы в terraform можно как создавать, редактировать, так и удалять. При удалении ресурса, terraform провайдер производит необходимые действия на платформе, после чего очищает эти ресурсы из своего .tfstate - файла, в котором хранится состояние инфраструктуры. В данном разделе рассмотрены различные способы удаления ресурсов, проблемы, которые могут возникнуть, их причины, а так же способы их решить. ## Команда destroy Для удаления ресурса, в terraform имеется команда ```bash terraform destroy ``` По умолчанию, эта команда производит удаление всей инфраструктуры, описанной и сохраненной в .tfstate-файле. ### Влияние конфигурационного параметра permanently В некоторых ресурсах terraform провайдера имеется параметр permanently, который регулирует удаление ресурса: - Если флаг имеет значение - `true`, то ресурс будет мгновенно удален с платформы и восстановить его будет невозможно. - Если флаг имеет значение - `false` (используется по умолчанию), то ресурс будет помещен в корзину, с возможностью дальнейшего восстановления. Ресурс будет удален автоматически из корзины через 7 дней (зависит от настроек платформы). #### Возможные проблемы Так как terraform, при удалении ресурса, производит удаление .tfstate-файла, то при использовании фдага permanently = false, ресурс невозможно будет восстановить из конфигурационного файла инфраструктуры - при использовании `terraform apply` - будет создана новая инфраструктура. Поэтому, старую инфраструктуру необходимо импортировать, чтобы сформировать .tfstate - файл, а потом применить `terraform apply` - тогда ресурс будет восстановлен из корзины (_фича находится в разработке - доступно в ресурсе disks_, в провайдере версии 3.2.0+) ## Команда destroy с флагом target Как и было сказано выше, команда `terraform destroy` производит удаление всей инфраструктуры. Для того, чтобы произвести удаление определенных ресурсов, используется флаг `-target`. Флаг, в качестве параметра, принимает название ресурса для удаления, вида ``` <тип-ресурса>.<имя-ресурса> ``` либо ``` <модуль>.<имя-ресурса> ``` для ресурсов, содержащихся в модулях. Таким образом, общая команда выглядит так: ``` terraform destroy -target <тип-ресурса>.<имя-ресурса> ``` или ``` terraform destroy -target <модуль>.<имя-ресурса> ``` В примерах не используется модуль, поэтому, далее, в качестве примера, будет взята команда `terraform destroy -target <тип-ресурса>.<имя-ресурса>` ### Способы передачи параметра 1. `terraform destroy -target <тип-ресурса>.<имя-ресурса>` 2. `terraform destroy -target="<тип-ресурса>.<имя-ресурса>"` ### Пример использования target В качестве примера возьмем пример конфигурации из [прошлой статьи](https://repository.basistech.ru/BASIS/terraform-provider-decort/src/branch/main/wiki/4.6.3/05.04-Массовое-создание-ресурсов.-Мета-аргументы.md): ```terraform resource "decort_disk" "disk1" { account_id = 777 disk_name = "disk-1" size_max = 10 gid = 212 } resource "decort_disk" "disk2" { account_id = 777 disk_name = "disk-2" size_max = 10 gid = 212 } ``` - Чтобы удалить всю инфраструктуру, необходимо просто выполнить в терминале команду ```bash terraform destroy ``` - Чтобы удалить "disk2", можно воспользоваться командой: ``` terraform destroy -target decort_disk.disk2 ``` - Чтобы удалить "disk1", можно воспользоваться другим способом удаления: ``` terraform destroy -target="decort_disk.disk1" ``` Таким образом, определенный ресурс можно удалить с помощью флага target. ### Использование флага target при работе с ресурсами, созданными с помощью мета аргументов. При создании ресурсов с помощью мета аргументов, первые получают дополнительные символы в именах ресурсов, что может привести к некоторым проблемам при работе с такими ресурсами. #### Работа с for_each При работе с for_each, ресурс получается имя вида: `<тип-ресурса>.<общее-имя-ресурса>["<название>"]` Таким образом, обращение к такому ресурсу будет выглядит следующим образом: ``` terraform destroy -target='<тип-ресурса>.<общее-имя-ресурса>[\"<название>\"]' ``` или ``` terraform destroy -target '<тип-ресурса>.<общее-имя-ресурса>[\"<название>\"]' ``` Пример: Для примера рассмотрим создание ресурса с помощью мета аргумента for_each из предыдущей статьи: ```terraform locals { disk_names = [ "disk-1", "disk-2", ] } resource "decort_disk" "disks" { for_each = toset(local.disk_names) account_id = 777 disk_name = each.key size_max = 10 gid = 212 } ``` В результате применения команды `terrafrom apply`, будут созданы ресурсы с именами: - decort_disk.disks["disk-1"] - decort_disk.disks["disk-2"] Чтобы удалить определенный ресурс, можно воспользоваться одной из команд: ``` #для удаления disk-1 terraform destroy -target='decort_disk.disks[\"disk-1\"]' ``` ``` #для удаления disk-2 terraform destroy -target 'decort_disk.disks[\"disk-2\"]' ``` Либо: ``` #для удаления всей инфраструктуры terraform destroy ``` Такая запись с экранирование кавычек обуславливается работой терминальной оболочки, через которую будет производится вызов данной команды, а так же то, что terraform в качестве параметра флага ожидает строку. Так же, есть еще одно правило - в terraform в квадратных скобках указывается либо строка в двойных кавычках (в качестве имени ключа для объекта, используется для for_each), либо число - в качестве индекса для массива (используется для count) #### Работа с count При работе с count, ресурс получается имя вида: `<тип-ресурса>.<общее-имя-ресурса>[<индекс>]` Таким образом, обращение к такому ресурсу будет выглядит следующим образом: ``` terraform destroy -target="<тип-ресурса>.<общее-имя-ресурса>[<индекс>]" ``` или ``` terraform destroy -target <тип-ресурса>.<общее-имя-ресурса>[<индекс>] ``` Пример: Для примера рассмотрим создание ресурса с помощью мета аргумента for_each из предыдущей статьи: ```terraform locals { disk_names = [ "disk-1", "disk-2", ] } resource "decort_disk" "disks" { count = length(local.disk_names) account_id = 777 disk_name = local.disk_names[count.index] size_max = 10 gid = 212 } ``` В результате применения команды `terrafrom apply`, будут созданы ресурсы с именами: - decort_disk.disks[0] - decort_disk.disks[1] Чтобы удалить определенный ресурс, можно воспользоваться одной из команд: ``` #для удаления disk-1 terraform destroy -target="decort_disk.disks[0]" ``` ``` #для удаления disk-2 terraform destroy -target decort_disk.disks[1] ``` Либо: ``` #для удаления всей инфраструктуры terraform destroy ``` ### Удаление ресурса из состояния В ходе работы, могут возникать случаи, когда состояние (state, стейт) terraform имеет ресурсы, которые были удалены с платформы. В таком случае, можно, при выполнении команд `terraform plan/apply` получить ошибку: ```bash Planning failed. Terraform encountered an error while generating this plan. ╷ │ Error: The resource cannot be updated because it has been destroyed │ │ with decort_kvmvm.instances["pgsmonsietc03"], │ on main.tf line 33, in resource "decort_kvmvm" "instances": │ 33: resource "decort_kvmvm" "instances" { ``` Либо, в ходе неверного выполнения может возникнуть подобная ошибка: ```bash ╷ │ Error: Failed to read the given file as a state or plan file │ │ State read error: Error loading statefile: open data.decort_cb_vins.vins: no such file or directory │ │ Plan read error: open data.decort_cb_vins.vins: no such file or directory ``` Для того, чтобы этого избежать, необходимо удалить отсутствующий ресурс из стейта, выполнив команду `terraform state rm .` Например, `terraform state rm decort_kvmvm.vm1` В случае, если ресурс был создан путен работы генераторов count/for_each, работают те же правила, что и для команды `terraform destroy`. ## Возможные проблемы Были обнаружены проблемы при использовании _oh my zsh_, которые заключались в том, что не считывались данные, переданные, при экранировании строки. Рекомендация: использовать _bash_. ## Заключение Таким образом, terraform позволяет выполнять удаление: - всей инфраструктуры, хранящейся в файле .tfstate с помощью `terraform destroy` - части инфраструктуры, используя флаг target. ОБщий вид команды такой: `terraform destroy -target <тип-ресурса>.<имя-ресурса>`