Ви думаєте, що «нормально» пишете Terraform? Або п’ять best-practices, як робити НЕ треба

Усі статті, обговорення, новини про DevOps — в одному місці. Підписуйтеся на DOU | DevOps!

«Ніколи такого не було, і ось знову...» — саме така думка в мене виникає кожного разу, коли я бачу помилки в Terraform плані на зразок «Index out of range».

«Ну... певно, це дуже старий Terraform-код!» — плекаю надію я. Потім йду в репозиторій, знаходжу необхідний ресурс, що містить славнозвісний «count», і бачу поряд з ним напис в IDLE: «This code was created by mr. X 8 months ago». Що? Ви серйозно? 8 місяців тому? count? Я вважаю, що таких людей потрібно автоматично позбавляти лички «senior», якщо вона в них звісно є!

Нормальна така заява від якогось там мідл-сопляка з 3 роками досвіду, погодьтесь.... Не зрозумійте мене неправильно, але якщо ви за 5 років існування «for_each» в Terraform, не зрозуміли його переваги і не навчились його використовувати замість «count» — в мене для вас погані новини (дуже символічно, до речі, що цю статтю я пишу на 5-річний ювілей появи «for_each» в terraform — він з’явився з версії 0.12.6, що датується 31 липня 2019 ). Розкажу вам історію....

В мене є товариш, якому купили права на водіння автомобілем. І він вже близько 10 років їздить на машині. Треба віддати йому належне — водить він добре, питань нема. Починаючи з відчуття габаритів машини та «інтуїтивного» розуміння ситуації на дорозі, і закінчуючи ідеальними навичками паралельного паркування, про нього можна сказати: «він наче був народжений з кермом в руках».... Але!

Їхали ми якось на його машині, і в один прекрасний момент він повертає направо під всесвітньо відомий «знак цеглини», після чого ми «успішно» вискакуємо на односторонній зустрічний рух і вдаривши по гальмам зупиняємось за півметра від ошалівшого водія Gelandewagen. Я кажу йому: «Ти ненормальний? Нащо ти це зробив? Там же ж знак був!» На що отримую відповідь: «Який знак? Мені права купили! Ти думаєш, я знаю, що він означає? Я знаю лише одне правило: красний- стій, зелений- їдь!»

А тепер питання до вас: чи можна вважати його «нормальним» водієм і дозволити мати права? Відповідь: звісно ні!!! Яким би він «крутим» водієм не був, по-хорошому в нього треба забрати права, відправити навчатись, і лише після здачі екзамену дозволити знову сідати за кермо!

Так само потрібно вчиняти і з сіньйорами, які продовжують в 2024 році використовувати «count» в Terraform коді! Адже «Index out of range» так само як і штраф за їзду в полосі громадського транспорту — це найменші із зол, які можуть бути, коли ти не знаєш як користуватись «for_each», або не знаєш правил дорожнього руху.

Тож я хочу поділитися з вами своїми 5-ма «best-practices» як НЕ треба робити в Terraform.

Що не так з «count»

Використання «count» здається дуже зручним на перший погляд: визначив кількість ресурсів, яку хочеш створити, додав кондішн якщо необхідно — вуаля, ресурси створюються при виконанні цього кондішину. Але це лише на перший погляд....

Річ у тім, що кожен з цих ресурсів отримує свій ідентифікаційний номер в списку(починаючи з 0), і зберігається в Terraform стейті як ресурс із цим порядковим номером. Відповідно, якщо ви створювали 10 ресурсів за допомогою «count» півроку назад і вони успішно «живуть» у вас на продакшені, а зараз по якійсь із причин ви вирішили змінити їх кількість (або видалити якийсь конкретний із них), то видаливши цей ресурс «із середини» списку, ви отримуєте 100% ризик видалення і перестворення всіх ресурсів, які знаходяться далі в списку (мають більший порядковий номер), так як їхній ідентифікатор тепер теж змінюється.

І ваше щастя, якщо у вас налаштована CI/CD «Continuous delivery» стратегія — ви це помітите перед ‘terraform apply’.

А що ж на це каже офіційна документація Terraform

— «Using for_each gives the same flexibility without the extra churn.» Що в перекладі на українську звучить як: «Ну так, ми колись трохи налажали з ‘count’, але все виправили за допомогою ‘for_each’. І оскільки ми не хочемо всім ламати існуючі інфраструктури, ми ‘count’ теж будемо підтримувати, але дуже радимо вам використовувати ‘for_each’, адже в нього є весь функціонал як в ‘count’ і навіть більше, але немає таких ризиків отримати неочікуваний результат».

