diff options
Diffstat (limited to 'tozt/instance.py')
-rw-r--r-- | tozt/instance.py | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/tozt/instance.py b/tozt/instance.py new file mode 100644 index 0000000..1d94bda --- /dev/null +++ b/tozt/instance.py @@ -0,0 +1,137 @@ +from pathlib import Path +from typing import Optional + +import pulumi +import pulumi_digitalocean as do +import pulumi_command as command + +from .ssh import SshKey + + +class Instance(pulumi.ComponentResource): + def __init__( + self, + name: str, + region: str, + size: str, + dns_name: str, + reserved_ip: Optional[str] = None, + volume_name: Optional[str] = None, + opts: Optional[pulumi.ResourceOptions] = None, + ): + self.name = name + self.dns_name = dns_name + self.reserved_ip = reserved_ip + + super().__init__( + f"{pulumi.get_project()}:instance:Instance/{name}", name, None, opts + ) + + ssh_key = SshKey( + f"{self.name}-ssh-keypair", + opts=pulumi.ResourceOptions(parent=self), + ) + ssh = do.SshKey( + self.name, + public_key=ssh_key.public_key, + name=f"{pulumi.get_project()}-{pulumi.get_stack()}-{self.name}", + opts=pulumi.ResourceOptions(parent=self), + ) + + volumes = [] + if volume_name is not None: + volume = do.get_volume_output( + name=volume_name, + region=region, + opts=pulumi.InvokeOptions(parent=self), + ) + volumes.append(volume.id) + self.instance = do.Droplet( + self.name, + name=dns_name, + image="debian-10-x64", + region=region, + size=size, + ssh_keys=[ssh.id], + volume_ids=volumes, + opts=pulumi.ResourceOptions(parent=self), + ) + + if reserved_ip is not None: + self.ip_assignment = do.ReservedIpAssignment( + self.name, + ip_address=reserved_ip, + droplet_id=self.instance.id.apply(lambda id: int(id)), + opts=pulumi.ResourceOptions(parent=self), + ) + + connection = command.remote.ConnectionArgs( + host=self.instance.ipv4_address, + private_key=ssh_key.private_key, + user="root", + dial_error_limit=100, + ) + bootstrap_debian_file = command.remote.CopyFile( + f"{self.name}-bootstrap_debian", + connection=connection, + local_path="bootstrap/debian", + remote_path="/tmp/bootstrap", + opts=pulumi.ResourceOptions(parent=self), + ) + bootstrap_debian = command.remote.Command( + f"{self.name}-bootstrap_debian", + connection=connection, + create="sh /tmp/bootstrap", + opts=pulumi.ResourceOptions( + parent=self, depends_on=[bootstrap_debian_file] + ), + ) + sleep = command.local.Command( + f"{self.name}-sleep", + create="sleep 30", + opts=pulumi.ResourceOptions( + parent=self, depends_on=[bootstrap_debian] + ), + ) + make_secrets_dir = command.remote.Command( + f"{self.name}-make_secrets_dir", + connection=connection, + create="mkdir /tmp/secrets", + opts=pulumi.ResourceOptions(parent=self, depends_on=[sleep]), + ) + bootstrap_arch_file = command.remote.CopyFile( + f"{self.name}-bootstrap_arch", + connection=connection, + local_path="bootstrap/arch", + remote_path="/tmp/bootstrap", + opts=pulumi.ResourceOptions(parent=self, depends_on=[sleep]), + ) + secret_files = [] + for file in Path(f"/mnt/puppet/{name}").glob("*"): + secret_files.append( + command.remote.CopyFile( + f"{self.name}-secret-{file.name}", + connection=connection, + local_path=str(file), + remote_path=f"/tmp/secrets/{file.name}", + opts=pulumi.ResourceOptions( + parent=self, depends_on=[make_secrets_dir] + ), + ) + ) + command.remote.Command( + f"{self.name}-bootstrap_arch", + connection=connection, + create="sh /tmp/bootstrap", + opts=pulumi.ResourceOptions( + parent=self, + depends_on=[bootstrap_arch_file, *secret_files], + ), + ) + + self.register_outputs( + { + "dns_name": dns_name, + "ip_address": self.instance.ipv4_address, + } + ) |