def test_successful_plugin_import_resolver(self): self.upload_plugin(TEST_PACKAGE_NAME, TEST_PACKAGE_VERSION, TEST_PACKAGE_YAML_FILE) dsl_location = os.path.join(self.get_blueprint_path('mock_blueprint'), 'blueprint_with_plugin_import.yaml') tasks.parse_dsl(dsl_location=dsl_location, resources_base_path=self.tmpdir, resolver=self.resolver)
def test_successful_plugin_import_resolver(self): self.upload_plugin(TEST_PACKAGE_NAME, TEST_PACKAGE_VERSION, TEST_PACKAGE_YAML_FILE) dsl_location = os.path.join( self.get_blueprint_path('mock_blueprint'), 'blueprint_with_plugin_import.yaml') tasks.parse_dsl(dsl_location=dsl_location, resources_base_path=self.tmpdir, resolver=self.resolver)
def publish_blueprint(self, dsl_location, alias_mapping_url, resources_base_url, blueprint_id): # TODO: error code if parsing fails (in one of the 2 tasks) try: plan = tasks.parse_dsl(dsl_location, alias_mapping_url, resources_base_url) except Exception, ex: raise DslParseException(*ex.args)
def publish_blueprint(self, application_dir, application_file_name, resources_base, blueprint_id): application_file = os.path.join(application_dir, application_file_name) dsl_location = '{0}{1}'.format(resources_base, application_file) try: plan = tasks.parse_dsl(dsl_location, resources_base, **self._get_parser_context()) except Exception, ex: raise DslParseException(str(ex))
def publish_blueprint(self, dsl_location, alias_mapping_url, resources_base_url, blueprint_id=None): # TODO: error code if parsing fails (in one of the 2 tasks) try: plan = tasks.parse_dsl(dsl_location, alias_mapping_url, resources_base_url) with contextlib.closing(urlopen(dsl_location)) as f: source = f.read() except Exception, ex: raise DslParseException(*ex.args)
def stage_deployment_update(self, deployment_id, app_dir, app_blueprint, additional_inputs): """Stage a deployment update :param app_blueprint: :param app_dir: :param deployment_id: the deployment id for the update :return: """ # enables reverting to original blueprint resources deployment = self.sm.get(models.Deployment, deployment_id) blueprint_id = deployment.blueprint_id file_server_root = config.instance.file_server_root blueprint_resource_dir = os.path.join( file_server_root, 'blueprints', current_app.config[CURRENT_TENANT_CONFIG].name, blueprint_id) # The dsl parser expects a URL blueprint_resource_dir_url = 'file:{0}'.format(blueprint_resource_dir) app_path = os.path.join(file_server_root, app_dir, app_blueprint) # parsing the blueprint from here try: plan = tasks.parse_dsl( app_path, resources_base_path=file_server_root, additional_resources=[blueprint_resource_dir_url], **app_context.get_parser_context()) except parser_exceptions.DSLParsingException as ex: raise manager_exceptions.InvalidBlueprintError( 'Invalid blueprint - {0}'.format(ex)) # Updating the new inputs with the deployment inputs # (overriding old values and adding new ones) inputs = copy.deepcopy(deployment.inputs) inputs.update(additional_inputs) # applying intrinsic functions try: prepared_plan = tasks.prepare_deployment_plan(plan, get_secret_method(), inputs=inputs) except parser_exceptions.MissingRequiredInputError, e: raise manager_exceptions.MissingRequiredDeploymentInputError( str(e))
def publish_blueprint(self, application_dir, application_file_name, resources_base, blueprint_id): application_file = os.path.join(application_dir, application_file_name) dsl_location = '{0}{1}'.format(resources_base, application_file) try: plan = tasks.parse_dsl( dsl_location, resources_base, **self._get_parser_context()) except Exception, ex: raise DslParseException(str(ex))
def stage_deployment_update(self, deployment_id, app_dir, app_blueprint, additional_inputs, new_blueprint_id=None, preview=False, runtime_only_evaluation=False): # enables reverting to original blueprint resources deployment = self.sm.get(models.Deployment, deployment_id) old_blueprint = deployment.blueprint file_server_root = config.instance.file_server_root blueprint_resource_dir = os.path.join(file_server_root, 'blueprints', old_blueprint.tenant_name, old_blueprint.id) runtime_only_evaluation = runtime_only_evaluation or \ deployment.runtime_only_evaluation # The dsl parser expects a URL blueprint_resource_dir_url = 'file:{0}'.format(blueprint_resource_dir) app_path = os.path.join(file_server_root, app_dir, app_blueprint) # parsing the blueprint from here try: plan = tasks.parse_dsl( app_path, resources_base_path=file_server_root, additional_resources=[blueprint_resource_dir_url], **app_context.get_parser_context()) except parser_exceptions.DSLParsingException as ex: raise manager_exceptions.InvalidBlueprintError( 'Invalid blueprint - {0}'.format(ex)) # Updating the new inputs with the deployment inputs # (overriding old values and adding new ones) old_inputs = copy.deepcopy(deployment.inputs) new_inputs = { k: old_inputs[k] for k in plan.inputs.keys() if k in old_inputs } new_inputs.update(additional_inputs) # applying intrinsic functions try: prepared_plan = tasks.prepare_deployment_plan( plan, get_secret_method, inputs=new_inputs, runtime_only_evaluation=runtime_only_evaluation) except parser_exceptions.MissingRequiredInputError, e: raise manager_exceptions.MissingRequiredDeploymentInputError( str(e))
def test_success_with_blueprint_import_resolver(self): blueprint_id = 'imported_blueprint' self.put_blueprint('mock_blueprint', 'blueprint.yaml', blueprint_id) dsl_location = os.path.join(self.get_blueprint_path('mock_blueprint'), 'blueprint_with_blueprint_import.yaml') plan = tasks.parse_dsl(dsl_location=dsl_location, resources_base_path=self.tmpdir, resolver=self.resolver) nodes = {node["name"] for node in plan[constants.NODES]} self.assertEqual(nodes, {"test", "vm", "http_web_server"})
def stage_deployment_update(self, deployment_id, app_dir, app_blueprint, additional_inputs): """Stage a deployment update :param app_blueprint: :param app_dir: :param deployment_id: the deployment id for the update :return: """ # enables reverting to original blueprint resources deployment = self.sm.get_deployment(deployment_id) blueprint_id = deployment.blueprint_id # enables reverting to original blueprint resources file_server_base_url = \ '{0}/'.format(config.instance().file_server_base_uri) blueprint_resource_dir = os.path.join(file_server_base_url, 'blueprints', blueprint_id) app_path = os.path.join(file_server_base_url, app_dir, app_blueprint) # parsing the blueprint from here try: plan = tasks.parse_dsl( app_path, resources_base_url=file_server_base_url, additional_resources=[blueprint_resource_dir], **app_context.get_parser_context()) except parser_exceptions.DSLParsingException as ex: raise manager_exceptions.InvalidBlueprintError( 'Invalid blueprint - {0}'.format(ex)) # Updating the new inputs with the deployment inputs # (overriding old values and adding new ones) inputs = copy.deepcopy(deployment.inputs) inputs.update(additional_inputs) # applying intrinsic functions try: prepared_plan = tasks.prepare_deployment_plan(plan, inputs=inputs) except parser_exceptions.MissingRequiredInputError, e: raise manager_exceptions.MissingRequiredDeploymentInputError( str(e))
def test_success_with_blueprint_import_resolver(self): blueprint_id = 'imported_blueprint' self.put_blueprint('mock_blueprint', 'blueprint.yaml', blueprint_id) dsl_location = os.path.join( self.get_blueprint_path('mock_blueprint'), 'blueprint_with_blueprint_import.yaml') plan = tasks.parse_dsl(dsl_location=dsl_location, resources_base_path=self.tmpdir, resolver=self.resolver) nodes = {node["name"] for node in plan[constants.NODES]} self.assertEqual(nodes, {"test", "ns--vm", "ns--http_web_server"})
def get_parsed_deployment(blueprint, app_dir, app_blueprint): file_server_root = config.instance.file_server_root blueprint_resource_dir = os.path.join(file_server_root, 'blueprints', blueprint.tenant_name, blueprint.id) # The dsl parser expects a URL blueprint_resource_dir_url = 'file:{0}'.format(blueprint_resource_dir) app_path = os.path.join(file_server_root, app_dir, app_blueprint) try: return tasks.parse_dsl( app_path, resources_base_path=file_server_root, additional_resources=[blueprint_resource_dir_url], **app_context.get_parser_context()) except parser_exceptions.DSLParsingException as ex: raise manager_exceptions.InvalidBlueprintError( 'Invalid blueprint - {0}'.format(ex))
def stage_deployment_update(self, deployment_id, app_dir, app_blueprint, additional_inputs, new_blueprint_id=None, preview=False): # enables reverting to original blueprint resources deployment = self.sm.get(models.Deployment, deployment_id) old_blueprint = deployment.blueprint file_server_root = config.instance.file_server_root blueprint_resource_dir = os.path.join(file_server_root, 'blueprints', old_blueprint.tenant_name, old_blueprint.id) # The dsl parser expects a URL blueprint_resource_dir_url = 'file:{0}'.format(blueprint_resource_dir) app_path = os.path.join(file_server_root, app_dir, app_blueprint) # parsing the blueprint from here try: plan = tasks.parse_dsl( app_path, resources_base_path=file_server_root, additional_resources=[blueprint_resource_dir_url], **app_context.get_parser_context() ) except parser_exceptions.DSLParsingException as ex: raise manager_exceptions.InvalidBlueprintError( 'Invalid blueprint - {0}'.format(ex)) # Updating the new inputs with the deployment inputs # (overriding old values and adding new ones) old_inputs = copy.deepcopy(deployment.inputs) new_inputs = {k: old_inputs[k] for k in plan.inputs.keys() if k in old_inputs} new_inputs.update(additional_inputs) # applying intrinsic functions try: prepared_plan = tasks.prepare_deployment_plan(plan, get_secret_method(), inputs=new_inputs) except parser_exceptions.MissingRequiredInputError, e: raise manager_exceptions.MissingRequiredDeploymentInputError( str(e))
def stage_deployment_update(self, deployment_id, app_dir, app_blueprint, additional_inputs): """Stage a deployment update :param app_blueprint: :param app_dir: :param deployment_id: the deployment id for the update :return: """ # enables reverting to original blueprint resources deployment = self.sm.get_deployment(deployment_id) blueprint_id = deployment.blueprint_id # enables reverting to original blueprint resources file_server_base_url = \ '{0}/'.format(config.instance.file_server_base_uri) blueprint_resource_dir = os.path.join(file_server_base_url, 'blueprints', blueprint_id) app_path = os.path.join(file_server_base_url, app_dir, app_blueprint) # parsing the blueprint from here try: plan = tasks.parse_dsl( app_path, resources_base_url=file_server_base_url, additional_resources=[blueprint_resource_dir], **app_context.get_parser_context()) except parser_exceptions.DSLParsingException as ex: raise manager_exceptions.InvalidBlueprintError( 'Invalid blueprint - {0}'.format(ex)) # Updating the new inputs with the deployment inputs # (overriding old values and adding new ones) inputs = copy.deepcopy(deployment.inputs) inputs.update(additional_inputs) # applying intrinsic functions try: prepared_plan = tasks.prepare_deployment_plan(plan, inputs=inputs) except parser_exceptions.MissingRequiredInputError, e: raise manager_exceptions.MissingRequiredDeploymentInputError( str(e))
def upload(ctx, **kwargs): client = get_rest_client() # extract the execution parameters blueprint_id = kwargs['blueprint_id'] app_file_name = kwargs['app_file_name'] url = kwargs['url'] file_server_root = kwargs['file_server_root'] validate_only = kwargs['validate_only'] labels = kwargs.get('labels') # Download the archive, one way or the other archive_target_path = tempfile.mkdtemp() try: if url: # download the blueprint archive from URL using requests: if not validate_only: client.blueprints.update( blueprint_id, update_dict={'state': BlueprintUploadState.UPLOADING}) with requests.get(url, stream=True, timeout=(5, None)) as resp: resp.raise_for_status() archive_file_path = os.path.join(archive_target_path, os.path.basename(url)) with open(archive_file_path, 'wb') as f: for chunk in resp.iter_content(chunk_size=8192): if chunk: f.write(chunk) # Upload the downloaded archive to the manager if not validate_only: client.blueprints.upload_archive( blueprint_id, archive_path=archive_file_path) else: # download the blueprint archive using REST archive_file_path = client.blueprints.download( blueprint_id, output_file=archive_target_path) except Exception as e: client.blueprints.update(blueprint_id, update_dict={ 'state': BlueprintUploadState.FAILED_UPLOADING, 'error': str(e), 'error_traceback': traceback.format_exc() }) remove(archive_target_path) raise ctx.logger.info('Blueprint archive uploaded. Extracting...') # Extract the archive so we can parse it if not validate_only: client.blueprints.update( blueprint_id, update_dict={'state': BlueprintUploadState.EXTRACTING}) try: archive_util.unpack_archive(archive_file_path, archive_target_path) except archive_util.UnrecognizedFormat: error_msg = 'Blueprint archive is of an unrecognized format. ' \ 'Supported formats are: ' \ '{0}'.format(SUPPORTED_ARCHIVE_TYPES) handle_failed_extracting(ctx, client, blueprint_id, error_msg, archive_target_path) except Exception as e: handle_failed_extracting(ctx, client, blueprint_id, str(e), archive_target_path) archive_file_list = os.listdir(archive_target_path) # ignore the archive file for now archive_file_list.remove(os.path.basename(archive_file_path)) # the other item in the archive dir is the extracted app, which is # supposed to consist of one folder in a properly-structured archive app_dir = os.path.join(archive_target_path, archive_file_list[0]) if len(archive_file_list) != 1 or not os.path.isdir(app_dir): error_msg = 'Archive must contain exactly 1 directory' handle_failed_extracting(ctx, client, blueprint_id, error_msg, archive_target_path) # get actual app file name if app_file_name: app_file_name = unquote(app_file_name) application_file = os.path.join(app_dir, app_file_name) if not os.path.isfile(application_file): error_msg = '{0} does not exist in the application ' \ 'directory'.format(app_file_name) handle_failed_extracting(ctx, client, blueprint_id, error_msg, archive_target_path) else: app_file_name = CONVENTION_APPLICATION_BLUEPRINT_FILE application_file = os.path.join(app_dir, app_file_name) if not os.path.isfile(application_file): error_msg = 'Application directory is missing blueprint.yaml and' \ ' application_file_name query parameter was not passed' handle_failed_extracting(ctx, client, blueprint_id, error_msg, archive_target_path) ctx.logger.info('Blueprint archive extracted. Parsing...') # Parse plan if not validate_only: client.blueprints.update( blueprint_id, update_dict={'state': BlueprintUploadState.PARSING}) dsl_location = os.path.join(app_dir, app_file_name) provider_context = client.manager.get_context()['context'] try: parser_context = extract_parser_context(provider_context, resolver_parameters={ 'file_server_root': file_server_root, 'client': client }) except dsl_parser_utils.ResolverInstantiationError as e: ctx.logger.critical(str(e)) client.blueprints.update(blueprint_id, update_dict={ 'state': BlueprintUploadState.FAILED_PARSING, 'error': str(e), 'error_traceback': traceback.format_exc() }) raise try: plan = tasks.parse_dsl(dsl_location, file_server_root, **parser_context) except (InvalidBlueprintImport, DSLParsingException) as e: error_msg = 'Invalid blueprint - {}'.format(e) ctx.logger.critical(error_msg) client.blueprints.update(blueprint_id, update_dict={ 'state': BlueprintUploadState.INVALID, 'error': error_msg, 'error_traceback': traceback.format_exc() }) raise except Exception as e: error_msg = 'Failed parsing blueprint - {}'.format(e) ctx.logger.critical(error_msg) client.blueprints.update(blueprint_id, update_dict={ 'state': BlueprintUploadState.FAILED_PARSING, 'error': error_msg, 'error_traceback': traceback.format_exc() }) raise finally: remove(archive_target_path) if validate_only: ctx.logger.info('Blueprint validated.') else: ctx.logger.info('Blueprint parsed. Updating DB with blueprint plan.') # Update DB with parsed plan update_dict = { 'plan': plan, 'main_file_name': app_file_name, 'state': BlueprintUploadState.UPLOADED, } if plan.get('description'): update_dict['description'] = plan['description'] if labels: update_dict['labels'] = labels client.blueprints.update(blueprint_id, update_dict=update_dict)
def publish_blueprint(self, dsl_location, resources_base_url, blueprint_id): try: plan = tasks.parse_dsl(dsl_location, resources_base_url) except Exception, ex: raise DslParseException(str(ex))