Existe-t-il un moyen d'utiliser quelque chose comme ça dans Terraform?
count = "$ {var.I_am_true}" && "$ {var.I_am_false}"
La réponse de deniszh est assez proche, mais j'ai pensé clarifier un peu et nettoyer la syntaxe.
Dans Terraform, un booléen true
est converti en un 1
Et un booléen false
est converti en un 0
. Donc, si vous avez deux variables booléennes, var.foo
Et var.bar
, Vous pouvez représenter AND
en utilisant une multiplication simple:
count = "${var.foo * var.bar}"
Dans le code ci-dessus, count
sera 1 uniquement si var.foo
ET var.bar
Sont tous les deux true
, car 1 * 1 est 1. Dans tous les autres cas ( 1 * 0, 0 * 1, 0 * 0), vous obtenez 0.
Pour représenter OR, vous pouvez profiter de la fonction signum (x) , qui renvoie 1 si le x
que vous passez est un nombre positif, 0 si x
est 0 et -1 si x
est un nombre négatif. En tenant compte de cela, voici OU:
count = "${signum(var.foo + var.bar)}"
Dans le code ci-dessus, count
sera 1 si soit var.foo
OR var.bar
Est true
et 0 seulement si les deux sont false
(signum(1 + 1) = 1
, signum(1 + 0) = 1
, signum(0 + 1) = 1
, signum(0 + 0) = 0
).
Notez que pour utiliser les techniques ci-dessus, vous devez prendre soin de définir les variables sur un booléen et NON sur une chaîne. Tu veux ça:
variable "foo" {
# Proper boolean usage
default = true
}
Pas ça:
variable "foo" {
# THIS WILL NOT WORK!
default = "true"
}
Pour plus d'informations sur la façon de faire une variété de conditions Terraform, consultez Terraform trucs et astuces: boucles, instructions if et gotchas et Terraform : En cours d'exécution.
Ceci est plus approprié dans la version actuelle (0.12.X)
Les opérateurs pris en charge sont:
Égalité: == et! =
Comparaison numérique:>, <,> =, <=
Logique booléenne: &&, ||, unaire!
https://www.terraform.io/docs/configuration/interpolation.html#conditionals
condition_one et condition two:
count = var.condition_one && var.condition_two ? 1 : 0
condition_one et NOT condition_two:
count = var.condition_one && !var.condition_two ? 1 : 0
condition_one OR condition_two:
count = var.condition_one || var.condition_two ? 1 : 0
Terraform 0.8 ajout du support de première classe pour logique conditionnelle plutôt que les solutions de contournement précédentes.
Cela utilise la syntaxe ternaire classique, vous pouvez maintenant faire quelque chose comme ceci:
variable "env" { default = "development" }
resource "aws_instance" "production_server" {
count = "${var.env == "production" ? 1 : 0}"
...
}
Maintenant, cela ne fera que créer le production_server
Instance EC2 lorsque env
est défini sur "production"
.
Vous pouvez également l'utiliser dans d'autres endroits, comme la définition d'une variable/d'un paramètre comme celui-ci:
variable "env" { default = "development" }
variable "production_variable" { default = "foo" }
variable "development_variable" { default = "bar" }
output "example" {
value = "${var.env == "production" ? var.production_variable : var.development_variable}"
}
Une chose à savoir est que Terraform évalue réellement les deux côtés avant de choisir la valeur utilisée dans la déclaration ternaire plutôt que d'évaluer paresseusement juste le côté du ternaire que la logique déclenchera.
Cela signifie que vous ne pouvez pas faire quelque chose comme cet exemple récent de moi essayant de contourner un problème avec le aws_route53_zone
source de données :
variable "vpc" {}
variable "domain" {}
variable "private_zone" { default = "true" }
data "aws_vpc" "vpc" {
filter {
name = "tag-key"
values = [ "Name" ]
}
filter {
name = "tag-value"
values = [ "${var.vpc}" ]
}
}
data "aws_route53_zone" "private_zone" {
count = "${var.private_zone == "true" ? 1 : 0}"
name = "${var.domain}"
vpc_id = "${data.aws_vpc.vpc.id}"
private_zone = "true"
}
data "aws_route53_zone" "public_zone" {
count = "${var.private_zone == "true" ? 0 : 1}"
name = "${var.domain}"
private_zone = "false"
}
output "zone_id" {
value = "${var.private_zone == "true" ? data.aws_route53_zone.private_zone.zone_id : data.aws_route53_zone.public_zone.zone_id}"
}
Dans l'exemple ci-dessus, cela échouera sur le plan car data.aws_route53_zone.private_zone.zone_id
ou data.aws_route53_zone.public_zone.zone_id
n'est pas défini selon que public_zone
est défini sur true ou false.
Aucun type binaire n'est défini dans Terraform. Mais vous pouvez essayer d'utiliser mathématiques simples
Par exemple.
Ou équivalent
count = signum(${var.I_am_true} + ${var.I_am_false})
ET équivalent
count = ${var.I_am_true} * ${var.I_am_false}
Les deux fonctionneront si I_am_true == 1 et I_am_false == 0.
Mais je n'ai pas essayé les deux.