from flask import Flask, make_response, abort, jsonify, render_template from datetime import datetime import logging, randomname, requests, time 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" # } admin_token = 'mS7rgguZeb-VTyP8Yc3RPWQ1uy2thqsOi' template_id = '80c50f63-0d2c-4a2c-a99f-45b36a9c038a' organization_id = '9284e3c7-e20c-4736-929e-4f1508920811' user = 'akamai' user_email = 'learn@akamai.com' user_pwd = 'Qodnwk=$s8' 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 @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!" else: 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") else: 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 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 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 else: time.sleep(3) return is_ready @app.errorhandler(500) def internal_error(e): return jsonify(error=str(e)), 500 if __name__ == "__main__": app.run(host='0.0.0.0', port=5000, debug=True)