-
Notifications
You must be signed in to change notification settings - Fork 0
/
deploy.py
120 lines (105 loc) · 3.6 KB
/
deploy.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import argparse
import logging
import textwrap
from googleapiclient import discovery
from googleapiclient.http import HttpError
DEBIAN_10_IMAGE = "projects/debian-cloud/global/images/debian-10-buster-v20200714"
class GcloudClient:
def __init__(self, project: str) -> None:
self.project = project
self._compute = None
@property
def compute(self) -> discovery.Resource:
if self._compute is None:
self._compute = discovery.build("compute", "v1")
return self._compute
def create_firewall_rule(self) -> None:
"""
Idempotently creates a firewall rule allowing TCP traffic on port 8000 from
instances with tag `accessioning` into instances with tag `caper-server`.
"""
logging.info("Creating firewall rule")
rule_name = "accession-remote-caper"
firewall_body = {
"name": rule_name,
"allowed": [{"IPProtocol": "tcp", "ports": ["8000"]}],
"sourceTags": ["accessioning"],
"targetTags": ["caper-server"],
}
request = self.compute.firewalls().insert(
project=self.project, body=firewall_body
)
try:
request.execute()
except HttpError:
logging.warn("Firewall rule %s already exists, skipping", rule_name)
def create_instance(self, zone, instance_name: str) -> None:
logging.info("Creating instance %s", instance_name)
startup_script = textwrap.dedent(
"""
sudo apt-get update
sudo apt-get install -y python3-pip
sudo pip3 install -U accession
"""
)
config = {
"name": instance_name,
"machineType": f"zones/{zone}/machineTypes/n1-standard-4",
"disks": [
{
"boot": True,
"autoDelete": True,
"initializeParams": {"sourceImage": DEBIAN_10_IMAGE},
}
],
"networkInterfaces": [
{
"network": "global/networks/default",
"accessConfigs": [
{"type": "ONE_TO_ONE_NAT", "name": "External NAT"}
],
}
],
"serviceAccounts": [
{
"email": "default",
"scopes": ["https://www.googleapis.com/auth/logging.write"],
}
],
"metadata": {"items": [{"key": "startup-script", "value": startup_script}]},
"tags": {"items": ["accessioning"]},
}
self.compute.instances().insert(
project=self.project, zone=zone, body=config
).execute()
def main() -> None:
logging.basicConfig(
level=logging.INFO, format="%(asctime)s %(name)s %(levelname)s %(message)s"
)
parser = get_parser()
args = parser.parse_args()
client = GcloudClient(args.project)
client.create_firewall_rule()
client.create_instance(args.zone, args.instance_name)
def get_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser()
parser.add_argument(
"-p",
"--project",
help="The Google Cloud project ID in which the instance will be deployed",
)
parser.add_argument(
"-z",
"--zone",
default="us-west1-a",
help="The Compute Engine zone to deploy to.",
)
parser.add_argument(
"-n",
"--instance-name",
default="accession",
help="The name for the new instance.",
)
return parser
if __name__ == "__main__":
main()