droplets: Add support for creating prod droplets.

This commit is contained in:
Vishnu KS
2021-03-18 00:33:43 +05:30
committed by Tim Abbott
parent fa623dbd62
commit c1d80561a6
2 changed files with 91 additions and 20 deletions

View File

@@ -210,3 +210,12 @@ They can remove your SSH keys by running:
```
$ python3 ~/zulip/tools/droplets/add_mentor.py <your username> --remove
```
# Creating a production droplet
`create.py` can also create a production droplet quickly for testing purposes.
```
$ python3 create.py <username> --production
```

View File

@@ -1,4 +1,6 @@
# Creates a Droplet on DigitalOcean for remote Zulip development.
# Creates a Zulip remote development environment droplet or
# a production droplet in DigitalOcean.
#
# Particularly useful for sprints/hackathons, interns, and other
# situation where one wants to quickly onboard new contributors.
#
@@ -25,6 +27,7 @@ import urllib.request
from typing import Any, Dict, List
import digitalocean
import requests
# initiation argument parser
parser = argparse.ArgumentParser(description="Create a Zulip devopment VM DigitalOcean droplet.")
@@ -33,6 +36,7 @@ parser.add_argument(
)
parser.add_argument("--tags", nargs="+", default=[])
parser.add_argument("-f", "--recreate", action="store_true")
parser.add_argument("-p", "--production", action="store_true")
def get_config() -> configparser.ConfigParser:
@@ -109,7 +113,7 @@ def get_ssh_keys_string_from_github_ssh_key_dicts(userkey_dicts: List[Dict[str,
return "\n".join([userkey_dict["key"] for userkey_dict in userkey_dicts])
def set_user_data(username: str, userkey_dicts: List[Dict[str, Any]]) -> str:
def generate_dev_droplet_user_data(username: str, userkey_dicts: List[Dict[str, Any]]) -> str:
ssh_keys_string = get_ssh_keys_string_from_github_ssh_key_dicts(userkey_dicts)
setup_root_ssh_keys = f"printf '{ssh_keys_string}' > /root/.ssh/authorized_keys"
setup_zulipdev_ssh_keys = f"printf '{ssh_keys_string}' > /home/zulipdev/.ssh/authorized_keys"
@@ -146,6 +150,22 @@ su -c 'git config --global pull.rebase true' zulipdev
return cloudconf
def generate_prod_droplet_user_data(username: str, userkey_dicts: List[Dict[str, Any]]) -> str:
ssh_keys_string = get_ssh_keys_string_from_github_ssh_key_dicts(userkey_dicts)
setup_root_ssh_keys = f"printf '{ssh_keys_string}' > /root/.ssh/authorized_keys"
cloudconf = f"""\
#!/bin/bash
{setup_root_ssh_keys}
passwd -d root
sed -i "s/PasswordAuthentication yes/PasswordAuthentication no/g" /etc/ssh/sshd_config
service ssh restart
"""
print("...returning cloud-config data.")
return cloudconf
def create_droplet(
my_token: str, template_id: str, name: str, tags: List[str], user_data: str
) -> str:
@@ -205,7 +225,7 @@ def create_dns_record(my_token: str, record_name: str, ip_address: str) -> None:
domain.create_new_domain_record(type="A", name=wildcard_name, data=ip_address)
def print_completion(droplet_domain_name: str) -> None:
def print_dev_droplet_instructions(droplet_domain_name: str) -> None:
print(
"""
COMPLETE! Droplet for GitHub user {0} is available at {0}.zulipdev.org.
@@ -242,41 +262,80 @@ Your remote Zulip dev server has been created!
print("------")
if __name__ == "__main__":
# define id of image to create new droplets from
# You can get this with something like the following. You may need to try other pages.
# Broken in two to satisfy linter (line too long)
# curl -X GET -H "Content-Type: application/json" -u <API_KEY>: "https://api.digitaloc
# ean.com/v2/images?page=5" | grep --color=always base.zulipdev.org
template_id = "63219191"
def print_production_droplet_instructions(droplet_domain_name: str) -> None:
print(
"""
-----
Production droplet created successfully!
Connect to the server by running
ssh root@{}
-----
""".format(
droplet_domain_name
)
)
def get_zulip_oneclick_app_slug(api_token: str) -> str:
response = requests.get(
"https://api.digitalocean.com/v2/1-clicks", headers={"Authorization": f"Bearer {api_token}"}
).json()
one_clicks = response["1_clicks"]
for one_click in one_clicks:
if one_click["slug"].startswith("kandralabs"):
return one_click["slug"]
raise Exception("Unable to find Zulip One-click app slug")
if __name__ == "__main__":
# get command line arguments
args = parser.parse_args()
username = args.username.lower()
print(f"Creating Zulip developer environment for GitHub user {username}...")
subdomain = username
droplet_domain_name = f"{subdomain}.zulipdev.org"
if args.production:
print(f"Creating production droplet for GitHub user {username}...")
else:
print(f"Creating Zulip developer environment for GitHub user {username}...")
# get config details
config = get_config()
api_token = config["digitalocean"]["api_token"]
assert_github_user_exists(github_username=username)
# grab user's public keys
public_keys = get_keys(username=username)
# now make sure the user has forked zulip/zulip
fork_exists(username=username)
if args.production:
subdomain = f"{username}-prod"
droplet_domain_name = f"{subdomain}.zulipdev.org"
template_id = get_zulip_oneclick_app_slug(api_token)
user_data = generate_prod_droplet_user_data(username=username, userkey_dicts=public_keys)
else:
# now make sure the user has forked zulip/zulip
fork_exists(username=username)
subdomain = username
droplet_domain_name = f"{subdomain}.zulipdev.org"
user_data = generate_dev_droplet_user_data(username=username, userkey_dicts=public_keys)
# define id of image to create new droplets from
# You can get this with something like the following. You may need to try other pages.
# Broken in two to satisfy linter (line too long)
# curl -X GET -H "Content-Type: application/json" -u <API_KEY>: "https://api.digitaloc
# ean.com/v2/images?page=5" | grep --color=always base.zulipdev.org
template_id = "63219191"
api_token = config["digitalocean"]["api_token"]
assert_droplet_does_not_exist(
my_token=api_token, droplet_name=droplet_domain_name, recreate=args.recreate
)
# set user_data
user_data = set_user_data(username=username, userkey_dicts=public_keys)
# create droplet
ip_address = create_droplet(
my_token=api_token,
@@ -288,6 +347,9 @@ if __name__ == "__main__":
create_dns_record(my_token=api_token, record_name=subdomain, ip_address=ip_address)
print_completion(droplet_domain_name=droplet_domain_name)
if args.production:
print_production_droplet_instructions(droplet_domain_name=droplet_domain_name)
else:
print_dev_droplet_instructions(droplet_domain_name=droplet_domain_name)
sys.exit(1)