web-dev-qa-db-fra.com

Existe-t-il un opérateur ET / OU conditionnel dans la terraforme?

Existe-t-il un moyen d'utiliser quelque chose comme ça dans Terraform?

count = "$ {var.I_am_true}" && "$ {var.I_am_false}"

16
user2062360

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.

18
Yevgeniy Brikman

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
33
NicoKowe

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.

8
ydaetskcoR

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.

2
deniszh