def from_json(cls, kwargs): from dimensigon.domain.entities import ActionTemplate, Orchestration kwargs = dict(kwargs) if 'orchestration_id' in kwargs: ident = kwargs.pop('orchestration_id') kwargs['orchestration'] = db.session.query(Orchestration).get(ident) if kwargs['orchestration'] is None: raise errors.EntityNotFound('Orchestration', ident=ident) if 'action_template_id' in kwargs: ident = kwargs.pop('action_template_id') kwargs['action_template'] = db.session.query(ActionTemplate).get(ident) if kwargs['action_template'] is None: raise errors.EntityNotFound('ActionTemplate', ident=ident) if 'action_type' in kwargs: kwargs['action_type'] = ActionType[kwargs.pop('action_type')] if 'created_on' in kwargs: kwargs['created_on'] = datetime.datetime.strptime(kwargs['created_on'], defaults.DATETIME_FORMAT) kwargs['parent_steps'] = [] for parent_step_id in kwargs.pop('parent_step_ids', []): ps = Step.query.get(parent_step_id) if ps: kwargs['parent_steps'].append(ps) else: raise errors.EntityNotFound('Step', parent_step_id) return super().from_json(kwargs)
def wrapper(*args, **kwargs): # app resolution app = None if 'app' in kwargs: app = kwargs['app'] else: for a in args: if isinstance(a, Flask): app = a break else: app = current_app if app: ctx = app.app_context() ctx.push() try: user = User.get_by_name(username) if user is None: raise errors.EntityNotFound("User", username, ['name']) from flask_jwt_extended.utils import ctx_stack ctx_stack.top.jwt_user = user jwt = {'identity': str(user.id)} ctx_stack.top.jwt = jwt return f(*args, **kwargs) finally: db.session.close() if app: ctx.pop()
def wrapper_decorator(*args, **kwargs): destination_id = None if 'D-Destination' in request.headers: destination_id = request.headers['D-Destination'] else: # Get information from content # Code Compatibility. Use D-Destination header instead data = request.get_json() if data is not None and 'destination' in data: destination_id = data.get('destination') if destination_id and destination_id != str(g.server.id) and (not methods or request.method in methods): destination: Server = Server.query.get(destination_id) if destination is None: return errors.format_error_response(errors.EntityNotFound('Server', destination_id)) try: if destination.route.proxy_server or destination.route.gate: logger.debug(f"Forwarding request {request.method} {request.full_path} to {destination.route}") resp = _proxy_request(request=request, destination=destination) else: return errors.format_error_response(errors.UnreachableDestination(destination, g.server)) except requests.exceptions.RequestException as e: return errors.format_error_response(errors.ProxyForwardingError(destination, e)) else: return resp.content, resp.status_code, dict(resp.headers) else: value = func(*args, **kwargs) return value
def test_server_not_found(self, mock_g): mock_g.server = MagicMock(id=self.srv1.id) resp = self.client.post('/', json={'data': None}, headers={'D-Destination': 'bbbbbbbb-1234-5678-1234-56781234bbb5'}) self.validate_error_response(resp, errors.EntityNotFound('Server', 'bbbbbbbb-1234-5678-1234-56781234bbb5'))
def delete(self, software_id): data = request.get_json() if Software.query.filter_by(id=software_id).count() == 0: raise errors.EntityNotFound('Software', software_id) for server_id in data: ssa = SoftwareServerAssociation.query.filter_by( software_id=software_id, server_id=server_id) if not ssa: raise errors.EntityNotFound('SoftwareServerAssociation', (software_id, server_id), ['software_id', 'server_id']) ssa.delete() db.session.commit() return {}, 204
def join_acknowledge(server_id): server_data = servers_to_be_created.get(server_id, None) if not server_data: raise errors.EntityNotFound('Server', server_id) s = Server.from_json(server_data) with _lock_add_node: db.session.add(s) db.session.commit() current_app.logger.debug(f"Server join acknowledge {s.name}") return {}, 204
def test_launch_orchestration_filter_by_orchestration_not_found(self): data = {'hosts': self.s1.id, 'orchestration': 'invented', 'params': {'folder': '/home/{{user}}', 'home': '{{folder}}', 'user': '******'}, 'skip_validation': True, 'background': False} resp = self.client.post(url_for('api_1_0.launch_orchestration'), json=data, headers=self.auth.header) self.validate_error_response(resp, errors.EntityNotFound('Orchestration', ['invented'], ('orchestration',)))
def test_post(self): resp = self.client.post(url_for('api_1_0.vaultresource', name='foo'), json={'value': ['list']}, headers=self.auth.header) self.assertEqual(204, resp.status_code) v = Vault.query.get((ROOT, 'global', 'foo')) self.assertListEqual(['list'], v.value) resp = self.client.post(url_for('api_1_0.vaultresource', name='fake'), json={'value': ['list']}, headers=self.auth.header) self.validate_error_response( resp, errors.EntityNotFound("Vault", [ROOT, 'global', 'fake']))
def get(id_or_name, version=None) -> t.Union['Orchestration', str]: if is_valid_uuid(id_or_name): orch = Orchestration.query.get(id_or_name) if orch is None: return str(errors.EntityNotFound('Orchestration', id_or_name)) else: if id_or_name: query = Orchestration.query.filter_by( name=id_or_name).order_by(Orchestration.version.desc()) if version: query.filter_by(version=version) orch = query.first() if orch is None: return f"No orchestration found for '{id_or_name}'" + ( f" version '{version}'" if version else None) else: return "No orchestration specified" return orch
def file_sync(file_id): if get_jwt_identity() == '00000000-0000-0000-0000-000000000001': data = request.get_json() file = File.query.get(file_id) if file is None and not data.get('force', False): raise errors.EntityNotFound("File", file_id) file = data.get('file') content = zlib.decompress(base64.b64decode(data.get('data').encode('ascii'))) _logger.debug(f"received file sync {file}.") try: if not os.path.exists(os.path.dirname(file)): os.makedirs(os.path.dirname(file)) with open(file, 'wb') as fh: fh.write(content) except Exception as e: raise errors.GenericError(f"Error while trying to create/write file: {e}", 500) return {}, 204 else: raise errors.UserForbiddenError
def test_get(self): resp = self.client.get(url_for('api_1_0.vaultresource', name='foo'), headers=self.auth.header) self.assertDictEqual(self.vr1.to_json(no_delete=True), resp.get_json()) resp = self.client.get(url_for('api_1_0.vaultresource', name='foo', scope='test'), headers=self.auth.header) self.assertDictEqual(self.vr2.to_json(no_delete=True), resp.get_json()) resp = self.client.get(url_for('api_1_0.vaultresource', name='foo') + '?params=human', headers=self.auth.header) self.assertDictEqual(self.vr1.to_json(no_delete=True, human=True), resp.get_json()) resp = self.client.get(url_for('api_1_0.vaultresource', name='fake'), headers=self.auth.header) self.validate_error_response( resp, errors.EntityNotFound("Vault", [ROOT, 'global', 'fake']))
def launch_command(): data = request.get_json() server_list = [] if 'target' in data: not_found = [] servers = Server.query.all() if data['target'] == 'all': server_list = servers elif is_iterable_not_string(data['target']): for vv in data['target']: sl = search(vv, servers) if len(sl) == 0: not_found.append(vv) else: server_list.extend(sl) else: sl = search(data['target'], servers) if len(sl) == 0: not_found.append(data['target']) else: server_list.extend(sl) if not_found: return { 'error': "Following granules or ids did not match to any server: " + ', '.join(not_found) }, 404 else: server_list.append(g.server) if re.search(r'rm\s+((-\w+|--[-=\w]*)\s+)*(-\w*[rR]\w*|--recursive)', data['command']): return {'error': 'rm with recursion is not allowed'}, 403 data.pop('target', None) start = None username = getattr(User.query.get(get_jwt_identity()), 'name', None) if not username: raise errors.EntityNotFound('User', get_jwt_identity()) cmd = wrap_sudo(username, data['command']) if g.server in server_list: start = time.time() server_list.pop(server_list.index(g.server)) proc = subprocess.Popen( cmd, stdin=subprocess.PIPE if data.get('input', None) else None, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=True, close_fds=True, encoding='utf-8') resp_data = {} if check_param_in_uri("human"): attr = 'name' else: attr = 'id' if server_list: resp: t.List[ntwrk.Response] = asyncio.run( ntwrk.parallel_requests(server_list, method='POST', view_or_url='api_1_0.launch_command', json=data)) for s, r in zip(server_list, resp): key = getattr(s, attr, s.id) if r.ok: resp_data[key] = r.msg[s.id] else: if not r.exception: resp_data[key] = { 'error': { 'status_code': r.code, 'response': r.msg } } else: if isinstance(r.exception, errors.BaseError): resp_data[key] = errors.format_error_content( r.exception, current_app.config['DEBUG']) else: resp_data[key] = { 'error': format_exception(r.exception) if current_app.config['DEBUG'] else str(r.exception) or str(r.exception.__class__.__name__) } if start: key = getattr(g.server, attr, g.server.id) timeout = data.get('timeout', defaults.TIMEOUT_COMMAND) try: outs, errs = proc.communicate(input=(data.get('input', '') or ''), timeout=timeout) except (TimeoutError, subprocess.TimeoutExpired): proc.kill() try: outs, errs = proc.communicate(timeout=1) except: resp_data[key] = { 'error': f"Command '{cmd}' timed out after {timeout} seconds. Unable to communicate with the process launched." } else: resp_data[key] = { 'error': f"Command '{cmd}' timed out after {timeout} seconds", 'stdout': outs.split('\n'), 'stderr': errs.split('\n') } except Exception as e: current_app.logger.exception( "Exception raised while trying to run command") resp_data[key] = { 'error': traceback.format_exc() if current_app.config['DEBUG'] else str(r.exception) or str(r.exception.__class__.__name__) } else: resp_data[key] = { 'stdout': outs.split('\n'), 'stderr': errs.split('\n'), 'returncode': proc.returncode } resp_data['cmd'] = cmd resp_data['input'] = data.get('input', None) return resp_data, 200
def launch_orchestration(orchestration_id): data = request.get_json() if orchestration_id: orchestration = Orchestration.query.get_or_raise(orchestration_id) else: iden = (data.get('orchestration'), ) columns = ('orchestration', ) query = Orchestration.query.filter_by(name=data.get('orchestration')) if 'version' in data: iden += (data.get('version'), ) columns += ('version', ) query = query.filter_by(version=data.get('version')) query = query.order_by(Orchestration.version.desc()) if query.count() <= 1: orchestration = query.one_or_none() else: orchestration = query.first() if not orchestration: raise errors.EntityNotFound('Orchestration', iden, columns) if not orchestration.steps: return errors.GenericError( 'orchestration does not have steps to execute', orchestration_id=orchestration_id) params = data.get('params') or {} hosts = data.get('hosts', Server.get_current().id) a = set(orchestration.target) if not isinstance(hosts, dict): hosts = dict(all=hosts) b = set(hosts.keys()) c = a - b if len(c) > 0: raise errors.TargetUnspecified(c) c = b - a if len(c) > 0: raise errors.TargetNotNeeded(c) not_found = normalize_hosts(hosts) if not_found: raise errors.ServerNormalizationError(not_found) for target, target_hosts in hosts.items(): if len(target_hosts) == 0: raise errors.EmptyTarget(target) # check param entries # rest = orchestration.user_parameters - set(params.keys()) # if rest: # rest = list(rest) # rest.sort() # return {'error': f"Parameter(s) not specified: {', '.join(rest)}"}, 404 execution_id = str(uuid.uuid4()) executor_id = get_jwt_identity() vc = Context(params, dict(execution_id=None, root_orch_execution_id=execution_id, orch_execution_id=execution_id, executor_id=executor_id), vault=Vault.get_variables_from(executor_id, scope=data.get( 'scope', 'global'))) if not data.get('skip_validation', False): validate_input_chain( orchestration, { 'input': set(params.keys()), 'env': set(vc.env.keys()), 'vault': set(vc.vault.keys()) }) if request.get_json().get('background', True): future = executor.submit(deploy_orchestration, orchestration=orchestration.id, var_context=vc, hosts=hosts, timeout=data.get('timeout', None)) try: future.result(5) except concurrent.futures.TimeoutError: return {'execution_id': execution_id}, 202 except Exception as e: current_app.logger.exception( f"Exception got when executing orchestration {orchestration}") raise else: try: deploy_orchestration(orchestration=orchestration, var_context=vc, hosts=hosts, timeout=data.get('timeout', None)) except Exception as e: current_app.logger.exception( f"Exception got when executing orchestration {orchestration}") raise return OrchExecution.query.get(execution_id).to_json( add_step_exec=True, human=check_param_in_uri('human'), split_lines=True), 200