А ось вам приклад як створювати ресурси в залежності від значення змінної за допомогою «for_each» :

А ви досі використовуєте «locals» всередині Terraform темплейтів?

Особисто я проти «locals» нічого не маю — куди ж без них! Але питання в тому, де вони використовуються (в якому місці лежать). Що мається на увазі.

Всі знають, що повторне використання коду — це святе святих правило всієї розробки ПЗ. Девелопери для цього навіть ООП собі придумали наряду з іншими парадигмами програмування. Девопс інженери вирішили не відставати і придумали таку штуку як «module» в Terraform (насправді то скоріш за все придумали теж девелопери, які працювали над Terraform, але то таке).

Ідея полягає в чому: ми описуємо «темплейт» для якихось ресурсів інфраструктури, і замість конкретних значень для атрибутів/пропертів цих ресурсів вказуємо плейсхолдери, які отримають свої фактичні значення вже протягом деплою. Такий «module» ми називаємо «child» модулем, і тепер можемо «викликати» його з багатьох інших «root» модулів, які потребують створення ресурсів, описаних в «child» (той що наш «темплейт»). І як ви всі напевно вже знаєте, ці «child» модулі/темплейти мають приймати в себе якісь значення (назву енву, кількість інстансів, неймінг мікросервісу, назву сабскіпшину і т.д), на основі яких генеруватимуться вже «фактичні» значення для атрибутів ресурсів. Для цієї генерації ми й використовуємо «locals».

А тепер уявімо собі таку ситуацію: ми маємо 5 «root» модулів в різних репозиторіях для деплою різних частин інфраструктури, але всі ці 5 модулів «викликають» один і той же «child» модуль/темплейт для створення одного й того ж набору ресурсів, проте з різними значеннями. І от уявімо, що ми передаємо в «child» модуль/темплейт якісь значення (vars наприклад), і генеруємо на їх основі фактичні значення для атрибутів ресурсів всередині (за допомогою «locals» звісно ж). Потім ресурси деплояться і всі щасливі....

Але проходить деякий час, і в нас виникає така ситуація, коли один з 5 «root» модулів потребує «специфічної» конфігурації/неймінгу в порівнянні з іншими 4-ма. Нам для цього необхідно зайти в репозиторій «child» модулю/темплейту та змінити під цю «специфіку» наші «locals».

Проте тепер інші 4 «root» модулі, передаючи свої значення, можуть мати конфлікти з нашим новим кодом, адже не завжди неймінг та структура об’єктів, що використовується для створення ресурсів одного «root» модуля підходить і співпадає з неймінгом та структурою об’єктів для іншого. І гратися з написанням «locals», які б одночасно підійшли для всіх 5-ти «root» модулів, постійно перевіряючи, що нічого не зламається — можна довго!

А що з цим робити? А все дуже просто: генеруйте всі свої фактичні значення прямо в «root» модулях, і нехай ваш «child» модуль/темплейт лише отримує вже готові значення чи об’єкти, не займаючись їхньою генерацією. Іншими словами — не пхайте «locals» в «child» модуль/темплейт, якщо це не «конче необхідно»!

Розбивай свій Terraform код на частинки за «логічним» принципом

Знову ж таки, повертаючись до девелоперів, які, на відміну від відносно молодого «Девопс племені», взрощують свої «best practices» вже понад 50 років.... Вони придумали для зручності розбивати код на логічні частини по репозиторіям, пакетам, папкам, файлам....

А з Terraform що? Все точнісінько так само! Якщо ви вже помітили, то в скриншоті з прикладом про «for_each» вище все розбито по окремим файлам: «locals» знаходяться в locals.tf, провайдери в providers.tf, змінні в variables.tf, і далі по списку. Думаю, бенефіти від такого «групування» очевидні, тому не бачу необхідності затримуватись на цій темі. Хочу лише поділитись прикладом як робити не треба:

Погодьтесь, виходить якась «каша», в якій розібратись, де, і що лежить, доволі складно (особливо, якщо ми в одному файлі описуємо безліч ресурсів разом з компонентами для них).

Будьте незалежні від «depends_on»

А що ж не так з «depends_on» ? Найкраще на це питання відповідає офіційна документація: «You should use depends_on as a last resort because it can cause Terraform to create more conservative plans that replace more resources than necessary. For example, Terraform may treat more values as unknown „(known after apply)“ because it is uncertain what changes will occur on the upstream object.»

