def _decompile_bp(bp_payload, with_secrets=False, prefix="", bp_dir=None): """decompiles the blueprint from payload""" blueprint = bp_payload["spec"]["resources"] blueprint_name = bp_payload["spec"].get("name", "DslBlueprint") blueprint_description = bp_payload["spec"].get("description", "") blueprint_metadata = bp_payload["metadata"] # POP unnecessary keys blueprint_metadata.pop("creation_time", None) blueprint_metadata.pop("last_update_time", None) metadata_obj = MetadataType.decompile(blueprint_metadata) # Copying dsl_name_map to global client_attrs if bp_payload["spec"]["resources"]["client_attrs"].get("None", {}): init_dsl_metadata_map(bp_payload["spec"]["resources"]["client_attrs"]["None"]) LOG.info("Decompiling blueprint {}".format(blueprint_name)) for sub_obj in blueprint.get("substrate_definition_list"): sub_type = sub_obj.get("type", "") or "AHV_VM" if sub_type == "K8S_POD": raise NotImplementedError( "Decompilation for k8s pod is not supported right now" ) elif sub_type != "AHV_VM": LOG.warning( "Decompilation support for providers other than AHV is experimental." ) break prefix = get_valid_identifier(prefix) bp_cls = BlueprintType.decompile(blueprint, prefix=prefix) bp_cls.__name__ = get_valid_identifier(blueprint_name) bp_cls.__doc__ = blueprint_description create_bp_dir( bp_cls=bp_cls, with_secrets=with_secrets, metadata_obj=metadata_obj, bp_dir=bp_dir, ) click.echo( "\nSuccessfully decompiled. Directory location: {}. Blueprint location: {}".format( get_bp_dir(), os.path.join(get_bp_dir(), "blueprint.py") ) )
def _decompile_bp(bp_payload, with_secrets=False): """decompiles the blueprint from payload""" blueprint = bp_payload["spec"]["resources"] blueprint_name = bp_payload["spec"].get("name", "DslBlueprint") blueprint_description = bp_payload["spec"].get("description", "") # Copying dsl_name_map to global client_attrs if bp_payload["spec"]["resources"]["client_attrs"].get("None", {}): init_dsl_metadata_map(bp_payload["spec"]["resources"]["client_attrs"]["None"]) LOG.info("Decompiling blueprint {}".format(blueprint_name)) for sub_obj in blueprint.get("substrate_definition_list"): sub_type = sub_obj.get("type", "") or "AHV_VM" if sub_type == "K8S_POD": raise NotImplementedError( "Decompilation for k8s pod is not supported right now" ) elif sub_type != "AHV_VM": LOG.warning( "Decompilation support for providers other than AHV is experimental/best effort" ) break bp_cls = BlueprintType.decompile(blueprint) bp_cls.__name__ = get_valid_identifier(blueprint_name) bp_cls.__doc__ = blueprint_description create_bp_dir(bp_cls=bp_cls, with_secrets=with_secrets) click.echo("\nSuccessfully decompiled. Directory location: {}".format(get_bp_dir()))
def render_credential_template(cls): global CRED_VAR_NAME_MAP, CRED_FILES LOG.debug("Rendering {} credential template".format(cls.__name__)) if not isinstance(cls, CredentialType): raise TypeError("{} is not of type {}".format(cls, CredentialType)) user_attrs = cls.get_user_attrs() user_attrs["description"] = cls.__doc__ var_name = "BP_CRED_{}".format(get_valid_identifier(cls.__name__)) file_name = "{}_{}".format(var_name, user_attrs["type"]) file_loc = os.path.join(get_local_dir(), file_name) # Storing empty value in the file with open(file_loc, "w+") as fd: fd.write("") user_attrs["var_name"] = var_name user_attrs["value"] = file_name if user_attrs.get("editables", {}): user_attrs["editables"] = user_attrs["editables"].get_dict() # update the map CRED_VAR_NAME_MAP[user_attrs["name"]] = var_name CRED_FILES.append(file_name) text = render_template("credential.py.jinja2", obj=user_attrs) return text.strip()
def get_provider_spec_string(spec, filename, provider_type, vm_images): # TODO add switch to use YAML_file/Helper_class for ahv provider dsl_file_location_alias = "os.path.join('{}', '{}')".format( get_specs_dir_key(), filename) if provider_type == "AHV_VM": disk_list = spec["resources"]["disk_list"] disk_ind_img_map = {} for ind, disk in enumerate(disk_list): data_source_ref = disk.get("data_source_reference", {}) if data_source_ref: if data_source_ref.get("kind") == "app_package": disk_ind_img_map[ind + 1] = get_valid_identifier( data_source_ref.get("name")) data_source_ref.pop("uuid", None) disk_pkg_string = "" for k, v in disk_ind_img_map.items(): disk_pkg_string += ",{}: {}".format(k, v) if disk_pkg_string.startswith(","): disk_pkg_string = disk_pkg_string[1:] disk_pkg_string = "{" + disk_pkg_string + "}" res = "read_ahv_spec({}, disk_packages = {})".format( dsl_file_location_alias, disk_pkg_string) elif provider_type == "VMWARE_VM": spec_template = get_valid_identifier(spec["template"]) if spec_template in vm_images: spec["template"] = "" res = "read_vmw_spec({}, vm_template={})".format( dsl_file_location_alias, spec_template) else: res = "read_vmw_spec({})".format(dsl_file_location_alias) else: res = "read_provider_spec({})".format(dsl_file_location_alias) return res
def decompile_marketplace_bp(name, version, app_source, bp_name, project, with_secrets, bp_dir): """decompiles marketplace blueprint""" if not version: LOG.info("Fetching latest version of Marketplace Blueprint {} ".format( name)) version = get_mpi_latest_version(name=name, app_source=app_source) LOG.info(version) LOG.info("Converting MPI into blueprint") bp_payload = convert_mpi_into_blueprint(name=name, version=version, project_name=project, app_source=app_source) del bp_payload["status"] client = get_api_client() blueprint_uuid = bp_payload["metadata"]["uuid"] res, err = client.blueprint.export_file(blueprint_uuid) if err: LOG.error("[{}] - {}".format(err["code"], err["error"])) sys.exit(-1) bp_payload = res.json() blueprint = bp_payload["spec"]["resources"] blueprint_name = get_valid_identifier(bp_name or name) if not bp_dir: bp_dir_suffix = bp_name or "mpi_bp_{}_v{}".format( blueprint_name, version) bp_dir = os.path.join(os.getcwd(), bp_dir_suffix) blueprint_description = bp_payload["spec"].get("description", "") LOG.info("Decompiling marketplace blueprint {}".format(name)) for sub_obj in blueprint.get("substrate_definition_list"): sub_type = sub_obj.get("type", "") or "AHV_VM" if sub_type == "K8S_POD": raise NotImplementedError( "Decompilation for k8s pod is not supported right now") elif sub_type != "AHV_VM": LOG.warning( "Decompilation support for providers other than AHV is experimental." ) break bp_cls = BlueprintType.decompile(blueprint) bp_cls.__name__ = blueprint_name bp_cls.__doc__ = blueprint_description create_bp_dir(bp_cls=bp_cls, bp_dir=bp_dir, with_secrets=with_secrets) click.echo( "\nSuccessfully decompiled. Directory location: {}. Blueprint location: {}" .format(get_bp_dir(), os.path.join(get_bp_dir(), "blueprint.py")))
def render_restore_config_template(cls, entity_context): LOG.debug("Rendering {} restore config template".format(cls.__name__)) if not isinstance(cls, ConfigSpecType): raise TypeError("{} is not of type {}".format(cls, ConfigSpecType)) _user_attrs = cls.get_user_attrs() user_attrs = dict() user_attrs["name"] = _user_attrs["name"] or cls.__name__ attrs = _user_attrs["attrs_list"][0] user_attrs["target"] = get_valid_identifier( attrs["target_any_local_reference"]["name"] ) user_attrs["delete_vm_post_restore"] = attrs["delete_vm_post_restore"] text = render_template(schema_file="restore_config.py.jinja2", obj=user_attrs) return text.strip()
def render_snapshot_config_template(cls, entity_context, CONFIG_SPEC_MAP): LOG.debug("Rendering {} snapshot config template".format(cls.__name__)) if not isinstance(cls, ConfigSpecType): raise TypeError("{} is not of type {}".format(cls, ConfigSpecType)) _user_attrs = cls.get_user_attrs() user_attrs = dict() user_attrs["name"] = _user_attrs["name"] or cls.__name__ user_attrs["restore_config"] = CONFIG_SPEC_MAP[ _user_attrs["config_references"][0].name ]["local_name"] attrs = _user_attrs["attrs_list"][0] user_attrs["target"] = get_valid_identifier( attrs["target_any_local_reference"]["name"] ) user_attrs["num_of_replicas"] = attrs["num_of_replicas"] if attrs.get("app_protection_policy_reference", None): user_attrs["policy"] = attrs["app_protection_policy_reference"]["name"] if attrs.get("app_protection_rule_reference", None): user_attrs["rule"] = attrs["app_protection_rule_reference"]["name"] text = render_template(schema_file="snapshot_config.py.jinja2", obj=user_attrs) return text.strip()
def _test_decompile_with_prefix(self, bp_name): runner = CliRunner() # Decompiling the created bp and storing secrets in file with prefix prefix = get_valid_identifier("_{}".format(str(uuid.uuid4())[:10])) LOG.info( "Decompiling Blueprint {} with prefix flag set to '{}'".format( bp_name, prefix)) cli_inputs = [CRED_PASSWORD, CRED_PASSWORD, CRED_PASSWORD] result = runner.invoke( cli, ["decompile", "bp", bp_name, "--with_secrets", "-p", prefix], input="\n".join(cli_inputs), ) if result.exit_code: cli_res_dict = { "Output": result.output, "Exception": str(result.exception) } LOG.debug("Cli Response: {}".format( json.dumps(cli_res_dict, indent=4, separators=(",", ": ")))) LOG.debug("Traceback: \n{}".format("".join( traceback.format_tb(result.exc_info[2])))) self.bp_dir_list.append(get_bp_dir()) decompiled_bp_file_location = os.path.join(get_bp_dir(), "blueprint.py") user_bp_module = get_blueprint_module_from_file( decompiled_bp_file_location) UserBlueprint = get_blueprint_class_from_module(user_bp_module) LOG.info("Asserting prefix in the entity names") for svc in UserBlueprint.services: assert svc.__name__.startswith(prefix) for pkg in UserBlueprint.packages: assert pkg.__name__.startswith(prefix) for sub in UserBlueprint.substrates: assert sub.__name__.startswith(prefix) assert sub.provider_spec.__name__.startswith(prefix) assert sub.provider_spec.resources.__name__.startswith(prefix) for pfl in UserBlueprint.profiles: assert pfl.__name__.startswith(prefix) for dep in pfl.deployments: assert dep.__name__.startswith(prefix) LOG.info("Success") # Resetting context for decompiling init_decompile_context # On applying prefix, name of dsl classes will be changed but UI name will be preserved # So compiled payload should be same bp_file_location = os.path.join(os.getcwd(), BP_FILE) LOG.info( "Compiling original blueprint file at {}".format(bp_file_location)) result = runner.invoke( cli, ["-vv", "compile", "bp", "-f", bp_file_location]) if result.exit_code: cli_res_dict = { "Output": result.output, "Exception": str(result.exception) } LOG.debug("Cli Response: {}".format( json.dumps(cli_res_dict, indent=4, separators=(",", ": ")))) LOG.debug("Traceback: \n{}".format("".join( traceback.format_tb(result.exc_info[2])))) bp_json = json.loads(result.output) LOG.info( "Compiling decompiled blueprint file having entity names with prefix at {}" .format(decompiled_bp_file_location)) result = runner.invoke( cli, ["-vv", "compile", "bp", "-f", decompiled_bp_file_location]) if result.exit_code: cli_res_dict = { "Output": result.output, "Exception": str(result.exception) } LOG.debug("Cli Response: {}".format( json.dumps(cli_res_dict, indent=4, separators=(",", ": ")))) LOG.debug("Traceback: \n{}".format("".join( traceback.format_tb(result.exc_info[2])))) decompiled_bp_json = json.loads(result.output) # We don't have paramter to pass name of blueprint during compile right now # So compare everythin else other than blueprint name decompiled_bp_json["metadata"]["name"] = bp_json["metadata"]["name"] decompiled_bp_json["spec"]["name"] = bp_json["spec"]["name"] # POP out the client attrs, as they will be changed due to prefix bp_json["spec"]["resources"].pop("client_attrs", {}) decompiled_bp_json["spec"]["resources"].pop("client_attrs", {}) LOG.info("Comparing original and decompiled blueprint json") assert bp_json == decompiled_bp_json LOG.info("Success") # Reseting context ContextObj = get_context() ContextObj.reset_configuration()