Skip to content

Commit

Permalink
Add a thebacknd create subcommand.
Browse files Browse the repository at this point in the history
  • Loading branch information
noteed committed May 10, 2024
1 parent e43ee0b commit 931e005
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 64 deletions.
75 changes: 75 additions & 0 deletions lib/thebacknd/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import datetime
import hmac
import hashlib
import json
import os
import pydo
from types import SimpleNamespace
Expand Down Expand Up @@ -98,12 +99,74 @@ def list_droplets():
r[x["id"]]["debug"] = x
return r


# Find the smallest number (starting from 1) that is not in a given list.
def smallest_missing_number(numbers):
current = 1
while True:
if current not in numbers:
return current
current += 1


def existing_droplet_numbers():
xs = do_client.droplets.list(tag_name="thebacknd")
# The names looks like "thebacknd-123".
ns = [int(x["name"].split("-")[-1]) for x in xs["droplets"]]
return ns


def create_droplet(nix_toplevel, nix_binary):
numbers = existing_droplet_numbers()
n = smallest_missing_number(numbers)
vm_id = create_vm_id()

user_data_content = {}
per_vm_secret = create_killcode(vm_id)
user_data_content["vm_id"] = vm_id
user_data_content["vm_killcode"] = per_vm_secret
# doctl serverless functions get thebacknd/destroy-self --url
# TODO Must be automatically discovered.
user_data_content[
"destroy_url"
] = "https://faas-ams3-2a2df116.doserverless.co/api/v1/web/fn-85df16d9-63e4-4388-875f-28a44e683171/thebacknd/destroy-self"

if nix_toplevel:
user_data_content["nix_toplevel"] = nix_toplevel
if nix_binary:
user_data_content["nix_binary"] = nix_binary
user_data_content["nix_cache"] = conf.nix_cache
user_data_content["nix_trusted_key"] = conf.nix_trusted_key
user_data_content["nix_cache_key_id"] = conf.nix_cache_key_id
user_data_content["nix_cache_key_secret"] = conf.nix_cache_key_secret

droplet_req = {
"name": "thebacknd-{0}".format(n),
"region": conf.vm_region,
"size": conf.vm_size,
"image": conf.vm_image,
"ssh_keys": [ssh_key],
# We pass the file content with user_data instead of
# user_data_file because I don't know how to get content
# back within the VM. With user_data, we can simple query
# the metadata service at
# http://169.254.169.254/metadata/v1/user-data.
"user_data": json.dumps(user_data_content, indent=2),
"tags": ["thebacknd", vm_id],
}
c = do_client.droplets.create(body=droplet_req)
return {
"create": c,
}


def destroy_all_droplets():
d = do_client.droplets.destroy_by_tag(tag_name="thebacknd")
return {
"destroy": d,
}


def cli():
"""
Drive the above functions from the command-line (i.e. locally instead of
Expand All @@ -121,6 +184,13 @@ def run_list():
xs = list_droplets()
pprint.pp(xs)

def run_create(nix_toplevel, nix_binary):
r = create_droplet(
nix_toplevel=nix_toplevel,
nix_binary=nix_binary,
)
pprint.pp(r)

def run_destroy_all():
r = destroy_all_droplets()
pprint.pp(r)
Expand All @@ -131,6 +201,11 @@ def run_destroy_all():
parser_list = subparsers.add_parser('list', help='List virtual machines')
parser_list.set_defaults(func=lambda args: run_list())

parser_create = subparsers.add_parser('create', help='Create a virtual machine')
parser_create.add_argument("--toplevel", type=str, default=None, help="Specify a toplevel to deploy.")
parser_create.add_argument("--binary", type=str, default=None, help="Specify a binary to run.")
parser_create.set_defaults(func=lambda args: run_create(nix_toplevel=args.toplevel, nix_binary=args.binary))

parser_destroy_all = subparsers.add_parser('destroy-all', help='Destroy all virtual machines')
parser_destroy_all.set_defaults(func=lambda args: run_destroy_all())

Expand Down
65 changes: 2 additions & 63 deletions packages/thebacknd/create/__main__.py
Original file line number Diff line number Diff line change
@@ -1,70 +1,9 @@
import json
import thebacknd


# Find the smallest number (starting from 1) that is not in a given list.
def smallest_missing_number(numbers):
current = 1
while True:
if current not in numbers:
return current
current += 1


def existing_droplet_numbers():
xs = thebacknd.do_client.droplets.list(tag_name="thebacknd")
# The names looks like "thebacknd-123".
ns = [int(x["name"].split("-")[-1]) for x in xs["droplets"]]
return ns


def create_droplet(nix_toplevel, nix_binary):
numbers = existing_droplet_numbers()
n = smallest_missing_number(numbers)
vm_id = thebacknd.create_vm_id()

user_data_content = {}
per_vm_secret = thebacknd.create_killcode(vm_id)
user_data_content["vm_id"] = vm_id
user_data_content["vm_killcode"] = per_vm_secret
# doctl serverless functions get thebacknd/destroy-self --url
# TODO Must be automatically discovered.
user_data_content[
"destroy_url"
] = "https://faas-ams3-2a2df116.doserverless.co/api/v1/web/fn-85df16d9-63e4-4388-875f-28a44e683171/thebacknd/destroy-self"

if nix_toplevel:
user_data_content["nix_toplevel"] = nix_toplevel
if nix_binary:
user_data_content["nix_binary"] = nix_binary
user_data_content["nix_cache"] = thebacknd.conf.nix_cache
user_data_content["nix_trusted_key"] = thebacknd.conf.nix_trusted_key
user_data_content["nix_cache_key_id"] = thebacknd.conf.nix_cache_key_id
user_data_content["nix_cache_key_secret"] = thebacknd.conf.nix_cache_key_secret

droplet_req = {
"name": "thebacknd-{0}".format(n),
"region": thebacknd.conf.vm_region,
"size": thebacknd.conf.vm_size,
"image": thebacknd.conf.vm_image,
"ssh_keys": [thebacknd.ssh_key],
# We pass the file content with user_data instead of
# user_data_file because I don't know how to get content
# back within the VM. With user_data, we can simple query
# the metadata service at
# http://169.254.169.254/metadata/v1/user-data.
"user_data": json.dumps(user_data_content, indent=2),
"tags": ["thebacknd", vm_id],
}
r = thebacknd.do_client.droplets.create(body=droplet_req)
return r


def main(event):
c = create_droplet(
r = thebacknd.create_droplet(
nix_toplevel=event.get("nix_toplevel", None),
nix_binary=event.get("nix_binary", None),
)
return {
"create": c,
}
return r
2 changes: 1 addition & 1 deletion packages/thebacknd/destroy-all/__main__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import thebacknd


def main(args):
def main(event):
r = thebacknd.destroy_all_droplets()
return r

0 comments on commit 931e005

Please sign in to comment.