首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Terraform create_before_destroy输出数据

Terraform create_before_destroy输出数据
EN

Stack Overflow用户
提问于 2019-08-05 10:35:12
回答 3查看 1K关注 0票数 0

是否有一种方法可以在同一应用程序中引用即将到来的资源的信息?例如,如果我想知道我要在资源中替换什么资源。

代码语言:javascript
运行
复制
resource "digitalocean_droplet" "droplet" {
  name      = "example"
  region    = "nyc3"
  image     = "docker-18-04"
  size      = "s-1vcpu-2gb"
  ssh_keys  = [...]

  provisioner "remote-exec" {
     inline = [
         "echo replacing ${digitalocean_droplet.droplet[0:old].ipv4_address} with ${self.ipv4_address}"
     ]
  }

  lifecycle {
      create_before_destroy = true
  }
}

我略去了液滴代码,但我认为这应该足够了。如果我没有很好地解释这个问题,请告诉我。

或者,如果在同样的应用中这是不可能的,我将如何去做,否则呢?

EN

回答 3

Stack Overflow用户

发布于 2019-08-05 12:31:36

我没有和DigitalOcean合作过,也没有一个操场可以使用。但是,我尝试了以下使用AWS EC2的方法,并取得了预期的结果。

也许有更好的方法来做到这一点(欢迎评论和贡献!)但是您可以使用数据源对象来获取现有液滴的IP地址。然后,作为terraform应用的一部分,您可以引用该数据对象来获取旧的IP地址。

代码语言:javascript
运行
复制
data "aws_instance" "web" {
  filter {
    name   = "tag:Name"
    values = ["HelloWorld"]
  }
}

resource "aws_instance" "web" {
  ami           = "ami-0d8e27447ec2c8410"
  instance_type = "t2.micro"

  subnet_id = "subnet-1bb60f60"
  private_ip = "172.31.15.31"

  tags = {
    Name = "HelloWorld"
  }

  lifecycle {
      create_before_destroy = true
  }

  provisioner "local-exec" {
      command =  "echo old IP is ${data.aws_instance.web.private_ip}, new one is ${self.private_ip}"
  }

}

然后,我将IP地址更新为.32,输出如下

代码语言:javascript
运行
复制
aws_instance.web: Still creating... [30s elapsed]
aws_instance.web: Provisioning with 'local-exec'...
aws_instance.web (local-exec): Executing: ["/bin/sh" "-c" "echo old IP is 172.31.15.31, new one is 172.31.15.32"]
aws_instance.web (local-exec): old IP is 172.31.15.31, new one is 172.31.15.32
aws_instance.web: Creation complete after 32s [id=i-0cf1ac2618be9d202]
aws_instance.web: Destroying... [id=i-0bcad4b6988f60976]
aws_instance.web: Still destroying... [id=i-0bcad4b6988f60976, 10s elapsed]
aws_instance.web: Destruction complete after 20s

这应该对你的液滴起同样的作用。下面是我为您编写代码的尝试,但可能需要在一些地方进行更正。

代码语言:javascript
运行
复制
data "digitalocean_droplet" "droplet" {
  name = "example"
}

resource "digitalocean_droplet" "droplet" {
  name      = "example"
  region    = "nyc3"
  image     = "docker-18-04"
  size      = "s-1vcpu-2gb"
  ssh_keys  = [...]

  provisioner "remote-exec" {
     inline = [
         "echo replacing ${data.digitalocean_droplet.droplet.ipv4_address} with ${self.ipv4_address}"
     ]
  }

  lifecycle {
      create_before_destroy = true
  }
}
票数 1
EN

Stack Overflow用户

发布于 2019-08-05 12:32:17

您可以使用数据属性获得它,ipv4_address:

https://www.terraform.io/docs/providers/do/d/droplet.html

代码语言:javascript
运行
复制
"${data. digitalocean_droplet.name.ipv4_address}"
票数 0
EN

Stack Overflow用户

发布于 2019-08-05 17:33:42

Terraform保证访问旧实例值的唯一地方是破坏时提供程序,但它们不能访问新的实例值,因此在一个地方访问两个实例都需要跟踪其他地方的信息。

这么说,你可以得到类似你试图这样做的东西:

代码语言:javascript
运行
复制
resource "digitalocean_droplet" "droplet" {
  name      = "example"
  region    = "nyc3"
  image     = "docker-18-04"
  size      = "s-1vcpu-2gb"
  ssh_keys  = [...]

  provisioner "remote-exec" {
     inline = [
         "echo creating droplet with with ${self.ipv4_address}"
     ]
  }

  provisioner "remote-exec" {
     when = destroy
     inline = [
         "echo destroying droplet with with ${self.ipv4_address}"
     ]
  }

  lifecycle {
      create_before_destroy = true
  }
}

原则上,您可以让破坏时间提供程序将IP地址写入本地磁盘的某个位置,然后创建时间提供程序读取它,从而使后者能够访问这两种磁盘。这绝不是一种干净的解决办法,但应该有效。

由于Terraform的一些实现细节,目前可能可以通过使用数据源或其他技术间接地观察旧值,但这不是Terraform的保证,因此在Terraform的未来版本中可能会发生更改。

Terraform假设给定的配置可以管理或读取对象,因此在相同的配置中这样做会导致未定义的行为。如果这样做,您将需要小心地显式地告诉Terraform对象之间的所有依赖项,这样它们就不会在将来可能出现的Terraform版本中被重新排序,该版本可能会以不同的方式实现图遍历。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57356830

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档