Skip to content

Instantly share code, notes, and snippets.

@t0yv0
Last active October 27, 2022 15:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save t0yv0/addb78402b3e91a910b2021bce7c8e1d to your computer and use it in GitHub Desktop.
Save t0yv0/addb78402b3e91a910b2021bce7c8e1d to your computer and use it in GitHub Desktop.
Pulumi Command CopyFile replacements
*.pyc
venv/
rsa
rsa.pub
import pulumi
import pulumi_aws as aws
import pulumi_command as command
import base64
import keys
profile = 'devsandbox'
region = 'us-east-1'
prefix = 'repro'
size = 'm6i.large'
key_name = keys.key_name
public_key = keys.public_key
private_key = keys.private_key
aws_provider = aws.Provider(f"{prefix}-provider",
region=region,
profile=profile)
# Create a new security group that permits SSH access.
secgrp = aws.ec2.SecurityGroup(f"{prefix}-secgrpallowssh",
description='allow-port-22-ssh-access',
ingress=[
aws.ec2.SecurityGroupIngressArgs(
protocol='tcp',
from_port=22,
to_port=22,
cidr_blocks=['0.0.0.0/0']),
],
egress=[aws.ec2.SecurityGroupEgressArgs(
from_port=0,
to_port=0,
protocol="-1",
cidr_blocks=["0.0.0.0/0"],
ipv6_cidr_blocks=["::/0"],
)],
opts=pulumi.ResourceOptions(provider=aws_provider))
# Get the AMI
ami = aws.ec2.get_ami(
owners=['amazon'],
most_recent=True,
filters=[aws.ec2.GetAmiFilterArgs(
name='name',
values=['amzn2-ami-hvm-*x86_64*'],
)],
opts=pulumi.invoke.InvokeOptions(provider=aws_provider))
# Maybe generate a KeyPair.
if key_name is None:
key = aws.ec2.KeyPair(f"{prefix}-key",
public_key=public_key,
opts=pulumi.ResourceOptions(provider=aws_provider)
)
key_name = key.key_name
# Provision a server as an EC2 instance.
server = aws.ec2.Instance(f"{prefix}-server",
instance_type=size,
ami=ami.id,
key_name=key_name,
vpc_security_group_ids=[secgrp.id],
opts=pulumi.ResourceOptions(provider=aws_provider)
)
# Configure SSH connector.
connection = command.remote.ConnectionArgs(
host=server.public_ip,
user='ec2-user',
private_key=private_key
)
def contents(f):
with open(f, 'r') as fp:
return fp.read()
# Copy an example file.
cp = command.remote.CopyFile(f"{prefix}-file",
connection=connection,
local_path='example.txt',
remote_path='example.txt',
opts=pulumi.ResourceOptions(depends_on=[server]),
# triggers=[contents('example.txt')],
)
# Observe the contents of the copied file.
observe = command.remote.Command(f"{prefix}-observe",
connection=connection,
create='cat example.txt',
opts=pulumi.ResourceOptions(depends_on=[cp]),
# triggers=[contents('example.txt')],
)
pulumi.export('public_ip', server.public_ip)
pulumi.export('public_dns', server.public_dns)
pulumi.export('observe_stdout', observe.stdout)

Does CopyFile detect changes in a local file to initiate a replacement on the remote machine?

./make-keys.sh
pulumi stack init repro
pulumi stack select repro
./configure-keys.sh

pulumi up --yes

pulumi stack output observe_stdout  # "Hello"

echo "World" > example.txt

pulumi up --yes

# Resources: 7 unchanged?

pulumi stack output observe_stdout  # "Hello" ?

It appears that editing the file locally does not trigger a replacement by default.

It is possible to make the example work as expected using triggers:

triggers=[contents('example.txt')]

Using contents of the file here, but a hash would do also.

But this feels a little surprising and something that needs to be documented in examples to the user.

Consider making file hash a default implicit trigger for CopyFile?

Also, is it possible for replacements to cascade in Pulumi via depends_on, so that Command that depends_on a CopyFile will replace itself once the CopyFile is replaced, or this is convtroversial?

#!/usr/bin/env bash
set -euo pipefail
cat rsa.pub | pulumi config set publicKey --
cat rsa | pulumi config set privateKey --secret --
import pulumi
# Get the config ready to go.
config = pulumi.Config()
# If keyName is provided, an existing KeyPair is used, else if publicKey is provided a new KeyPair derived from the
# publicKey is created.
key_name = config.get('keyName')
public_key = config.get('publicKey')
# The privateKey associated with the selected key must be provided (either directly or base64 encoded)
def decode_key(key):
try:
key = base64.b64decode(key.encode('ascii')).decode('ascii')
except:
pass
if key.startswith('-----BEGIN RSA PRIVATE KEY-----'):
return key
return key.encode('ascii')
# Decode priviate key.
private_key = config.require_secret('privateKey').apply(decode_key)
#!/usr/bin/env bash
set -euo pipefail
ssh-keygen -t rsa -f rsa -b 4096 -m PEM
name: addb78402b3e91a910b2021bce7c8e1d
description: A minimal Python Pulumi program
runtime:
name: python
options:
virtualenv: venv
pulumi>=3.0.0,<4.0.0
pulumi-aws>=5.0.0,<6.0.0
pulumi-command
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment