proud-painting-63563
09/27/2025, 4:13 PMmodern-zebra-45309
09/28/2025, 11:10 AMproud-painting-63563
09/28/2025, 11:23 PMmodern-zebra-45309
09/29/2025, 6:48 AMproud-painting-63563
09/29/2025, 10:06 AMmodern-zebra-45309
09/29/2025, 10:29 AMServer(image="firstImage") resource and deploy a stack, and then you change your program to Server(image="secondImage") , and you then run pulumi up (or the equivalent in the Automation API) again, your server provider will determine that image has changed. If a change to image requires a resource replacement (rather than an in-place update), it will then 1) bring up a new server instance with the new image, 2) wait for the new server instance to be ready, 3) shut down the old server instance. If the server never becomes ready, the old one will just stay there (unless you set destroyBeforeReplace to true) and Pulumi will fail with an error. Your Server resource should have an ipAddress output that you can pass as an input to other resources in your program. If the IP address changes, these other resources will then be updated accordingly.
The key idea here is that you update the same stack to a new version of your program. The mechanics of provisioning a server are handled by the provider and/or the APIs the provider calls into. It's their job to determine whether the server is ready.proud-painting-63563
09/29/2025, 10:51 AMmodern-zebra-45309
09/29/2025, 11:00 AMproud-painting-63563
09/29/2025, 1:52 PMterraform {
required_providers {
digitalocean = {
source = "digitalocean/digitalocean"
version = "~> 2.0"
}
tls = {
source = "hashicorp/tls"
version = "4.0.6"
}
}
}
variable "do_token" {}
variable "should_fail" { description = "true or false" }
variable "software_choice" { description = "apache or nginx" }
provider "digitalocean" {
token = var.do_token
}
resource "tls_private_key" "rsa_ssh_key" {
algorithm = "RSA"
rsa_bits = 2048
}
resource "digitalocean_ssh_key" "do_ssh_key" {
name = "my_throw_away_ssh_key_name"
public_key = tls_private_key.rsa_ssh_key.public_key_openssh
}
resource "digitalocean_droplet" "software-droplet" {
name = "nginx-droplet"
region = "lon1"
image = "rockylinux-8-x64"
size = "s-1vcpu-2gb-intel"
user_data = "# ${var.software_choice}"
ssh_keys = [
digitalocean_ssh_key.do_ssh_key.id
]
provisioner "local-exec" {
command = var.should_fail == "true" ? "exit 1" : "exit 0"
}
provisioner "remote-exec" {
connection {
host = self.ipv4_address
private_key = tls_private_key.rsa_ssh_key.private_key_pem
}
inline = [
var.software_choice == "nginx" ? "dnf update -y\ndnf install -y nginx\nsystemctl enable nginx --now" : "dnf update -y\ndnf install -y httpd\nsystemctl enable httpd --now"
]
}
lifecycle { create_before_destroy = true }
}
resource "digitalocean_reserved_ip" "reserved_ip" {
droplet_id = digitalocean_droplet.software-droplet.id
region = digitalocean_droplet.software-droplet.region
}
output "floating_ip_address" {
value = digitalocean_reserved_ip.reserved_ip.ip_address
}
output "droplet_ip_address" {
value = digitalocean_droplet.software-droplet.ipv4_address
}
output "running_software_choice" {
value = var.software_choice
}modern-zebra-45309
09/29/2025, 1:58 PMcreate_before_destroy but should otherwise be equivalent. Also, https://github.com/pulumi/pulumi-digitalocean is directly built on https://github.com/digitalocean/terraform-provider-digitalocean, so I'd be surprised to learn that Pulumi does something fundamentally different here when it comes to creating resources or determining their state. I'll look at your TF example later.proud-painting-63563
09/29/2025, 2:03 PMmodern-zebra-45309
09/29/2025, 2:19 PMconst server = new Server();
const ip_address = server.ip_address.apply(async (ip_address) => {
// do whatever you have to do on the server
return ip_address;
});
const proxy = new Proxy(backend_ip=ip_address);
The ip_adress output will only resolve after the apply returns.