summaryrefslogtreecommitdiffstats
path: root/tozt/instance.py
diff options
context:
space:
mode:
Diffstat (limited to 'tozt/instance.py')
-rw-r--r--tozt/instance.py137
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,
+ }
+ )