#amazon-web-services #terraform
#amazon-web-services #terraform
Вопрос:
Произойдет ли сбой terraform, если пользователь в данных не существует? Мне нужно указать пользователя в непроизводственной среде с помощью блока данных:
data "aws_iam_user" "labUser" {
user_name = "gitlab_user"
}
Затем я использую этого пользователя для предоставления пользовательских разрешений:
resource "aws_iam_role" "ApiAccessRole_abc" {
name = "${var.stack}-ApiAccessRole_abc"
tags = "${var.tags}"
assume_role_policy = <<EOF
{
"Version": "2019-11-29",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"AWS": [
"${aws_iam_user.labUser.arn}"
]
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
В рабочей среде этот пользователь не существует. Будет ли сбой terraform, если этот пользователь не существует? Каков был бы хороший подход к использованию одного и того же terraform в обеих средах?
Комментарии:
1. Что вы собираетесь делать, если пользователь не существует? И да, сбой Terraform произойдет, если источник данных вернет нулевые результаты.
2. Что-то мешает вам напрямую управлять пользователем IAM?
3. @Mattschuchardтерраформ удалит ручные настройки после запуска
Ответ №1:
В Terraform data
блок, подобный тому, который вы показали здесь, является одновременно механизмом извлечения данных, а также утверждением автора (вас) о том, что ожидается существование определенного внешнего объекта, чтобы эта конфигурация могла быть применима.
В вашем случае ответ заключается в том, чтобы гарантировать, что утверждение о существовании объекта появляется только в ситуациях, когда оно должно существовать. Ответ «в целом» на этот вопрос заключается в том, чтобы просмотреть руководство по составлению модуля и рассмотреть, следует ли эту часть вашего модуля разбить на отдельный модуль, если он не всегда является частью модуля, в который он встроен, но я также покажу меньшее решение, которое использует условные выражения для полученияповедение, которое вы хотели, без какого-либо рефакторинга:
variable "lab_user" {
type = string
default = null
}
data "aws_iam_user" "lab_user" {
count = length(var.lab_user[*])
user_name = var.lab_user
}
resource "aws_iam_role" "api_access_role_abc" {
count = length(data.aws_iam_user.lab_user)
name = "${var.stack}-ApiAccessRole_abc"
tags = var.tags
assume_role_policy = jsonencode({
Version = "2019-11-29"
Statement = [
{
Sid = ""
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
AWS = [data.aws_iam_user.lab_user[count.index].arn]
}
},
]
})
}
В приведенном выше есть несколько разных вещей, на которые я хочу обратить внимание:
- Я сделал имя пользователя лаборатории необязательной переменной, а не жестко заданным значением. Вы можете изменить поведение в разных средах, присвоив этой
lab_user
переменной другое значение или вообще не задавая его для сред, которым не нужен «лабораторный пользователь». - В
data "aws_iam_user"
I установите значение countlength(var.lab_user[*])
равным .[*]
Здесь оператор просит Terraform преобразовать строковую переменную с возможным значением nullvar.lab_user
в список либо из нуля, либо из одного элемента, а затем, используя длину этого списка, решить, сколькоaws_iam_user
запросов нужно выполнить. Еслиvar.lab_user
этоnull
, то длина будет равна нулю, и поэтому запросы выполняться не будут. - Наконец, я установил
count
дляaws_iam_role
ресурса соответствие длине результатаaws_iam_user
данных, так что в любой ситуации, когда ожидается один пользователь, также будет создана одна роль.
Если вы поразмыслите над руководством по составлению модуля и придете к выводу, что этот лабораторный пользователь должен быть отдельной проблемой в отдельном модуле, тогда вы сможете удалить эту условную сложность из самого модуля «gitlab user», и вместо этого вызывающий модуль либо вызовет этот модуль, либо нет, в зависимости от того, является ли такой пользовательнеобходимо для этой среды. Эффект будет тем же, но решение будет приниматься в другой части конфигурации, и, таким образом, будет достигнуто другое разделение задач. Какое разделение задач наиболее подходит для вашей системы, в конечном счете, является компромиссом, который вам нужно будет сделать самостоятельно, исходя из ваших знаний о системе и того, как вы ожидаете, что она может развиваться в будущем.
Ответ №2:
Как было предложено в комментариях, произойдет сбой.
Один из подходов, который я могу предложить, — указать имя пользователя в качестве переменной, которую вы передаете извне из файлов dev.tfvars и prod.tfvars, и запустить terraform с:
terraform apply --var-file example.tfvars
Затем в вашем ресурсе данных у вас может быть count или for_each, чтобы проверить, был ли заполнен var или нет (если var не был передан, вы можете пропустить интерполяцию данных)
count = var.enable_gitlab_user ? 1 : 0
Подход AWS direct заключается в переключении с пользователя IAM в основном на условие на основе тегов или даже на цепочку ролей. Некоторые идеи можно найти в этом сообщении в блоге AWS. Есть примеры для обоих случаев.