If I need to connect to something like RDS (using ...
# general
b
If I need to connect to something like RDS (using the Postgres provider) via an SSH tunnel, two questions: 1. Is there a way to set up the SSH tunnel in the core Pulumi program, as opposed to needing to do it outside (e.g. via a wrapper script or automation API)? Basically, just using
pulumi up
should ideally work. 2. If the SSH tunnel provisions a dynamic local port (e.g. to handle several concurrent tunnels being on the machine), is this going to mess up the provider as the port changes every time?
m
The most recent iteration of this idea comes via the beta Command package: https://www.pulumi.com/registry/packages/command/api-docs/remote/command/ https://github.com/pulumi/pulumi-command
b
@millions-furniture-75402 I was thinking about that too, but wasn’t sure if this is suitable (i.e. will the
local.Command
be run every time the
pulumi up
is executed) or not
m
FWIW, the automation API can be used inline in a Pulumi plan and work with only
pulumi up
b
The
Command
docs are not super clear on this, in the sense that the
Command
resource is a resource in the overall graph as far as I understand, so assuming no updates are needed (i.e. nothing has changed in it or its dependencies that cause it to need to be updated), it won’t be re-executed again. An example would be if I used
Command
to set up the tunnel, and ran
pulumi up
, and then rebooted my machine, and ran
pulumi up
again (let’s say changed some
postgresql.Role
object, so it needs to be updated), will the tunnel get recreated (since it doesn’t exist locally anymore? Is my understanding wrong?
Copy code
FWIW, the automation API can be used inline in a Pulumi plan and work with only pulumi up
I’m not sure I followed this one 🙂
m
Lets say your
index.ts
looks like:
Copy code
const executePlan = async (): Promise<void> => {
...
}

executePlan();
Then all your logic inside of that plan will execute using
pulumi up
including the tunnel that you want to setup.
b
I’m still not sure I follow (I’m also using Go, so maybe it’s just not possible there). My stack creates the VPC/subnets and then the RDS, and then I want to create a role in that RDS (or database or some other resource) using the
postgresql
provider, all in the same stack. So I don’t know ahead of time the RDS information in order to set up the tunnel, or my bastion host that I’ll use for the tunnel, etc. Does that make sense? It feels like in order to do this, I’d need to split it up into two stacks in order to be able to create the tunnel prior to running the main Pulumi program. But I could be thinking about it wrong
m
So I don’t know ahead of time the RDS information in order to set up the tunnel, or my bastion host that I’ll use for the tunnel, etc.
For this part, you just can apply your outputs, but then you're in the trap of putting resource declarations inside your applies
b
Yes, which I believe is generally disallowed/discouraged, yes?
m
I tried mocking up what I think it looks like based on the automation example
Not tested at all.
b
So this may be just my lack of familiarity of how the Automation API works in TypeScript, but isn’t non-deterministic when the actual calls to create the DB will be called (i.e. it will be done at a future point), and by the time it runs,
stopSshTunnel
might already be called? Conceptually, the way I think about it, it has to be:
Copy code
startTunnel();
... run Pulumi plan ...
stopTunnel();
m
The above isn't using the automation API, just synchronously calling the startSshTunnel helper function inside of the apply (bad-ish practice).
I took the helper functions from the automation API example though: https://github.com/pulumi/automation-api-examples/blob/main/nodejs/ssh-tunnel/pulumi.ts
I do agree with you, that this should be a first class supported case with Pulumi.
b
Yes, though isn’t the actual call to Postgres to run
CREATE DATABASE …
going to be done asynchronously, and as such, the
stopTunnel()
call on line 58 might be called prior to that asynchronous activity happening?
m
Which is what I think the Pulumi Command package is attempting to do, but still in its infancy.
I'm not sure, I stole the finally from the automation example 🙂
b
Yeah, in the automation API case it makes sense because the start/stop of the tunnel happens outside the actual running of the plan.
m
You could drop the postgres provider and do RAW SQL on a bastion? replacing the copyfile example with copying a SQL file, and executing the remote command: https://github.com/pulumi/pulumi-command#remote-provisioning-of-an-ec2-instance
b
Command
is promising, but I can’t tell if it’s suitable for this particular case, as I think it’s treated as a resource rather than as a procedural command 🙂
That would be very painful as it would lose all the diffing features of the
postgresql
provider (i.e. does this DB exist, does it need to be modified, etc).
m
You'd also lose the diff with the apply hack. Consider it an opportunity to use something like flyway db or liquibase, maybe? Then your Command copies the migration files and runs the migration tool, and handles cases like "does this db exist?"
217 Views