2024-03-28 05:43:56 +00:00
|
|
|
from flask import Flask, make_response, abort, jsonify, render_template
|
|
|
|
from datetime import datetime
|
|
|
|
import logging, randomname, requests, time
|
2024-03-28 00:00:44 +00:00
|
|
|
|
|
|
|
app = Flask(__name__)
|
|
|
|
app.logger.setLevel(logging.DEBUG)
|
|
|
|
|
|
|
|
# How can we update coder admin_token??? What is the maximum expiration days?
|
|
|
|
# coder server --max-token-lifetime. Default 2540400 hours = 290 days
|
|
|
|
# The maximum lifetime duration users can specify when creating an API token.
|
|
|
|
# coder tokens create --lifetime. Default 720 hours = 30 days
|
|
|
|
# Specify a duration for the lifetime of the token.
|
|
|
|
# Create token API key - curl -X POST http://coder-server:8080/api/v2/users/{user}/keys/tokens
|
|
|
|
# {
|
|
|
|
# "lifetime": 0,
|
|
|
|
# "scope": "all",
|
|
|
|
# "token_name": "string"
|
|
|
|
# }
|
|
|
|
|
2024-03-28 05:43:56 +00:00
|
|
|
admin_token = 'mS7rgguZeb-VTyP8Yc3RPWQ1uy2thqsOi'
|
|
|
|
template_id = '80c50f63-0d2c-4a2c-a99f-45b36a9c038a'
|
|
|
|
organization_id = '9284e3c7-e20c-4736-929e-4f1508920811'
|
|
|
|
user = 'akamai'
|
2024-03-28 00:00:44 +00:00
|
|
|
user_email = 'learn@akamai.com'
|
|
|
|
user_pwd = 'Qodnwk=$s8'
|
|
|
|
|
2024-03-28 05:43:56 +00:00
|
|
|
|
2024-03-28 00:00:44 +00:00
|
|
|
token_header = {'Coder-Session-Token': admin_token,
|
|
|
|
'Accept': 'application/json'}
|
|
|
|
token_param = {'email': user_email, 'password': user_pwd}
|
|
|
|
|
|
|
|
# unused hours of workspace
|
|
|
|
unused_hours = 2
|
|
|
|
|
|
|
|
# workspace ttl ms
|
|
|
|
ttl = 86400000 # 24 hours
|
|
|
|
|
2024-03-28 05:43:56 +00:00
|
|
|
@app.route('/flask/hello')
|
|
|
|
def hello():
|
|
|
|
return 'hello'
|
|
|
|
|
|
|
|
@app.route('/flask/create')
|
|
|
|
def create():
|
|
|
|
start = datetime.now()
|
|
|
|
is_agent_ready = False
|
|
|
|
is_code_ready = False
|
|
|
|
body = create_workspace()
|
|
|
|
if body is None:
|
|
|
|
abort(500, description="cannot create new workspace")
|
|
|
|
|
|
|
|
workspace_name = get_workspace_name(body)
|
|
|
|
|
|
|
|
# is_agent_ready = is_agent_connected(workspace_name)
|
|
|
|
is_code_ready = is_code_live(workspace_name)
|
|
|
|
if is_code_ready == True:
|
|
|
|
end = datetime.now()
|
|
|
|
elapsed = end - start
|
|
|
|
app.logger.debug('elapsed= '+str(elapsed))
|
|
|
|
return workspace_name + " is ready!"
|
2024-03-28 00:00:44 +00:00
|
|
|
else:
|
2024-03-28 05:43:56 +00:00
|
|
|
abort(500, description="cannot start new workspace")
|
|
|
|
|
|
|
|
|
|
|
|
# this function creates a new workspace name based on current time
|
|
|
|
def create_workspace_name():
|
|
|
|
# past = timedelta(hours=-unused_hours)
|
|
|
|
# new_name = datetime.now() + past
|
|
|
|
new_name = str(datetime.now().strftime('%Y%m%d%H%M%S'))
|
|
|
|
name = randomname.get_name()
|
|
|
|
new_name = new_name + name
|
|
|
|
app.logger.debug('new_name= '+new_name)
|
|
|
|
return new_name
|
|
|
|
|
|
|
|
# create a workspace
|
|
|
|
def create_workspace():
|
|
|
|
url = 'http://coder:7080/api/v2/organizations/'+organization_id+'/members/'+user+'/workspaces'
|
|
|
|
workspace_name = create_workspace_name()
|
|
|
|
param = {"name": workspace_name,
|
|
|
|
"template_id": template_id, "ttl_ms": ttl}
|
|
|
|
|
|
|
|
response = requests.post(url, json=param, headers=token_header)
|
|
|
|
s_code = response.status_code
|
|
|
|
app.logger.info(workspace_name +
|
|
|
|
": create_workspace status: " + str(s_code))
|
|
|
|
body = response.json()
|
|
|
|
app.logger.debug(workspace_name + ': create_workspace body: ' + str(body))
|
|
|
|
if s_code == 201:
|
|
|
|
app.logger.info(workspace_name +" is created")
|
2024-03-28 00:00:44 +00:00
|
|
|
else:
|
2024-03-28 05:43:56 +00:00
|
|
|
app.logger.info(workspace_name +" cannot create a new workspace")
|
|
|
|
body = None
|
|
|
|
return body
|
|
|
|
|
|
|
|
def get_workspace_id(body: dict):
|
|
|
|
workspace_id = body['id']
|
|
|
|
app.logger.debug("workspace_id is "+workspace_id)
|
|
|
|
return workspace_id
|
|
|
|
|
|
|
|
def get_workspace_name(body: dict):
|
|
|
|
workspace_name = body['latest_build']['workspace_name']
|
|
|
|
app.logger.debug("workspace_name is "+workspace_name)
|
|
|
|
return workspace_name
|
2024-03-28 00:00:44 +00:00
|
|
|
|
2024-03-28 05:43:56 +00:00
|
|
|
def is_agent_connected(workspace_name):
|
|
|
|
agent_status = 'unknown'
|
|
|
|
count = 0
|
|
|
|
while agent_status != 'connected':
|
|
|
|
status_url = 'http://coder:7080/api/v2/users/'+user+'/workspace/'+workspace_name
|
|
|
|
status_response = requests.get(status_url, headers=token_header)
|
|
|
|
app.logger.debug(
|
|
|
|
workspace_name + ": is_agent_connected status code: " + str(status_response.status_code))
|
|
|
|
status_json = status_response.json()
|
|
|
|
app.logger.debug(status_json)
|
|
|
|
app.logger.debug(workspace_name + ': '+str(status_json))
|
|
|
|
if len(status_json['latest_build']['resources']) > 1:
|
|
|
|
for resource in status_json['latest_build']['resources']:
|
|
|
|
if resource['type'] == 'kubernetes_deployment':
|
|
|
|
for agent in resource['agents']:
|
|
|
|
if agent['name'] == 'main':
|
|
|
|
agent_status = agent['status']
|
|
|
|
app.logger.info(
|
|
|
|
workspace_name + ": agent status: " + agent_status)
|
|
|
|
if agent_status == 'timeout' or agent_status == 'connected':
|
|
|
|
break
|
2024-03-28 00:00:44 +00:00
|
|
|
|
|
|
|
|
2024-03-28 05:43:56 +00:00
|
|
|
count += 1
|
|
|
|
# will check coder is ready for the new url
|
|
|
|
time.sleep(3)
|
|
|
|
|
|
|
|
app.logger.debug(workspace_name + ": api call count: "+str(count))
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
# third, check the app running inside the workspace
|
|
|
|
# there are 2 apps. coder-server and OWASP juice-shop
|
|
|
|
def is_code_live(workspace_name):
|
|
|
|
code_url = 'http://coder:7080/@'+user+'/'+workspace_name+'.main/apps/code-server/?folder=/home/coder'
|
|
|
|
is_ready = False
|
|
|
|
while True:
|
|
|
|
response = requests.get(code_url)
|
|
|
|
s_code = response.status_code
|
|
|
|
app.logger.debug('%s status code= %s', code_url, s_code)
|
|
|
|
if s_code == 200:
|
|
|
|
is_ready = True
|
|
|
|
break
|
2024-03-28 00:00:44 +00:00
|
|
|
else:
|
2024-03-28 05:43:56 +00:00
|
|
|
time.sleep(3)
|
|
|
|
return is_ready
|
2024-03-28 00:00:44 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.errorhandler(500)
|
|
|
|
def internal_error(e):
|
|
|
|
return jsonify(error=str(e)), 500
|
2024-03-28 05:43:56 +00:00
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
app.run(host='0.0.0.0', port=5000, debug=True)
|