Переклад: «Не треба використовувати „depends_on“ в усіх ресурсах, де тільки можна! Terraform і без вас розуміє (в більшості випадків), що, і в якому порядку треба деплоїти.»

Тож просте правило: якщо можна обійтись без «depends_on» — обходимось без «depends_on». Особливо остерігайтесь його використання з модулями !!! Перше, що вас повинно насторожувати, це думка про те, що в «module» зазвичай лежить більше одного ресурсу («depends_on» на більшу кількість ресурсів — більше потенційних проблем, більше «known after apply» в вашому Terraform плані).

А друге.... Розкажу вам що буває, коли використовуєш «depends_on» разом з Terraform «data». Уявімо такий кейс: ви описуєте відразу декілька Terraform модулів. Скажімо, це модуль для створення Kubernetes кластеру, і модуль для створення нетворку до нього.

Все, що нам відомо перед деплоєм цих ресурсів — ім’я Vnet та subnet в яких будуть працювати наші K8’s ресурси. Цей subnet ми будемо «тягнути» за допомогою Terraform «data» і передавати його значення в Kubernetes кластер. Наш код виглядає приблизно ось так:

А знаєте, що відбудеться коли ми задеплоїмо ці ресурси, а через деякий час зробимо будь-які зміни в модулі «aks_network» ? Terraform буде перестворювати K8’s кластер !!! Відбуватиметься це тому, що виконання Terraform «data» буде завжди чекати допоки не відбудеться «terraform apply» на ресурси модулю «aks_network» (через «depends_on»).

І як наслідок ми матимемо в Terraform плані для K8’s кластеру:

“vnet_subnet_id = "/subscriptions/..." -> (known after apply) # forces replacement”

А що можна зробити щоб цього не сталось? Ну навіть не знаю..., як мінімум можна перенести ресурс «data.azurerm_subnet» з «child» модуля «aks_cluster» в окремий data.tf файл всередину «root» модуля (пам’ятаєте попередні 2 «best-practices»? забув сказати, що з «data» теж так працює) — передавайте в «child» модуль ВЖЕ ГОТОВІ ЗНАЧЕННЯ, і буде вам щастя!

Або, як радить сам Hashicorp support в своєму «Best Practice: depends_on Meta-Argument» — використовуйте «прямі» посилання на «output» модулів замість використання «depends_on» на ці модулі.

«local-exec» працює всупереч концепції Terraform

А чого це він «працює всупереч концепції», запитаєте ви? Давайте згадаємо історію еволюції підходів деплою інфраструктури....

«Спочатку у нас все мале, ну там раковини, спірохети разні.... Потом знов все велике, динозаври. бронтозаври ....» Ой, вибачте, не той текст.... Так от: було значить напочатках все «встановиРукамиОпс» — були адміністратори, були дискети з Віндовсом на них, були компакт диски з Лінуксом.... І те все встановлювалось на залізяки в серверних руцями, і руцями так само і конфігурилось.

Потім придумали писати автоматизацію, скріптіки на Python, bash, віртуальні машинки в клаудах.... І вигадали для того всього назву — DevOps методологія. Те все потроху розвивалось, йшло в масси....

Після чого якийсь розумник взяв та й придумав декларативний підхід (або він сам собі утворився, хто ж його знає). З’явилась така штука як K8’s, яка сама себе менеджить і хілить (подавай тільки .yaml файли), і з’явився наш славнозвісний Terraform, про який ми сьогодні балакаємо — теж яскравий представник декларативного підходу.

І все наче зрозуміло: описав бажане за дійсне — сиди, чекай, поки за тебе все зробиться! Але ж ні... давайте в декларативному Terraform використовувати імперативні команди! Ну, якщо пацани з Hashicorp контори створили ті Provisioners — значить так треба, значить є специфічна необхідність, яку вони покривають. Але наша з вами задача яка? Правильно! Бути в курсі, що Provisioners — це «the last resort. There are better alternatives for most situations».

І в принципі можна було б пошерити лінку на поради щодо використання, та альтернативи Provisioners, та й на тому все. Але я так зробити не можу, тому поділюсь з вами кейсом, який звісно ж трапився не зі мною (мені товариш розказував), і трапився він (як же ж по-іншому) не на роботі, а вдома на якомусь пет-проєкті.

