def _statuspage_create_incident( headers, component_id, tree, status_from, status_to, ): page_id = flask.current_app.config.get('STATUSPAGE_PAGE_ID') if not page_id: log.error('STATUSPAGE_PAGE_ID not defined in app config.') return data = _statuspage_data( False, component_id, tree, status_from, status_to, ) log.debug( f'Create statuspage incident for tree `{tree.tree}` under page `{page_id}`', data=data) response = requests.post( f'{STATUSPAGE_URL}/pages/{page_id}/incidents', headers=headers, json=data, ) try: response.raise_for_status() except Exception as e: log.exception(e) _statuspage_send_email_on_error( subject=f'[treestatus] Error when creating statuspage incident', content=STATUSPAGE_ERROR_ON_CREATE.format(tree=tree.tree), )
def _statuspage_resolve_incident( headers, component_id, tree, status_from, status_to, ): page_id = flask.current_app.config.get('STATUSPAGE_PAGE_ID') response = requests.get( f'{STATUSPAGE_URL}/pages/{page_id}/incidents/unresolved', headers=headers, ) try: response.raise_for_status() except Exception as e: log.exception(e) _statuspage_send_email_on_error( subject=f'[treestatus] Error when closing statuspage incident', content=STATUSPAGE_ERROR_ON_CLOSE.format(tree=tree.tree), ) return # last incident with meta.treestatus.tree == tree.tree incident_id = None incidents = sorted(response.json(), key=lambda x: x['created_at']) for incident in incidents: if 'id' in incident and \ 'metadata' in incident and \ 'treestatus' in incident['metadata'] and \ 'tree' in incident['metadata']['treestatus'] and \ incident['metadata']['treestatus']['tree'] == tree.tree: incident_id = incident['id'] break if incident_id is None: log.info(f'No incident found when closing tree `{tree.tree}`') return response = requests.patch( f'{STATUSPAGE_URL}/pages/{page_id}/incidents/{incident_id}', headers=headers, json=_statuspage_data( True, component_id, tree, status_from, status_to, ), ) try: response.raise_for_status() except Exception as e: log.exception(e) _statuspage_send_email_on_error( subject=f'[treestatus] Error when closing statuspage incident', content=STATUSPAGE_ERROR_ON_CLOSE.format(tree=tree.tree), incident_id=incident_id, )
def get_scheduler_graph_state(task_graph_id): '''poll the scheduler for overall status. this request is relatively cheap. :returns state where state is of: running, blocked or finished''' try: return TASK_GRAPH_STATE_TO_STEP_STATE[TC_SCHEDULER.status( task_graph_id)['status']['state']] except Exception: state = 'exception' log.exception( 'Could not determine status from taskcluster scheduler with graph id: %s', task_graph_id) return state
def delete_taskcluster_step(uid): log.info('deleting step %s', uid) try: step = TaskclusterStep.query.filter_by(uid=uid).one() except Exception as e: exception = 'Taskcluster step could not be found by given uid: {}'.format( uid) log.exception(exception) abort(404, exception) db.session.delete(step) db.session.commit() return {}
def list_taskcluster_steps(state='running'): log.info('listing steps') try: desired_state = TaskclusterStatus[state] except KeyError: exception = '{} is not a valid state'.format(state) log.warning('valid states: %s', [state.value for state in TaskclusterStatus]) log.exception(exception) abort(400, exception) try: steps = db.session.query(TaskclusterStep).filter( TaskclusterStep.state == desired_state).all() except NoResultFound: abort(404, 'No Taskcluster steps found with that given state.') log.info('listing steps: {}', steps) return [step.uid for step in steps]
def cmd_TASKCLUSTER_HOOK(ctx, project, extra_attribute, hook_id, hook_group_id, nix_build, nix_push, taskcluster_secret, taskcluster_client_id, taskcluster_access_token, docker_repo, interactive, ): secrets = cli_common.taskcluster.get_secrets( taskcluster_secret, project, required=( 'DOCKER_USERNAME', 'DOCKER_PASSWORD', ), taskcluster_client_id=taskcluster_client_id, taskcluster_access_token=taskcluster_access_token, ) docker_username = secrets['DOCKER_USERNAME'] docker_password = secrets['DOCKER_PASSWORD'] hooks_tool = cli_common.taskcluster.get_service('hooks') click.echo(' => Hook `{}/{}` exists? ... '.format(hook_group_id, hook_id), nl=False) with click_spinner.spinner(): hooks = [i['hookId'] for i in hooks_tool.listHooks(hook_group_id).get('hooks', [])] hook_exists = False result = 1 output = 'Hook {} not exists in {}'.format(hook_id, str(hooks)) if hook_id in hooks: hook_exists = True result = 0 output = 'Hook {} exists in {}'.format(hook_id, str(hooks)) please_cli.utils.check_result( result, output, success_message='EXISTS', error_message='NOT EXISTS', ask_for_details=interactive, raise_exception=False, ) ctx.invoke(please_cli.build.cmd, project=project, extra_attribute=extra_attribute, nix_build=nix_build, nix_push=nix_push, taskcluster_secret=taskcluster_secret, taskcluster_client_id=taskcluster_client_id, taskcluster_access_token=taskcluster_access_token, interactive=interactive, ) project_path = os.path.realpath(os.path.join( please_cli.config.TMP_DIR, 'result-build-{}-1'.format(project), )) with open(project_path) as f: hook = json.load(f) image = hook.get('task', {}).get('payload', {}).get('image', '') if image.startswith('/nix/store'): image_tag = '-'.join(reversed(image[11:-7].split('-', 1))) click.echo(' => Uploading docker image `{}:{}` ... '.format(docker_repo, image_tag), nl=False) with click_spinner.spinner(): push.registry.push( push.image.spec(image), please_cli.config.DOCKER_REGISTRY, docker_username, docker_password, docker_repo, image_tag, ) please_cli.utils.check_result( 0, 'Pushed {}:{} docker image.'.format(docker_repo, image_tag), ask_for_details=interactive, ) hook['task']['payload']['image'] = '{}:{}'.format(docker_repo, image_tag) if hook_exists: click.echo(' => Updating hook `{}/{}` ... '.format(hook_group_id, hook_id), nl=False) with click_spinner.spinner(): try: hooks_tool.updateHook(hook_group_id, hook_id, hook) result = 0 output = '' except taskcluster.exceptions.TaskclusterRestFailure as e: log.exception(e) output = str(e) result = 1 else: click.echo(' => Creating hook `{}/{}` ... '.format(hook_group_id, hook_id), nl=False) with click_spinner.spinner(): try: hooks_tool.createHook(hook_group_id, hook_id, hook) result = 0 output = '' except taskcluster.exceptions.TaskclusterRestFailure as e: log.exception(e) output = str(e) result = 1 please_cli.utils.check_result( result, output, ask_for_details=interactive, )
def cmd( project, cache_urls, nix_instantiate, channel, indent=0, interactive=True, ): '''Command to check if project is already in cache. ''' indent = ' ' * indent channel_derivations = dict() nix_path_attributes = [project] deploys = please_cli.config.PROJECTS_CONFIG.get(project, dict()).get('deploys', []) for deploy in deploys: for _channel, options in deploy.get('options', dict()).items(): if _channel in please_cli.config.DEPLOY_CHANNELS: nix_path_attribute = options.get('nix_path_attribute') if nix_path_attribute: nix_path_attributes.append(project + '.' + nix_path_attribute) else: nix_path_attributes.append(project) nix_path_attributes = list(set(nix_path_attributes)) for nix_path_attribute in nix_path_attributes: project_exists = False click.echo('{} => Calculating `{}` hash ... '.format( indent, nix_path_attribute), nl=False) command = [ nix_instantiate, os.path.join(please_cli.config.ROOT_DIR, 'nix/default.nix'), '-A', nix_path_attribute, ] if interactive: with click_spinner.spinner(): result, output, error = cli_common.command.run( command, stream=True, stderr=subprocess.STDOUT, ) else: result, output, error = cli_common.command.run( command, stream=True, stderr=subprocess.STDOUT, ) try: drv = output.split('\n')[-1].strip() with open(drv) as f: channel_derivations[nix_path_attribute] = eval(f.read()) except Exception as e: log.exception(e) raise click.ClickException( 'Something went wrong when reading derivation file for `{}` project.' .format(nix_path_attribute)) click.echo('{} found.'.format( channel_derivations[nix_path_attribute].nix_hash)) click.echo( '{} => Checking cache if build artifacts exists for `{}` ... '. format(indent, nix_path_attribute), nl=False) with click_spinner.spinner(): project_exists = False for cache_url in cache_urls: response = requests.get( '%s/%s.narinfo' % (cache_url, channel_derivations[nix_path_attribute].nix_hash), ) project_exists = response.status_code == 200 if project_exists: break result = 1 if project_exists: result = 0 please_cli.utils.check_result( result, success_message='EXISTS', error_message='NOT EXISTS', raise_exception=False, ask_for_details=interactive, ) return project_exists, channel_derivations[project].nix_hash
def cmd(project, cache_urls, nix_instantiate, indent=0, interactive=True): """Command to check if project is already in cache. """ indent = ' ' * indent click.echo('{} => Calculating `{}` hash ... '.format(indent, project), nl=False) command = [ nix_instantiate, os.path.join(please_cli.config.ROOT_DIR, 'nix/default.nix'), '-A', project ] if interactive: with click_spinner.spinner(): result, output, error = cli_common.command.run( command, stream=True, stderr=subprocess.STDOUT, ) else: result, output, error = cli_common.command.run( command, stream=True, stderr=subprocess.STDOUT, ) please_cli.utils.check_result( result, output, ask_for_details=interactive, ) try: drv = output.split('\n')[-1].strip() with open(drv) as f: derivation = eval(f.read()) except Exception as e: log.exception(e) raise click.ClickException('Something went wrong when reading derivation file for `{}` project.'.format(project)) click.echo('{} Application hash: {}'.format(indent, derivation.nix_hash)) click.echo('{} => Checking cache if build artifacts exists for `{}` ... '.format(indent, project), nl=False) with click_spinner.spinner(): project_exists = False for cache_url in cache_urls: response = requests.get( '%s/%s.narinfo' % (cache_url, derivation.nix_hash), ) project_exists = response.status_code == 200 if project_exists: break result = 1 if project_exists: result = 0 please_cli.utils.check_result( result, success_message='EXISTS', error_message='NOT EXISTS', raise_exception=False, ask_for_details=False, ) return project_exists, derivation.nix_hash
def cmd_TASKCLUSTER_HOOK(ctx, project, nix_path_attribute, hook_id, hook_group_id, nix_build, nix, taskcluster_secret, taskcluster_client_id, taskcluster_access_token, docker_registry, docker_repo, docker_stable_tag, interactive, ): secrets = cli_common.taskcluster.get_secrets( taskcluster_secret, project, required=( 'DOCKER_USERNAME', 'DOCKER_PASSWORD', ), taskcluster_client_id=taskcluster_client_id, taskcluster_access_token=taskcluster_access_token, ) docker_username = secrets['DOCKER_USERNAME'] docker_password = secrets['DOCKER_PASSWORD'] hooks_tool = cli_common.taskcluster.get_service('hooks') click.echo(f' => Hook `{hook_group_id}/{hook_id}` exists? ... ', nl=False) with click_spinner.spinner(): hooks = [i['hookId'] for i in hooks_tool.listHooks(hook_group_id).get('hooks', [])] hook_exists = False result = 1 output = f'Hook {hook_id} not exists in {str(hooks)}' if hook_id in hooks: hook_exists = True result = 0 output = f'Hook {hook_id} exists in {str(hooks)}' please_cli.utils.check_result( result, output, success_message='EXISTS', error_message='NOT EXISTS', ask_for_details=interactive, raise_exception=False, ) project_paths = ctx.invoke(please_cli.build.cmd, project=project, nix_path_attributes=[nix_path_attribute], nix_build=nix_build, nix=nix, taskcluster_secret=taskcluster_secret, taskcluster_client_id=taskcluster_client_id, taskcluster_access_token=taskcluster_access_token, interactive=interactive, ) for project_path in project_paths: project_path = os.path.realpath(project_path) with open(project_path) as f: hook = json.load(f) image = hook.get('task', {}).get('payload', {}).get('image', '') if image.startswith('/nix/store'): versioned_image_tag = '-'.join(reversed(image[11:-7].split('-', 1))) image_tags = [versioned_image_tag] if docker_stable_tag: image_tags.append(docker_stable_tag) for image_tag in image_tags: click.echo(f' => Uploading docker image `{docker_repo}:{image_tag}` ... ', nl=False) with click_spinner.spinner(): please_cli.utils.push_docker_image( registry=docker_registry, username=docker_username, password=docker_password, image=f'docker-archive://{image}', repo=docker_repo, tag=image_tag, interactive=interactive, ) hook['task']['payload']['image'] = f'{docker_repo}:{versioned_image_tag}' if hook_exists: click.echo(f' => Updating hook `{hook_group_id}/{hook_id}` ... ', nl=False) with click_spinner.spinner(): try: hooks_tool.updateHook(hook_group_id, hook_id, hook) result = 0 output = '' except taskcluster.exceptions.TaskclusterRestFailure as e: log.exception(e) output = str(e) result = 1 else: click.echo(f' => Creating hook `{hook_group_id}/{hook_id}` ... ', nl=False) with click_spinner.spinner(): try: hooks_tool.createHook(hook_group_id, hook_id, hook) result = 0 output = '' except taskcluster.exceptions.TaskclusterRestFailure as e: log.exception(e) output = str(e) result = 1 please_cli.utils.check_result( result, output, ask_for_details=interactive, )
def cmd(project, cache_urls, nix_instantiate, channel, indent=0, interactive=True, ): '''Command to check if project is already in cache. ''' indent = ' ' * indent channel_derivations = dict() nix_path_attributes = [project] deploys = please_cli.config.PROJECTS_CONFIG.get(project, dict()).get('deploys', []) for deploy in deploys: for _channel, options in deploy.get('options', dict()).items(): if _channel in please_cli.config.DEPLOY_CHANNELS: nix_path_attribute = options.get('nix_path_attribute') if nix_path_attribute: nix_path_attributes.append(project + '.' + nix_path_attribute) else: nix_path_attributes.append(project) nix_path_attributes = list(set(nix_path_attributes)) for nix_path_attribute in nix_path_attributes: project_exists = False click.echo('{} => Calculating `{}` hash ... '.format(indent, nix_path_attribute), nl=False) command = [ nix_instantiate, os.path.join(please_cli.config.ROOT_DIR, 'nix/default.nix'), '-A', nix_path_attribute, ] if interactive: with click_spinner.spinner(): result, output, error = cli_common.command.run( command, stream=True, stderr=subprocess.STDOUT, ) else: result, output, error = cli_common.command.run( command, stream=True, stderr=subprocess.STDOUT, ) try: drv = output.split('\n')[-1].strip() with open(drv) as f: channel_derivations[nix_path_attribute] = eval(f.read()) except Exception as e: log.exception(e) raise click.ClickException('Something went wrong when reading derivation file for `{}` project.'.format(nix_path_attribute)) click.echo('{} found.'.format(channel_derivations[nix_path_attribute].nix_hash)) click.echo('{} => Checking cache if build artifacts exists for `{}` ... '.format(indent, nix_path_attribute), nl=False) with click_spinner.spinner(): project_exists = False for cache_url in cache_urls: response = requests.get( '%s/%s.narinfo' % (cache_url, channel_derivations[nix_path_attribute].nix_hash), ) project_exists = response.status_code == 200 if project_exists: break result = 1 if project_exists: result = 0 please_cli.utils.check_result( result, success_message='EXISTS', error_message='NOT EXISTS', raise_exception=False, ask_for_details=interactive, ) return project_exists, channel_derivations[project].nix_hash