Неожиданная семантика реализации

Обновление: это не относится к Terraform 0.12+, в котором среди других преимуществ добавлены реальные логические и числовые типы. Обновите версию до 0.12 (или более позднюю), если вы можете избежать идиосинкразии до версии 0.12.

Terraform имеет логические значения ... но не имеет истинного логического типа. Вместо этого Terraform преобразует буквальные значения true и false в "1" и "0" соответственно, поэтому в действительности логические значения Terraform имеют строковый тип. Кроме того, при интерпретации строк как логических значений, например, в условном выражении, дополнительные значения "true" и "false" принимаются (без учета регистра).

Еще одна тонкость связана с поведением оператора == (равенство) Terraform, который работает со строковыми значениями. Например, все следующие значения эквивалентны:

true == true   # "1" == "1"
false == false # "0" == "0"
"1" == true    # "1" == "1"
"0" == false   # "0" == "0"

Однако эти пары значений, возможно, не интуитивно, не эквивалентны:

true != "true"   # "1" != "true"
false != "false" # "0" != "false"

Чтобы усложнить ситуацию, результат вычисления логических операторов не согласуется с вышеупомянутым преобразованием логических литералов. Например:

"x" == "x" # -> "true"
"x" == "y" # -> "false"
!!true     # -> "true"

Помня, что true преобразуется в "1", последний пример необычным образом оценивается на следующих этапах:

!!true
!!"1"
!"false"
"true"

Это пример того, насколько неудобным может быть код Terraform для работы, и это означает, что мы должны быть осторожны, в частности, при использовании логических значений и выражений.

Моя рекомендация:

  1. Никогда не используйте операторы == или != для сравнения логических значений, поскольку они выполняют сравнение строк и не могут обрабатывать несколько возможных синонимов истинного и ложного. Например, вместо:
    var.x == true ? var.y : var.z
    просто используйте:
    var.x ? var.y : var.z
  2. Нормализуйте логические выходные данные ваших модулей с помощью двойного отрицания:
    output "out" { value = "${!!var.in}" }
    Это приведет к тому, что выходные значения модуля будут последовательно "true" или "false"