Якось існував собі «local-exec» з дуже сенсітів значенням всередині. Щось на кшталт цього:

«І ніс він свою службу справно... та от, зістарився....» — взяв та й впав якось цей «local-exec». А коли Terraform падає — він справно виводить помилки в аутпут, навіть з «quiet» аргументом («Note that the output of the command will still be printed in any case»)

До речі, може й Дію так само взломали в 2022 ?)

P.S: наперед прошу вибачення у всіх сеньйорів, в яких можуть забрати личку сеньйора через мене. Сподіваюсь, мій досвід буде для когось корисним, і, можливо, вбереже від фатальних помилок.

Якщо ви з чимось не згодні чи, навпаки, згодні, або просто хочете поділитись своїми думками — велком в коментарі або в мій LinkedIn, я завжди відкритий до спілкування.

👍ПодобаєтьсяСподобалось12
До обраногоВ обраному5
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Дуже добра стаття, дякую.
Доречі більшість з описаних питань дуже часто зустрічаються на технічних інтерв’ю

У HCL є свої переваги і недоліки. Це класна абстракція, але вона дуже обмежує. Мені бракує:
— можливості написати своїх функцій;
— можливості реалізувати складні вкладеності без модулів;
— Автоматизацій для імпортів тощо.
— Експорт наявних ресурсу в код.

На жаль, найближчим часом цього не буде, а альтернативи небагато.

Ну Pulumi из того что сразу на ум приходит. Но там вполне можно столкнуться с проблемой «У вас тут всё на Х, это хня, нужно обязательно на У перенести»

Привіт, дякую за статтю, вона має кілька дійсно корисних порад (як от не використовувати count через особливості генерування індексів)

Проте мені не дуже сподобався стиль викладення матеріалу який виглядає як знецінювання будь-якого бачення, що не співпадає з Вашим, тому прошу якщо можливо на майбутнє не писати настільки зверхньо, це надає статті дурного тону на мою думку, як і говорити про те що «якщо ви використали якусь конструкцію то Ваш тайтл 100% не заслужений».

Щодо змісту то Ви розглянули лише випадки коли використання тої чи іншої конструкції є поганим. Ви казали про використання одного модуля у 10 інших, але це і не є дуже загально прийнятною практикою, самі розробники терраформу пропонують flat структуру як кращу альтернативу. Про locals погоджусь з іншими коментаторами що вказали на супер просте рішення з опціональним параметром для оверрайду якщо в ньому зʼявилась потреба.

Вибачте за стиль, я просто намагався писати «цікаво» (щоб зацепити). В мене не було мети «знецінення» іншого бачення, яке не співпадає з моїм! Я лише хотів сказати: «я роблю ось так, для досягнення таких цілей...»
Просто мінусом текстового контенту є те, що читач не завжди може оцінити «емоційне» забарвлення цього тексту. Тому багато жартівливих моментів (як я собі напочатку задумав) можна трактувати як агресивне подання матеріалу. Я обов’язково врахую це в наступний раз.

Дякую, що пошарили досвід (і стиль прикольний)! Заберу своїм слухачам на курс — обговоримо.

Автор, перестань позорити Інтеліас своїми статтями=)

Але проходить деякий час, і в нас виникає така ситуація, коли один з 5 «root» модулів потребує «специфічної» конфігурації/неймінгу в порівнянні з іншими 4-ма. Нам для цього необхідно зайти в репозиторій «child» модулю/темплейту та змінити під цю «специфіку» наші «locals».

Пример не корректный. Точнее, пример корректный, но решение не имеет никакого отношения к locals. Основная причина этой проблемы — не использование версионирования модулей.

Так, ви праві — версіонування модулів вирішує цю проблему.
Але мій приклад більше про збільшення «flexibility» модулю, щоб він міг приймати і створювати більшу «різноманітність» ресурсів.

P.S: і я ж не кажу, що немає інших альтернатив. Я кажу: «я роблю ось так для досягнення того-то».

Потім йду в репозиторій, знаходжу необхідний ресурс, що містить славнозвісний «count», і бачу поряд з ним напис в IDLE: «This code was created by mr. X 8 months ago». Що? Ви серйозно? 8 місяців тому? count? Я вважаю, що таких людей потрібно автоматично позбавляти лички «senior», якщо вона в них звісно є!

Я вважаю що людей котрі роблять заяви в подібному стилі, не зʼясувавши причин чому було щось зроблено так або інакше, не можна пускати працювати з іншими людьми. І в проєкти у котрих цикл життя трохи довше за стартап на 1 рік краще також не пускати.

