Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
singlestore-labs
GitHub Repository: singlestore-labs/singlestoredb-python
Path: blob/main/resources/create_test_cluster.py
469 views
1
#!/usr/bin/env python
2
# type: ignore
3
from __future__ import annotations
4
5
import os
6
import random
7
import re
8
import secrets
9
import subprocess
10
import sys
11
import time
12
import uuid
13
from optparse import OptionParser
14
15
import singlestoredb as s2
16
17
18
# Handle command-line options
19
usage = 'usage: %prog [options] workspace-name'
20
parser = OptionParser(usage=usage)
21
parser.add_option(
22
'-r', '--region',
23
default='AWS::*US East 1*',
24
help='region pattern or ID',
25
)
26
parser.add_option(
27
'-p', '--password',
28
default=secrets.token_urlsafe(20) + '-x&$',
29
help='admin password',
30
)
31
parser.add_option(
32
'-e', '--expires',
33
default='4h',
34
help='timestamp when workspace should expire (4h)',
35
)
36
parser.add_option(
37
'-s', '--size',
38
default='S-00',
39
help='size of the workspace (S-00)',
40
)
41
parser.add_option(
42
'-t', '--token',
43
help='API key for the workspace management API',
44
)
45
parser.add_option(
46
'--http-port', type='int',
47
help='enable HTTP API on given port',
48
)
49
parser.add_option(
50
'-i', '--init-sql',
51
help='initialize database with given SQL file',
52
)
53
parser.add_option(
54
'-o', '--output',
55
default='env', choices=['env', 'github', 'json'],
56
help='report workspace information in the requested format: github, env, json',
57
)
58
parser.add_option(
59
'-d', '--database',
60
help='database name to create',
61
)
62
63
(options, args) = parser.parse_args()
64
65
if len(args) != 1:
66
parser.print_help()
67
sys.exit(1)
68
69
if options.init_sql and not os.path.isfile(options.init_sql):
70
print('ERROR: Could not locate SQL file: {options.init_sql}', file=sys.stderr)
71
sys.exit(1)
72
73
74
# Connect to workspace
75
wm = s2.manage_workspaces(options.token or None)
76
77
# Find matching region
78
if '::' in options.region:
79
pattern = options.region.replace('*', '.*')
80
regions = wm.regions
81
for item in random.sample(regions, k=len(regions)):
82
region_name = '{}::{}'.format(item.provider, item.name)
83
if re.match(pattern, region_name):
84
options.region = item.id
85
break
86
87
if '::' in options.region:
88
print(
89
'ERROR: Could not find a region mating the pattern: '
90
'{options.region}', file=sys.stderr,
91
)
92
sys.exit(1)
93
94
95
# Create workspace group
96
wg_name = 'Python Client Testing'
97
98
wgs = [x for x in wm.workspace_groups if x.name == wg_name]
99
if len(wgs) > 1:
100
print('ERROR: There is more than one workspace group with the specified name.')
101
sys.exit(1)
102
elif len(wgs) == 1:
103
wg = wgs[0]
104
else:
105
wg = wm.create_workspace_group(
106
wg_name,
107
region=options.region,
108
admin_password=options.password,
109
# firewall_ranges=requests.get('https://api.github.com/meta').json()['actions'],
110
firewall_ranges=['0.0.0.0/0'],
111
allow_all_traffic=True,
112
)
113
114
# Make sure the workspace group exists before continuing
115
timeout = 300
116
while timeout > 0 and not [x for x in wm.workspace_groups if x.name == wg_name]:
117
time.sleep(10)
118
timeout -= 10
119
120
ws_name = re.sub(r'^-|-$', r'', re.sub(r'-+', r'-', re.sub(r'\s+', '-', args[0].lower())))
121
122
ws = wg.create_workspace(
123
ws_name,
124
size=options.size,
125
wait_on_active=True,
126
)
127
128
# Make sure the endpoint exists before continuing
129
timeout = 300
130
while timeout > 0 and not ws.endpoint:
131
time.sleep(10)
132
ws.refresh()
133
timeout -= 10
134
135
if not ws.endpoint:
136
print('ERROR: Endpoint was never activated.')
137
sys.exit(1)
138
139
140
# Extra pause for server to become available
141
time.sleep(10)
142
143
database = options.database
144
if not database:
145
database = 'TEMP_{}'.format(uuid.uuid4()).replace('-', '_')
146
147
host = ws.endpoint
148
if ':' in host:
149
host, port = host.split(':', 1)
150
port = int(port)
151
else:
152
port = 3306
153
154
# Print workspace information
155
if options.output == 'env':
156
print(f'CLUSTER_ID={ws.id}')
157
print(f'CLUSTER_HOST={host}')
158
print(f'CLUSTER_PORT={port}')
159
print(f'CLUSTER_DATABASE={database}')
160
elif options.output == 'github':
161
with open(os.environ['GITHUB_OUTPUT'], 'a') as output:
162
print(f'cluster-id={ws.id}', file=output)
163
print(f'cluster-host={host}', file=output)
164
print(f'cluster-port={port}', file=output)
165
print(f'cluster-database={database}', file=output)
166
elif options.output == 'json':
167
print('{')
168
print(f' "cluster-id": "{ws.id}",')
169
print(f' "cluster-host": "{host}",')
170
print(f' "cluster-port": {port}')
171
print(f' "cluster-database": {database}')
172
print('}')
173
174
# Initialize the database
175
if options.init_sql:
176
init_db = [
177
os.path.join(os.path.dirname(__file__), 'init_db.py'),
178
'--host', str(host), '--port', str(port),
179
'--user', 'admin', '--password', options.password,
180
'--database', database,
181
]
182
183
if options.http_port:
184
init_db += ['--http-port', str(options.http_port)]
185
186
init_db.append(options.init_sql)
187
188
subprocess.check_call(init_db)
189
190