diff --git a/calm-integrations/publish_blueprints_marketplace/README.md b/calm-integrations/publish_blueprints_marketplace/README.md index 6b044a3..17da755 100644 --- a/calm-integrations/publish_blueprints_marketplace/README.md +++ b/calm-integrations/publish_blueprints_marketplace/README.md @@ -1,10 +1,20 @@ # Plublish blueprint to marketplace without substrate spec +## How do we execute this? +You can execute this as a native python script, or as a runbook + ## What does this do? This script publishes existing blueprint to marketplace (LOCAL) within a PC without substrate elements. ## Supported Platforms: - - VCenter + - VCenter, AHV + +## Runbook +1. Import the runbook in Prism Central NCM Self-Service +2. Update the credential for PC +3. Update the variables to match your environment +4. Execute the runbook. +Note - the runbook is executed on your local Calm\PC as an escript. ## Inputs for publish_blueprints_to_marketplace.py: * --pc - PC Ip address diff --git a/calm-integrations/publish_blueprints_marketplace/publish_blueprint_to_marketplace.py b/calm-integrations/publish_blueprints_marketplace/publish_blueprint_to_marketplace.py index d0b22ab..23df11b 100644 --- a/calm-integrations/publish_blueprints_marketplace/publish_blueprint_to_marketplace.py +++ b/calm-integrations/publish_blueprints_marketplace/publish_blueprint_to_marketplace.py @@ -195,6 +195,45 @@ def remove_platform_data(bp_spec): for nic in substrate["create_spec"]["resources"]["nic_list"]: nic["net_name"] = "" nic["nic_type"] = "" + if substrate['type'] == "AHV_VM": + for disk in substrate["create_spec"]["resources"]["disk_list"]: + if hasattr(disk, "data_source_reference"): + if hasattr(disk["data_source_reference"], 'kind') and disk["data_source_reference"]['kind'] == "image": + disk["data_source_reference"]["name"] = "" + disk["data_source_reference"]["uuid"] = "" + for nic in substrate["create_spec"]["resources"]["nic_list"]: + nic["subnet_reference"]["uuid"] = "" + nic["subnet_reference"]["name"] = "" + if substrate["type"] == "AZURE_VM": + substrate["create_spec"]["resources"]["storage_profile"]["image_details"]["sku"] = "" + substrate["create_spec"]["resources"]["storage_profile"]["image_details"]["publisher"] = "" + substrate["create_spec"]["resources"]["storage_profile"]["image_details"]["offer"] = "" + substrate["create_spec"]["resources"]["storage_profile"]["image_details"]["version"] = "" + substrate["create_spec"]["resources"]["storage_profile"]["image_details"]["source_image_id"] = "" + substrate["create_spec"]["resources"]["storage_profile"]["image_details"]["source_image_type"] = "" + substrate["create_spec"]["resources"]["storage_profile"]["image_details"]["type"] = "" + #for disk in substrate["create_spec"]["resources"]["storage_profile"]["data_disk_list"]: + # disk["lun"] = None + # disk["size_in_gb"] = None + # disk["name"] = "" + for nic in substrate["create_spec"]["resources"]["nw_profile"]["nic_list"]: + nic["nsg_name"] = "" + nic["vnet_name"] = "" + nic["subnet_id"] = "" + nic["nsg_id"] = "" + nic["private_ip_info"]["ip_address"] = "" + nic["private_ip_info"]["type"] = "" + nic["nic_name"] = "" + nic["subnet_name"] = "" + nic["vnet_id"] = "" + nic["type"] = "" + nic["public_ip_info"] = None + substrate["create_spec"]["resources"]["resource_group"] = "" + substrate["create_spec"]["resources"]["hw_profile"]["max_data_disk_count"] = 0 + substrate["create_spec"]["resources"]["hw_profile"]["vm_size"] = "" + substrate["create_spec"]["resources"]["location"] = "" + substrate["create_spec"]["resources"]["availability_set_id"] = "" + substrate["create_spec"]["resources"]["account_uuid"] = "" return bp_spec ### --------------------------------------------------------------------------------- ### diff --git a/calm-integrations/publish_blueprints_marketplace/runbook_publish_blueprints_mpi_v1_10.json b/calm-integrations/publish_blueprints_marketplace/runbook_publish_blueprints_mpi_v1_10.json new file mode 100644 index 0000000..fc77bcf --- /dev/null +++ b/calm-integrations/publish_blueprints_marketplace/runbook_publish_blueprints_mpi_v1_10.json @@ -0,0 +1 @@ +{"status":{},"contains_secrets":false,"product_version":"3.5.2","spec":{"description":"This runbook should only be published to projects that are restricted to blueprint developers only. This runbook executes a script that removes specific items from the blueprint to facilitate the use of 'environments' in conjunction with the Market Place.\n\n if substrate['type'] == \"VMWARE_VM\":\n substrate[\"create_spec\"][\"cluster\"] = \"\"\n substrate[\"create_spec\"][\"storage_pod\"] = \"\"\n substrate[\"create_spec\"][\"host\"] = \"\"\n substrate[\"create_spec\"","resources":{"endpoints_information":[],"endpoint_definition_list":[],"client_attrs":{},"credential_definition_list":[{"username":"admin","description":"","type":"PASSWORD","secret":{"attrs":{"is_secret_modified":false,"secret_reference":{}}},"name":"cred_prismcentral","cred_class":"static"}],"runbook":{"task_definition_list":[{"retries":"0","description":"","inherit_target":false,"child_tasks_local_reference_list":[{"kind":"app_task","name":"Publish to Marketplace"}],"name":"b91e8541_dag","attrs":{"edges":[],"type":""},"timeout_secs":"0","type":"DAG","variable_list":[]},{"retries":"0","description":"","inherit_target":false,"child_tasks_local_reference_list":[],"name":"Publish to Marketplace","attrs":{"script":"# \n#\n# https:\/\/github.com\/nutanix\/blueprints\/tree\/master\/calm-integrations\/publish_blueprints_marketplace\n#\n\n#\n# Author: Nutanix\n#\n# Version: 1.10\n# Date: 20210730\n# Modified Date: 20230228\n# Change Log: Akshay Dobariya, update function to include logic to support\n# multiple disks in AHV BP.\n# Change log: Dusty Lane, update to make pc_port dynamic.\n# Change Log: Chris Glover, update for azure platform\n#\n#################### Modules #################### \n\nimport re\nimport requests\n\n#################### vars #################### \n\npc_ip='@@{pc_ip}@@'\npc_port='9440'\nblueprint_name='@@{blueprint_name}@@'\nname='@@{marketplace_bp_name}@@'\nmarketplace_bp_name=name\nversion='@@{version}@@'\ndescription='@@{description}@@'\nproject='@@{project}@@'\nauto_approve='true'\npublish_to_marketplace='true'\nwith_secrets='true'\nexisting_markeplace_bp='true'\nuser='@@{prism_central.username}@@'\npassword='@@{prism_central.secret}@@'\naction='store'\nicon='@@{icon}@@'\n\n#################### functions #################### \n\nheaders = {'content-type': 'application\/json', 'Accept': 'application\/json'}\n\ndef str2bool(v):\n if isinstance(v, bool):\n return v\n if v.lower() in ('yes', 'true', 't', 'y', '1'):\n return True\n elif v.lower() in ('no', 'false', 'f', 'n', '0'):\n return False\n else:\n raise argparse.ArgumentTypeError('Boolean value expected.')\n\ndef help_parser():\n\n parser = argparse.ArgumentParser(\n description='Standard Arguments for talking to vCenter or ESXi')\n parser.add_argument('--pc',\n required=True,\n action='store',\n help='vSphere service to connect to')\n parser.add_argument('--port',\n type=int,\n default=9440,\n action='store',\n help='Port to connect on')\n parser.add_argument('--user',\n required=True,\n action='store',\n help='User name to use when connecting to pc')\n parser.add_argument('--password',\n required=True,\n action='store',\n help='Password to use when connecting to pc')\n parser.add_argument('--blueprint_name',\n required=True,\n action='store',\n help='Blueprint name to be published')\n parser.add_argument('-v', '--version',\n required=True,\n action='store',\n help='Marketplace app version')\n parser.add_argument('-n', '--name',\n required=True,\n action='store',\n help='Marketplace app Name')\n parser.add_argument('-p', '--project',\n required=True,\n action='store',\n help='Projects for marketplace blueprint(used for approving blueprint)')\n parser.add_argument('-i', '--icon',\n required=True,\n action='store',\n help='Marketplace app Icon')\n parser.add_argument('-d', '--description',\n required=True,\n action='store',\n help='Marketplace app description')\n parser.add_argument(\"--with_secrets\", type=str2bool, nargs='?',\n const=True, default=False,\n help=\"Publish with secrets\")\n parser.add_argument(\"--publish_to_marketplace\", type=str2bool, nargs='?',\n const=True, default=False,\n help=\"Publish to Marketplace\")\n parser.add_argument(\"--auto_approve\", type=str2bool, nargs='?',\n const=True, default=False,\n help=\"Approve from Marketplace manager\")\n parser.add_argument(\"--existing_markeplace_bp\", type=str2bool, nargs='?',\n const=True, default=False,\n help=\"Existing marketplace app\")\n return parser\n\n### --------------------------------------------------------------------------------- ###\ndef get_blueprint_uuid(base_url, auth, blueprint_name):\n method = 'POST'\n url = base_url + \"\/blueprints\/list\"\n resp = None\n blueprint_uuid = \"\"\n payload = {\n \"length\":100,\n \"offset\":0,\n \"filter\":\"name=={}\".format(blueprint_name)\n }\n try:\n resp = requests.request(\n method,\n url,\n data=json.dumps(payload),\n headers=headers,\n auth=(auth[\"username\"], auth[\"password\"]),\n verify=False\n )\n except requests.exceptions.ConnectionError as e:\n print(\"Failed to connect to PC: {}\".format(e))\n exit(-1)\n finally:\n if resp.ok:\n json_resp = resp.json()\n if json_resp['metadata']['total_matches'] > 0:\n for bp in json_resp['entities']:\n if bp[\"metadata\"][\"name\"] == blueprint_name:\n return bp[\"metadata\"][\"uuid\"]\n else:\n print(\"Not able to find blueprint {}\".format(blueprint_name))\n exit(-1)\n else:\n print(\"Request failed\")\n print(\"Headers: {}\".format(headers))\n print('Status code: {}'.format(resp.status_code))\n print('Response: {}'.format(json.dumps(json.loads(resp.content), indent=4)))\n exit(-1)\n\n### --------------------------------------------------------------------------------- ###\ndef get_blueprint(base_url, auth, blueprint_uuid):\n method = 'GET'\n url = base_url + \"\/blueprints\/{}\/export_json?keep_secrets=true\".format(blueprint_uuid)\n resp = None\n try:\n resp = requests.request(\n method,\n url,\n headers=headers,\n auth=(auth[\"username\"], auth[\"password\"]),\n verify=False\n )\n except requests.exceptions.ConnectionError as e:\n print(\"Failed to connect to PC: {}\".format(e))\n exit(-1)\n finally:\n if resp.ok:\n return resp.json()\n else:\n print(\"Request failed\")\n print(\"Headers: {}\".format(headers))\n print('Status code: {}'.format(resp.status_code))\n print('Response: {}'.format(json.dumps(json.loads(resp.content), indent=4)))\n exit(-1)\n\n### --------------------------------------------------------------------------------- ###\ndef get_icon_uuid(base_url, auth, icon_name):\n method = 'POST'\n url = base_url + \"\/app_icons\/list\"\n app_icon_uuid = None\n payload = {\n \"length\":100,\n \"offset\":0\n }\n try:\n resp = requests.request(\n method,\n url,\n data=json.dumps(payload),\n headers=headers,\n auth=(auth[\"username\"], auth[\"password\"]),\n verify=False\n )\n except requests.exceptions.ConnectionError as e:\n print(\"Failed to connect to PC: {}\".format(e))\n exit(-1)\n finally:\n if resp.ok:\n json_resp = resp.json()\n if json_resp['metadata']['total_matches'] > 0:\n for icon in json_resp['entities']:\n if icon[\"metadata\"][\"name\"] == icon_name:\n app_icon_uuid = icon[\"metadata\"][\"uuid\"]\n else:\n print(\"Not able to find icon {}\".format(blueprint_name))\n exit(-1)\n return app_icon_uuid\n else:\n print(\"Request failed\")\n print(\"Headers: {}\".format(headers))\n print('Status code: {}'.format(resp.status_code))\n print('Response: {}'.format(json.dumps(json.loads(resp.content), indent=4)))\n exit(-1)\n\n### --------------------------------------------------------------------------------- ###\ndef remove_platform_data(bp_spec):\n for substrate in bp_spec[\"resources\"][\"substrate_definition_list\"]:\n if substrate['type'] == \"VMWARE_VM\":\n substrate[\"create_spec\"][\"cluster\"] = \"\"\n substrate[\"create_spec\"][\"storage_pod\"] = \"\"\n substrate[\"create_spec\"][\"host\"] = \"\"\n substrate[\"create_spec\"][\"datastore\"] = \"\"\n for nic in substrate[\"create_spec\"][\"resources\"][\"nic_list\"]:\n nic[\"net_name\"] = \"\"\n nic[\"nic_type\"] = \"\"\n if substrate['type'] == \"AHV_VM\":\n for disk in substrate[\"create_spec\"][\"resources\"][\"disk_list\"]:\n if hasattr(disk, \"data_source_reference\"):\n if hasattr(disk[\"data_source_reference\"], 'kind') and disk[\"data_source_reference\"]['kind'] == \"image\":\n disk[\"data_source_reference\"][\"name\"] = \"\"\n disk[\"data_source_reference\"][\"uuid\"] = \"\"\n for nic in substrate[\"create_spec\"][\"resources\"][\"nic_list\"]:\n nic[\"subnet_reference\"][\"uuid\"] = \"\"\n nic[\"subnet_reference\"][\"name\"] = \"\"\n if substrate[\"type\"] == \"AZURE_VM\":\n substrate[\"create_spec\"][\"resources\"][\"storage_profile\"][\"image_details\"][\"sku\"] = \"\"\n substrate[\"create_spec\"][\"resources\"][\"storage_profile\"][\"image_details\"][\"publisher\"] = \"\"\n substrate[\"create_spec\"][\"resources\"][\"storage_profile\"][\"image_details\"][\"offer\"] = \"\"\n substrate[\"create_spec\"][\"resources\"][\"storage_profile\"][\"image_details\"][\"version\"] = \"\"\n substrate[\"create_spec\"][\"resources\"][\"storage_profile\"][\"image_details\"][\"source_image_id\"] = \"\"\n substrate[\"create_spec\"][\"resources\"][\"storage_profile\"][\"image_details\"][\"source_image_type\"] = \"\"\n substrate[\"create_spec\"][\"resources\"][\"storage_profile\"][\"image_details\"][\"type\"] = \"\"\n #for disk in substrate[\"create_spec\"][\"resources\"][\"storage_profile\"][\"data_disk_list\"]:\n # disk[\"lun\"] = None\n # disk[\"size_in_gb\"] = None\n # disk[\"name\"] = \"\"\n for nic in substrate[\"create_spec\"][\"resources\"][\"nw_profile\"][\"nic_list\"]:\n nic[\"nsg_name\"] = \"\"\n nic[\"vnet_name\"] = \"\"\n nic[\"subnet_id\"] = \"\"\n nic[\"nsg_id\"] = \"\"\n nic[\"private_ip_info\"][\"ip_address\"] = \"\"\n nic[\"private_ip_info\"][\"type\"] = \"\"\n nic[\"nic_name\"] = \"\"\n nic[\"subnet_name\"] = \"\"\n nic[\"vnet_id\"] = \"\"\n nic[\"type\"] = \"\"\n nic[\"public_ip_info\"] = None\n substrate[\"create_spec\"][\"resources\"][\"resource_group\"] = \"\"\n substrate[\"create_spec\"][\"resources\"][\"hw_profile\"][\"max_data_disk_count\"] = 0\n substrate[\"create_spec\"][\"resources\"][\"hw_profile\"][\"vm_size\"] = \"\"\n substrate[\"create_spec\"][\"resources\"][\"location\"] = \"\"\n substrate[\"create_spec\"][\"resources\"][\"availability_set_id\"] = \"\"\n substrate[\"create_spec\"][\"resources\"][\"account_uuid\"] = \"\"\n return bp_spec\n\n### --------------------------------------------------------------------------------- ###\ndef publish_bp_to_marketplace_manager(\n bp_json,\n marketplace_bp_name,\n version,\n description=\"\",\n app_group_uuid=None,\n icon_name=None,\n icon_file=None,\n):\n\n bp_data = bp_json\n bp_status = bp_data[\"status\"][\"state\"]\n if bp_status != \"ACTIVE\":\n print(\"Blueprint is in {} state. Unable to publish it to marketplace manager\".format(bp_status))\n exit(-1)\n\n bp_template = {\n \"spec\": {\n \"name\": marketplace_bp_name,\n \"description\": description,\n \"resources\": {\n \"app_attribute_list\": [\"FEATURED\"],\n \"icon_reference_list\": [],\n \"author\": \"admin\",\n \"version\": version,\n \"app_group_uuid\": app_group_uuid or str(uuid.uuid4()),\n \"app_blueprint_template\": {\n \"status\": bp_data[\"status\"],\n \"spec\": bp_data[\"spec\"],\n },\n },\n },\n \"api_version\": \"3.0\",\n \"metadata\": {\"kind\": \"marketplace_item\"},\n }\n if icon_name:\n app_icon_uuid = get_icon_uuid(base_url, auth, icon_name)\n bp_template[\"spec\"][\"resources\"][\"icon_reference_list\"] = [\n {\n \"icon_type\": \"ICON\",\n \"icon_reference\": {\"kind\": \"file_item\", \"uuid\": app_icon_uuid},\n }\n ]\n method = 'POST'\n url = base_url + \"\/calm_marketplace_items\"\n resp = None\n try:\n resp = requests.request(\n method,\n url,\n data=json.dumps(bp_template),\n headers=headers,\n auth=(auth[\"username\"], auth[\"password\"]),\n verify=False\n )\n except requests.exceptions.ConnectionError as e:\n print(\"Failed to connect to PC: {}\".format(e))\n exit(-1)\n finally:\n if resp.ok:\n json_resp = resp.json()\n if json_resp[\"spec\"][\"resources\"][\"app_state\"] != \"PENDING\":\n print(\"Failed to publish blueprint to Marketplace\")\n exit(-1)\n else:\n return json_resp\n else:\n print(\"Request failed\")\n print(\"Headers: {}\".format(headers))\n print('Status code: {}'.format(resp.status_code))\n print('Response: {}'.format(json.dumps(json.loads(resp.content), indent=4)))\n exit(-1)\n\n print(\"Marketplace Blueprint is published to marketplace manager successfully\")\n\n### --------------------------------------------------------------------------------- ###\ndef get_project_uuid(base_url, auth, project_name):\n method = 'POST'\n url = base_url + \"\/projects\/list\"\n payload = {\n \"length\":100,\n \"offset\":0,\n \"filter\":\"name=={0}\".format(project_name)\n }\n resp = requests.request(\n method,\n url,\n data=json.dumps(payload),\n headers=headers,\n auth=(auth[\"username\"], auth[\"password\"]),\n verify=False\n )\n\n if resp.ok:\n json_resp = resp.json()\n if json_resp['metadata']['total_matches'] > 0:\n project = json_resp['entities'][0]\n project_uuid = project[\"metadata\"][\"uuid\"]\n return project_uuid\n else:\n print(\"Could not find project\")\n exit(-1)\n else:\n print(\"Request failed\")\n print(\"Headers: {}\".format(headers))\n print('Status code: {}'.format(resp.status_code))\n print('Response: {}'.format(json.dumps(json.loads(resp.content), indent=4)))\n exit(-1)\n\n### --------------------------------------------------------------------------------- ###\ndef approve_marketplace_bp(marketplace_json, projects=[], category=None):\n method = 'PUT'\n url = base_url + \"\/calm_marketplace_items\/{}\".format(marketplace_json[\"metadata\"][\"uuid\"])\n resp = None\n marketplace_json[\"spec\"][\"resources\"][\"app_state\"] = \"ACCEPTED\"\n marketplace_json[\"spec\"][\"resources\"][\"project_reference_list\"] = projects\n del marketplace_json[\"status\"]\n try:\n resp = requests.request(\n method,\n url,\n data=json.dumps(marketplace_json),\n headers=headers,\n auth=(auth[\"username\"], auth[\"password\"]),\n verify=False\n )\n except requests.exceptions.ConnectionError as e:\n print(\"Failed to connect to PC: {}\".format(e))\n exit(-1)\n finally:\n if resp.ok:\n json_resp = resp.json()\n if json_resp[\"spec\"][\"resources\"][\"app_state\"] != \"ACCEPTED\":\n print(\"Failed to approve Marketplace Application\")\n exit(-1)\n else:\n return json_resp\n else:\n print(\"Request failed\")\n print(\"Headers: {}\".format(headers))\n print('Status code: {}'.format(resp.status_code))\n print('Response: {}'.format(json.dumps(json.loads(resp.content), indent=4)))\n exit(-1)\n\n### --------------------------------------------------------------------------------- ###\ndef publish_marketplace_bp(marketplace_json):\n method = 'PUT'\n url = base_url + \"\/calm_marketplace_items\/{}\".format(marketplace_json[\"metadata\"][\"uuid\"])\n resp = None\n marketplace_json[\"spec\"][\"resources\"][\"app_state\"] = \"PUBLISHED\"\n marketplace_json[\"metadata\"][\"spec_version\"] = 1\n\n try:\n resp = requests.request(\n method,\n url,\n data=json.dumps(marketplace_json),\n headers=headers,\n auth=(auth[\"username\"], auth[\"password\"]),\n verify=False\n )\n except requests.exceptions.ConnectionError as e:\n print(\"Failed to connect to PC: {}\".format(e))\n exit(-1)\n finally:\n if resp.ok:\n json_resp = resp.json()\n if json_resp[\"spec\"][\"resources\"][\"app_state\"] != \"PUBLISHED\":\n print(\"Failed to Publish Marketplace Application\")\n exit(-1)\n else:\n return json_resp\n else:\n print(\"Request failed\")\n print(\"Headers: {}\".format(headers))\n print('Status code: {}'.format(resp.status_code))\n print('Response: {}'.format(json.dumps(json.loads(resp.content), indent=4)))\n exit(-1)\n\n### --------------------------------------------------------------------------------- ###\ndef get_app_group_uuid(marketplace_bp_name):\n method = 'POST'\n url = base_url + \"\/groups\"\n app_group_uuid = None\n group = None\n\n payload = {\n \"filter_criteria\": \"marketplace_item_type_list==APP;app_source==LOCAL;name=={}.*\".format(marketplace_bp_name),\n \"entity_type\": \"marketplace_item\",\n \"group_member_offset\": 0,\n \"group_member_count\": 1,\n \"group_count\": 64,\n \"grouping_attribute\": \"app_group_uuid\",\n \"group_member_attributes\": [\n {\n \"attribute\": \"name\"\n },\n {\n \"attribute\": \"app_group_uuid\"\n }\n ],\n \"group_member_sort_attribute\": \"name\",\n \"group_member_sort_order\": \"DESCENDING\"\n }\n\n try:\n resp = requests.request(\n method,\n url,\n data=json.dumps(payload),\n headers=headers,\n auth=(auth[\"username\"], auth[\"password\"]),\n verify=False\n )\n except requests.exceptions.ConnectionError as e:\n print(\"Failed to connect to PC: {}\".format(e))\n exit(-1)\n finally:\n if resp.ok:\n json_resp = resp.json()\n if json_resp[\"filtered_group_count\"] != 0:\n for result in json_resp[\"group_results\"]:\n for data in result[\"entity_results\"][0][\"data\"]:\n if data[\"name\"] == \"name\" and data[\"values\"][0][\"values\"][0] == marketplace_bp_name:\n group = result\n else:\n print(\"Failed to Find exiting Marketplace Application\")\n if group != None:\n for data in group[\"entity_results\"][0][\"data\"]:\n if data[\"name\"] == \"app_group_uuid\":\n app_group_uuid = data[\"values\"][0][\"values\"][0]\n return app_group_uuid \n else:\n print(\"Failed to Find exiting Marketplace Application\")\n return app_group_uuid \n else:\n print(\"Request failed\")\n print(\"Headers: {}\".format(headers))\n print('Status code: {}'.format(resp.status_code))\n print('Response: {}'.format(json.dumps(json.loads(resp.content), indent=4)))\n exit(-1)\n\n### --------------------------------------------------------------------------------- ###\ndef publish_bp_as_existing_marketplace_bp(\n bp_json,\n marketplace_bp_name,\n version,\n description=\"\",\n publish_to_marketplace=False,\n auto_approve=False,\n projects=[],\n category=None,\n icon_name=None\n ):\n app_group_uuid = get_app_group_uuid(marketplace_bp_name)\n published_json = publish_bp_to_marketplace_manager(bp_json, marketplace_bp_name, version, \n description=description, app_group_uuid=app_group_uuid, icon_name=icon_name)\n if publish_to_marketplace or auto_approve:\n project_reference_list = []\n for project in projects:\n project_uuid = get_project_uuid(base_url, auth, project)\n project_reference = {\"name\": project, \"kind\": \"project\", \"uuid\": project_uuid}\n project_reference_list.append(project_reference)\n\n approved_json = approve_marketplace_bp(\n published_json,\n projects=project_reference_list,\n category=category\n )\n if publish_to_marketplace:\n publish_marketplace_bp(published_json)\n\n#if __name__ == \"__main__\":\npc_ip = pc_ip\npc_port = pc_port\nblueprint_name = blueprint_name\n# marketplace_bp_name = name\nversion = version\ndescription = description\nproject = project\nicon = icon\nauto_approve = auto_approve\npublish_to_marketplace = publish_to_marketplace\nwith_secrets = with_secrets\nexisting_markeplace_bp = existing_markeplace_bp\n\nbase_url = \"https:\/\/{}:{}\/api\/nutanix\/v3\".format(pc_ip,str(pc_port))\nauth = { \"username\": user, \"password\": password}\n\nblueprint_uuid = get_blueprint_uuid(base_url, auth, blueprint_name)\nblueprint_json = get_blueprint(base_url, auth, blueprint_uuid)\nblueprint_json[\"spec\"] = remove_platform_data(blueprint_json[\"spec\"])\nblueprint_json[\"status\"] = remove_platform_data(blueprint_json[\"status\"])\npublish_bp_as_existing_marketplace_bp(blueprint_json, marketplace_bp_name, \n version, description=description, publish_to_marketplace=publish_to_marketplace, \n auto_approve=auto_approve, projects=project.split(','), icon_name=icon)","type":"","command_line_args":"","exit_status":[],"script_type":"static"},"timeout_secs":"0","type":"EXEC","variable_list":[]}],"description":"","name":"cec64f92_runbook","main_task_local_reference":{"kind":"app_task","name":"b91e8541_dag"},"variable_list":[{"val_type":"STRING","is_mandatory":true,"description":"Enter the name of the blue print.","data_type":"BASE","type":"LOCAL","name":"blueprint_name","value":"the_blueprint_name","label":"Blueprint Name","attrs":{"type":""},"editables":{"value":true},"is_hidden":false,"options":{"type":"PREDEFINED","choices":[]}},{"val_type":"STRING","is_mandatory":true,"description":"enter the name that will be displayed in the market place.","data_type":"BASE","type":"LOCAL","name":"marketplace_bp_name","value":"Name as it will appear in the marketplace","label":"Marketplace Item Name","attrs":{"type":""},"editables":{"value":true},"is_hidden":false,"options":{"type":"PREDEFINED","choices":[]}},{"regex":{"should_validate":true,"value":"^(\\d+\\.)?(\\d+\\.)?(\\d+)$"},"val_type":"STRING","is_mandatory":true,"description":"","data_type":"BASE","type":"LOCAL","name":"version","value":"1.0.4","label":"","attrs":{"type":"LOCAL"},"editables":{"value":true},"is_hidden":false,"options":{"type":"PREDEFINED","choices":[]}},{"val_type":"STRING","is_mandatory":true,"description":"","data_type":"BASE","type":"LOCAL","name":"project","value":"Windows10","label":"Calm Project Name to publish to","attrs":{"type":""},"editables":{"value":true},"is_hidden":false,"options":{"type":"PREDEFINED","choices":[]}},{"val_type":"STRING","is_mandatory":false,"description":"The icons must pre-exist in Calm\\NCM Self-service","data_type":"BASE","type":"LOCAL","name":"icon","value":"Windows2022","label":"Select the neame of the preexisting icon to use","attrs":{"type":"LOCAL"},"editables":{"value":true},"is_hidden":false,"options":{"type":"PREDEFINED","choices":["Windows2019","RHEL8","Ubuntu20","Windows2016","Windows10","Windows2022"]}},{"val_type":"STRING","is_mandatory":true,"description":"enter the description that will explain what this market place item will do\\provision.","data_type":"BASE","type":"LOCAL","name":"description","value":"your description here","label":"Description of the MPI","attrs":{"type":""},"editables":{"value":true},"is_hidden":false,"options":{"type":"PREDEFINED","choices":[]}},{"val_type":"STRING","is_mandatory":true,"description":"true\\false","data_type":"BASE","type":"LOCAL","name":"existing_markeplace_bp","value":"false","label":"Does this MPI already exist?","attrs":{"type":"LOCAL"},"editables":{"value":true},"is_hidden":false,"options":{"type":"PREDEFINED","choices":["true","false"]}},{"val_type":"STRING","is_mandatory":false,"description":"","data_type":"BASE","type":"LOCAL","name":"pc_ip","value":"127.0.0.1","label":"Prism Central IP","attrs":{"type":""},"editables":{"value":false},"is_hidden":true,"options":{"type":"PREDEFINED","choices":[]}}]}},"name":"runbook_publish_blueprints_mpi_v1_10_static_WIP"},"api_version":"3.0","metadata":{"last_update_time":"1677703436842652","kind":"runbook","spec_version":5,"creation_time":"1677586034627647","name":"runbook_publish_blueprints_mpi_v1_10_static_WIP"}} \ No newline at end of file