Пробач далі цього абзацу уже не зміг себе змусити читати, припускаю що ти там щось розумне писав. Але користуючись нагодою, прошу уточнити де в офіційній документації(developer.hashicorp.com/...​uage/meta-arguments/count) згадано що використання count deprecated або це bad practice?

update: ок я прочитав трохи далі. дуже не згодний з твоїм прикладом про locals, imo не бачу проблеми загорнути в середину модуля трохи логіки щоб розрулити вхідні дані різного типу, це називається інкапсуляція, складність додається один раз і підтримується в одному місці. А от «генерувати всі вхідні данні 4-5+++ разів у кожному root» буде копіпаста, котру потім треба буде підтримувати у багатьох місцях, і в якийсь момент це вистрілить боляче в ногу.

imo не бачу проблеми загорнути в середину модуля трохи логіки щоб розрулити вхідні дані різного типу

Та там даже проблемы нет. Если какому-то проекту прям нужно что-то специфическое, и модули не версионированные — всегда можно докинуть тернарный оператор и использовать кастомное значение если оно передаётся в модуль.

1. В «ternary operator» є лише «true» або «false», так? Тобто лише два варіанти ? А якщо треба більше?
2. Що на рахунок «readability» такого підходу? Це полегшує читання коду?
3. Що робити якщо ти в «child» модулі маєш прийняти мапу об’єктів, де у кожного об’єкту по 15-20 пропертів (наприклад, ти хочеш створювати таку махіну як FrontDoor з усіма origins, routing rules, WAF і т.д (реальний кейс з мого досвіду), і мати модуль, який би передбачав можливість деплою FrontDoor за допомогою платформи (Platform engineering), яка ВЖЕ деплоїть більше 10 кастомерів, що потребують кожен «свого унікального» FrontDoor, зі своїми унікальними вимогами і значеннями до нього? Теж використовувати «ternary operator»? Як це реалізувати щоб не потрапити в дурку?

1. В «ternary operator» є лише «true» або «false», так? Тобто лише два варіанти ? А якщо треба більше?

Больше чего? В locals ты задаешь дефолтное значение, которое определяется на основании других переменных, либо явно даёшь возможность передать кастомное значение.
Рандомный прмиер:

variable "custom_resource_prefix" {
  description = "Some fancy custom prefix"
  default     = ""
}

locals {
  prefix = var.custom_resource_prefix != "" ? var.custom_resource_prefix : "${var.name}-${var.env}"
}
2. Що на рахунок «readability» такого підходу? Це полегшує читання коду?

Это сугубо субъективно. Что лучше, опциональная переменная или копи-паста одного и того же кода в 5 мест? А если мы этот модуль используем в сотне мест?

3.
Як це реалізувати щоб не потрапити в дурку?
lookup(var.froontdoor, "some_var_changed_by_1%_of_child_modules_bool", local.env == "live" ? true : false)
lookup(var.froontdoor, "var_2", null)

1. В вашому прикладі з locals, ви задаєте «дефолтное значение, которое определяется на основании других переменных», або даєте можливість передати кастомне значення.... Тобто ви пеередаєте кастомне значення в «child» модуль, яке ВЖЕ згенерували в «root» модулі? По факту робите так, як я раджу в статті (але не завжди)?
Тоді чому б не викинути ці locals з «child» взагалі, і не перенести їх в «root» модулі, якщо ви все рівно в «специфічних» випадках виносите їх генерування в «root» ?
Я все ж впевнений, що це спростить розуміння логіки коду.

2. Згоден, це сугубо суб’єктивно. Для мене мій варіант здається «зрозумілішим» (наприклад, для людини, яка онбордиться на проект)

3. Ви знову ж таки передаєте ВЖЕ готове значення для «some_var_changed_by_1%_of_child_modules_bool», яке було згенероване в «root» модулі (або ж ставите дефолтне значення, якщо такого немає). Ви не генеруєте значення для пропертів ресурсів в locals «child» модулю, ви лише вказуєте дефолтне значення (що ніяк не суперечить моєму підходу). Але це тяжче читати....
Ну правда, це ви опишете близько 15 lookup-пів ? І як це виглядатиме?
Це звісно суб’єктивно, знову ж таки....

P.S: знов повторюсь, що я не претендую на звяння мессії Тераформу. Я лише описую як роблю я, і для чого я так роблю.

1. «прошу уточнити де в офіційній документації згадано що використання count deprecated або це bad practice?» — якщо ви читали мою статтю трохи далі, то я якраз цитую офіційну документацію, де про це згадано. До речі, в посиланні, що ви скинули, теж є про це в останньому абзаці ))

