def prepare_two_workdirs(deployment_id: str, blueprint_id: str, version_id: str, inputs: dict, location: Path = None): location_old = InvocationService.deployment_location( str(uuid.uuid4()), str(uuid.uuid4())) location_new = location or InvocationService.deployment_location( str(uuid.uuid4()), str(uuid.uuid4())) # old Deployed instance # TODO Next line should use PostgreSQL.get_deployment_status(deployment_id), had to be changed since # old blueprint_id is part of second to last invocation, last is already current inv_old = PostgreSQL.get_last_completed_invocation(deployment_id) CSAR_db.get_revision(inv_old.blueprint_id, location_old, inv_old.version_id) InvocationService.get_dot_opera_from_db(deployment_id, location_old) storage_old = Storage.create(str(location_old / '.opera')) # new blueprint CSAR_db.get_revision(blueprint_id, location_new, version_id) storage_new = Storage.create(str(location_new / '.opera')) storage_new.write_json(inputs or {}, "inputs") storage_new.write(str(entry_definitions(location_new)), "root_file") return storage_old, location_old, storage_new, location_new
def _undeploy(location: Path, inv: ExtendedInvocation): # get blueprint CSAR_db.get_revision(inv.blueprint_id, location, inv.version_id) # get session data (.opera) if not InvocationService.get_dot_opera_from_db(inv.deployment_id, location): raise MissingDeploymentDataError( 'Could not get .opera data from previous job, aborting...') with xopera_util.cwd(location): try: if inv.user_id and Settings.secure_workdir: xopera_util.setup_user([location], inv.user_id, inv.access_token) opera_storage = Storage.create(".opera") if inv.inputs: opera_storage.write_json(inv.inputs, "inputs") opera_undeploy(opera_storage, verbose_mode=False, num_workers=inv.workers) # Outputs in undeployment are not returned return None finally: if inv.user_id and Settings.secure_workdir: xopera_util.cleanup_user()
def _deploy_continue(location: Path, inv: ExtendedInvocation): # get blueprint CSAR_db.get_revision(inv.blueprint_id, location, inv.version_id) # get session data (.opera) InvocationService.get_dot_opera_from_db(inv.deployment_id, location) with xopera_util.cwd(location): try: if inv.user_id and Settings.secure_workdir: xopera_util.setup_user([location], inv.user_id, inv.access_token) opera_storage = Storage.create(".opera") service_template = entry_definitions(location) opera_deploy(service_template, inv.inputs, opera_storage, verbose_mode=False, num_workers=inv.workers, delete_existing_state=inv.clean_state) outputs = opera_outputs(opera_storage) return outputs finally: if inv.user_id and Settings.secure_workdir: xopera_util.cleanup_user()
def validate(blueprint_id: str, version_tag: str, inputs: dict): with tempfile.TemporaryDirectory() as location: CSAR_db.get_revision(blueprint_id, location, version_tag) try: with xopera_util.cwd(location): opera_storage = Storage.create(".opera") service_template = Path(location) / entry_definitions( location) opera_validate(service_template, inputs, opera_storage, verbose=False, executors=False) return None except Exception as e: return "{}: {}".format( e.__class__.__name__, xopera_util.mask_workdir(location, str(e)))
def delete_blueprint_version(blueprint_id, version_id, force=None): """Delete version of blueprint. :param blueprint_id: Id of blueprint :type blueprint_id: :param version_id: Id of blueprint version :type version_id: str :param force: force delete blueprint :type force: bool :rtype: Blueprint """ if not force: if PostgreSQL.blueprint_used_in_deployment(blueprint_id, version_id): return "Cannot delete blueprint, deployment with this blueprint exists", 403 repo_url, _ = CSAR_db.get_repo_url(blueprint_id) rows_affected, status_code = CSAR_db.delete_blueprint( blueprint_id, version_id) logger.debug(f"Rows affected, status_code: {rows_affected} {status_code}") if status_code == 200: PostgreSQL.delete_blueprint_meta(blueprint_id, version_id) PostgreSQL.save_git_transaction_data( blueprint_id=blueprint_id, version_id=version_id, revision_msg=f"Deleted a version of blueprint", job='delete', git_backend=str(CSAR_db.connection.git_connector), repo_url=repo_url) return BlueprintVersion( blueprint_id=blueprint_id, version_id=version_id, url=repo_url, timestamp=timestamp_util.datetime_now_to_string()), 200 message = { 200: 'Successfully removed', 404: 'Blueprint version or blueprint not found', 500: 'Server error' } return message[status_code], status_code
def prepare_location(cls, deployment_id: uuid, location: Path): """ Prepare location with blueprint and session_data (.opera dir) """ inv = PostgreSQL.get_deployment_status(deployment_id) if not CSAR_db.get_revision(inv.blueprint_id, location, inv.version_tag): logger.error( f'csardb_service.get_revision failed: blueprint_id: {inv.blueprint_id}, ' f'location: {location}, version_d: {inv.version_id}') InvocationService.get_dot_opera_from_db(deployment_id, location)
def post_new_blueprint(revision_msg=None, blueprint_name=None, aadm_id=None, username=None, project_domain=None): # noqa: E501 """Add new blueprint. :param revision_msg: Optional comment on submission :type revision_msg: str :param blueprint_name: Optional human-readable blueprint name :type blueprint_name: str :param aadm_id: End-to-end debugging id :type aadm_id: str :param username: End-to-end debugging id :type username: str :param project_domain: Optional project domain this blueprint belongs to :type project_domain: str :rtype: Blueprint """ # check roles if project_domain and not security_controller.check_roles(project_domain): return f"Unauthorized request for project: {project_domain}", 401 file = connexion.request.files['CSAR'] result, response = CSAR_db.add_revision(CSAR=file, revision_msg=revision_msg) if result is None: return f"Invalid CSAR: {response}", 406 blueprint_meta = BlueprintVersion.from_dict(result) blueprint_meta.blueprint_name = blueprint_name blueprint_meta.project_domain = project_domain blueprint_meta.aadm_id = aadm_id blueprint_meta.username = username if not PostgreSQL.save_blueprint_meta(blueprint_meta): blueprint_id = blueprint_meta.blueprint_id return f"Failed to save project data for blueprint_id={blueprint_id}", 500 PostgreSQL.save_git_transaction_data( blueprint_id=result['blueprint_id'], version_id=result['version_id'], revision_msg=f"Saved new blueprint: {revision_msg}", job='update', git_backend=str(CSAR_db.connection.git_connector), repo_url=result['url'], commit_sha=result['commit_sha']) return blueprint_meta, 201
def get_git_user(blueprint_id): """List users with access. :param blueprint_id: Id of blueprint :type blueprint_id: :rtype: List[str] """ user_list, error_msg = CSAR_db.get_blueprint_user_list(blueprint_id) if user_list is not None: return user_list, 200 return f"Could not retrieve list of users for repository with blueprint_id '{blueprint_id}': {error_msg}", 500
def wrapper_check_role_auth(*args, **kwargs): blueprint_id = kwargs.get("blueprint_id") if not blueprint_id: return f"Authorization configuration error", 401 version_id = kwargs.get("version_id") if not PostgreSQL.version_exists(blueprint_id, version_id) and not CSAR_db.version_exists(blueprint_id, version_id): return f"Did not find blueprint with id: {blueprint_id} and version_id: {version_id or 'any'}", 404 project_domain = PostgreSQL.get_project_domain(blueprint_id) if project_domain and not check_roles(project_domain): return f"Unauthorized request for project: {project_domain}", 401 return func(*args, **kwargs)
def delete_git_user(blueprint_id, user_id): """Delete user. :param blueprint_id: Id of blueprint :type blueprint_id: :param user_id: user_id to be removed from repository with blueprint :type user_id: str :rtype: str """ success, error_msg = CSAR_db.delete_blueprint_user( blueprint_id=blueprint_id, username=user_id) if success: return f"User {user_id} deleted", 200 return f"Could not delete user {user_id} from repository with blueprint_id '{blueprint_id}': {error_msg}", 500
def wrapper_check_role_auth(*args, **kwargs): deployment_id = kwargs.get("deployment_id") if not deployment_id: return f"Authorization configuration error", 401 inv = PostgreSQL.get_deployment_status(deployment_id) if not inv: return f"Deployment with id: {deployment_id} does not exist", 404 if not PostgreSQL.version_exists(inv.blueprint_id, inv.version_id) and not CSAR_db.version_exists( inv.blueprint_id, inv.version_id): return f"Did not find blueprint with id: {inv.blueprint_id} and version_id: {inv.version_id or 'any'}", 404 project_domain = PostgreSQL.get_project_domain(inv.blueprint_id) if project_domain and not check_roles(project_domain): return f"Unauthorized request for project: {project_domain}", 401 return func(*args, **kwargs)
def invoke(self, operation_type: OperationType, blueprint_id: uuid, version_id: uuid, workers: int, inputs: dict, deployment_id: uuid = None, username: str = None, clean_state: bool = None, deployment_label: str = None, access_token: str = None) -> Invocation: now = datetime.datetime.now(tz=datetime.timezone.utc) logger.info("Invoking %s with ID %s at %s", operation_type, deployment_id, now.isoformat()) invocation_id = uuid.uuid4() inv = ExtendedInvocation() inv.blueprint_id = blueprint_id inv.deployment_label = deployment_label inv.version_id = version_id or CSAR_db.get_last_tag(blueprint_id) inv.deployment_id = deployment_id or uuid.uuid4() inv.state = InvocationState.PENDING inv.operation = operation_type inv.timestamp_submission = now.isoformat() inv.inputs = inputs inv.instance_state = None inv.outputs = None inv.exception = None inv.stdout = None inv.stderr = None inv.workers = workers inv.clean_state = clean_state inv.user_id = username inv.access_token = access_token self.stdstream_dir(inv.deployment_id).mkdir(parents=True, exist_ok=True) self.save_invocation(invocation_id, inv) self.work_queue.put(inv) return inv
def post_blueprint(blueprint_id, revision_msg=None): """Add new version to existing blueprint. :param blueprint_id: Id of blueprint :type blueprint_id: :param revision_msg: Optional comment on submission :type revision_msg: str :rtype: Blueprint """ file = connexion.request.files['CSAR'] result, response = CSAR_db.add_revision(CSAR=file, revision_msg=revision_msg, blueprint_id=blueprint_id) if result is None: return f"Invalid CSAR: {response}", 406 blueprint_meta = BlueprintVersion.from_dict(result) # copy blueprint params from first revision blueprint_meta_old = BlueprintVersion.from_dict( PostgreSQL.get_blueprint_meta(blueprint_id, 'v1.0')) blueprint_meta.blueprint_name = blueprint_meta_old.blueprint_name blueprint_meta.project_domain = blueprint_meta_old.project_domain blueprint_meta.aadm_id = blueprint_meta_old.aadm_id blueprint_meta.username = blueprint_meta_old.username if not PostgreSQL.save_blueprint_meta(blueprint_meta): return f"Failed to save project data for blueprint_id={blueprint_id}", 500 PostgreSQL.save_git_transaction_data( blueprint_id=result['blueprint_id'], version_id=result['version_id'], revision_msg=f"Updated blueprint: {revision_msg}", job='update', git_backend=str(CSAR_db.connection.git_connector), repo_url=result['url'], commit_sha=result['commit_sha']) return blueprint_meta, 201
def post_git_user(blueprint_id, user_id): """Add user to blueprint. :param blueprint_id: Id of blueprint :type blueprint_id: :param user_id: Username to be added to repository with blueprint :type user_id: str :rtype: str """ success, error_msg = CSAR_db.add_member_to_blueprint( blueprint_id=blueprint_id, username=user_id) if success: message = { 'github': f"Invite for user {user_id} sent", 'gitlab': f"User {user_id} added", 'mock': f"User {user_id} added" } return message[Settings.git_config['type']], 200 return f"Could not add user {user_id} to repository with blueprint_id '{blueprint_id}': {error_msg}", 500