2. З приводу «не зʼясувавши причин чому було щось зроблено так або інакше» — наведіть хоч один приклад/аргумент для використання «count» замість «for_each». Іншими словами: є хоч один кейс, коли ти не зможеш реалізувати щось з «for_each», але зможеш реалізувати з «count»? Які його «переваги» в порівнянні з «for_each» ?

3. Інкапсуляція є механізмом об’єднання данних, методів та атрибутів в об’єкти, з подальшою можливістю(не завжди) скриття цих методів чи об’єктів від зовнішнього світу. І основною причиною для інкапсуляції є: «Essentially, encapsulation prevents external code from being concerned with the internal workings of an object». Тобто, щоб на данні об’єкта не можна було ніяк впливати окрім як із середини самого об’єкту.
По-перше, Тераформ не є ООП мовою програмування, в нього немає классів, методів і т.д.... Якщо ви хочете заперечити, що для інкапсуляції не є обов’язковим ООП — так, це правда, але Терраформ НЕ є не тільки ООП мовою програмування, але й взагалі НЕ є мовою програмування. Тож, цікаво, яке значення інкапсуляції ви вкладаєте в «інкапсуляцію в Тераформ»? Є якесь визначення з офіційних джерел про «інкапсуляцію в Тераформ» ?
По-друге, навіть якщо ми припустимо, що існує якась «інкапсуляція в Тераформ», і вона полягає з ваших слів в «загорнути в середину модуля трохи логіки щоб розрулити вхідні дані різного типу», то яким чином мій підхід заважає вам приймати модулем об’єкти/мапи об’єктів, або значення «locals» різних типів і «розрулювати» їх як ви вважаєте за потрібне?
Моя концепція, насамперед, полягає у формуванні неймінгу чи значень пропертів в «root» модулях, і передачі цих фактичних значень в «child» (це як передавати аргументи в функцію чи в створення об’єкту класу, якщо ви любите аналогії з програмуванням). А що ви вже далі будете з тими значеннями робити — ваша справа. Ви можете одночасно приймати об’єкти з 10 параметрами всередині, і об’єкти з 5 параметрами, але при цьому і ті, і ті будуть «прийняті» вашим «child» модулем, якщо ви опишете, що вони їх можуть приймати (default «" значення ще ніхто не відміняв). Чули щось про «duck typing» та «interfaces» в програмуванні ? Я намагаюсь досягнути саме такого ефекту!
Це робить ваші модулі більш «flexible» в плані різноманітності ресурсів, які вони зможуть створювати.

Зовсім забув, ще є така штука як «(optional)» в описаннях variables — це щодо того, як можна одночасно «приймати» одним модулем різні об’єкти з різною кількістю пропертів в них.

Якщо ви хочете заперечити, що для інкапсуляції не є обов’язковим ООП — так, це правда, але Терраформ НЕ є не тільки ООП мовою програмування, але й взагалі НЕ є мовою програмування. Тож, цікаво, яке значення інкапсуляції ви вкладаєте в «інкапсуляцію в Тераформ»? Є якесь визначення з офіційних джерел про «інкапсуляцію в Тераформ» ?
По-друге, навіть якщо ми припустимо, що існує якась «інкапсуляція в Тераформ», і вона полягає з ваших слів в «загорнути в середину модуля трохи логіки щоб розрулити вхідні дані різного типу», то яким чином мій підхід заважає вам приймати модулем об’єкти/мапи об’єктів, або значення «locals» різних типів і «розрулювати» їх як ви вважаєте за потрібне?

Рука-ліцо.jpg
Понабирають піценосців в інженери)

Не піценосів, а фізруків, попрошу ))

До речі, може й Дію так само взломали в 2022 ?)

думаю це не проблема local-exec, а проблема того як його використовують.

command — (Required) This is the command to execute. It can be provided as a relative path to the current working directory or as an absolute path. The command is is evaluated in a shell and can use environment variables for variable substitution. We do not recommend using Terraform variables for variable substitution because doing so can lead to shell injection vulnerabilities. Instead, you should pass Terraform variables to a command through the environment parameter and use environment variable substitution instead.

Так, я якраз про проблеми його використання і говорив!)

Підписатись на коментарі