def poll(cmd, request_url, poll_if_status): # pylint: disable=inconsistent-return-statements try: start = time.time() end = time.time() + POLLING_TIMEOUT animation = PollingAnimation() animation.tick() r = send_raw_request(cmd.cli_ctx, "GET", request_url) while r.status_code in [200, 201] and start < end: time.sleep(POLLING_SECONDS) animation.tick() r = send_raw_request(cmd.cli_ctx, "GET", request_url) r2 = r.json() if "properties" not in r2 or "provisioningState" not in r2["properties"] or not r2["properties"]["provisioningState"].lower() == poll_if_status: break start = time.time() animation.flush() return r.json() except Exception as e: # pylint: disable=broad-except animation.flush() delete_statuses = ["scheduledfordelete", "cancelled"] if poll_if_status not in delete_statuses: # Catch "not found" errors if polling for delete raise e
def test_send_raw_requests(self, request_mock): from azure.cli.core.commands.client_factory import UA_AGENT return_val = mock.MagicMock() return_val.is_ok = True request_mock.return_value = return_val cli_ctx = mock.MagicMock() cli_ctx.data = { 'command': 'rest', 'safe_params': ['method', 'uri'] } test_arm_endpoint = 'https://arm.com/' test_url = 'subscription/1234/good' tets_uri_parameters = ['p1=v1', "{'p2': 'v2'}"] test_body = '{"b1": "v1"}' cli_ctx.cloud.endpoints.resource_manager = test_arm_endpoint expected_header = { 'User-Agent': UA_AGENT, 'Content-Type': 'application/json', 'CommandName': 'rest', 'ParameterSetName': 'method uri' } send_raw_request(cli_ctx, 'PUT', test_url, uri_parameters=tets_uri_parameters, body=test_body, skip_authorization_header=True, generated_client_request_id_name=None) request_mock.assert_called_with('PUT', test_arm_endpoint + test_url, params={'p1': 'v1', 'p2': 'v2'}, data=test_body, headers=expected_header, verify=(not should_disable_connection_verify()))
def list(cls, cmd, resource_group_name, env_name, formatter=lambda x: x): env_list = [] management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager api_version = STABLE_API_VERSION sub_id = get_subscription_id(cmd.cli_ctx) url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/managedEnvironments/{}/storages?api-version={}" request_url = url_fmt.format( management_hostname.strip('/'), sub_id, resource_group_name, env_name, api_version) r = send_raw_request(cmd.cli_ctx, "GET", request_url) j = r.json() for env in j["value"]: formatted = formatter(env) env_list.append(formatted) while j.get("nextLink") is not None: request_url = j["nextLink"] r = send_raw_request(cmd.cli_ctx, "GET", request_url) j = r.json() for env in j["value"]: formatted = formatter(env) env_list.append(formatted) return env_list
def list_replicas(cls, cmd, resource_group_name, container_app_name, revision_name): replica_list = [] management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager sub_id = get_subscription_id(cmd.cli_ctx) url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/containerApps/{}/revisions/{}/replicas?api-version={}" request_url = url_fmt.format( management_hostname.strip('/'), sub_id, resource_group_name, container_app_name, revision_name, STABLE_API_VERSION) r = send_raw_request(cmd.cli_ctx, "GET", request_url) j = r.json() for replica in j["value"]: replica_list.append(replica) while j.get("nextLink") is not None: request_url = j["nextLink"] r = send_raw_request(cmd.cli_ctx, "GET", request_url) j = r.json() for replica in j["value"]: replica_list.append(replica) return replica_list
def list_by_subscription(cls, cmd, formatter=lambda x: x): app_list = [] management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager api_version = STABLE_API_VERSION sub_id = get_subscription_id(cmd.cli_ctx) request_url = "{}/subscriptions/{}/providers/Microsoft.App/containerApps?api-version={}".format( management_hostname.strip('/'), sub_id, api_version) r = send_raw_request(cmd.cli_ctx, "GET", request_url) j = r.json() for app in j["value"]: formatted = formatter(app) app_list.append(formatted) while j.get("nextLink") is not None: request_url = j["nextLink"] r = send_raw_request(cmd.cli_ctx, "GET", request_url) j = r.json() for app in j["value"]: formatted = formatter(app) app_list.append(formatted) return app_list
def Delete(self, cmd, client, resource_group_name, cluster_name, name, cluster_type, yes): # Delete DCR-A if it exists incase of MSI Auth useAADAuth = False isDCRAExists = False cluster_rp, _ = get_cluster_rp_api_version(cluster_type) try: extension = client.get(resource_group_name, cluster_rp, cluster_type, cluster_name, name) except Exception: pass # its OK to ignore the exception since MSI auth in preview subscription_id = get_subscription_id(cmd.cli_ctx) # handle cluster type here cluster_resource_id = '/subscriptions/{0}/resourceGroups/{1}/providers/{2}/{3}/{4}'.format( subscription_id, resource_group_name, cluster_rp, cluster_type, cluster_name) if (extension is not None) and (extension.configuration_settings is not None): configSettings = extension.configuration_settings if 'omsagent.useAADAuth' in configSettings: useAADAuthSetting = configSettings['omsagent.useAADAuth'] if (isinstance(useAADAuthSetting, str) and str(useAADAuthSetting).lower() == "true") or (isinstance(useAADAuthSetting, bool) and useAADAuthSetting): useAADAuth = True if useAADAuth: association_url = cmd.cli_ctx.cloud.endpoints.resource_manager + f"{cluster_resource_id}/providers/Microsoft.Insights/dataCollectionRuleAssociations/ContainerInsightsExtension?api-version=2019-11-01-preview" for _ in range(3): try: send_raw_request( cmd.cli_ctx, "GET", association_url, ) isDCRAExists = True break except HttpResponseError as ex: # Customize the error message for resources not found if ex.response.status_code == 404: isDCRAExists = False except Exception: pass # its OK to ignore the exception since MSI auth in preview if isDCRAExists: association_url = cmd.cli_ctx.cloud.endpoints.resource_manager + f"{cluster_resource_id}/providers/Microsoft.Insights/dataCollectionRuleAssociations/ContainerInsightsExtension?api-version=2019-11-01-preview" for _ in range(3): try: send_raw_request( cmd.cli_ctx, "DELETE", association_url, ) break except Exception: pass # its OK to ignore the exception since MSI auth in preview
def rest_call(cmd, url, method=None, headers=None, uri_parameters=None, body=None, skip_authorization_header=False, resource=None, output_file=None): from azure.cli.core.commands.transform import unregister_global_transforms # No transform should be performed on `az rest`. unregister_global_transforms(cmd.cli_ctx) from azure.cli.core.util import send_raw_request r = send_raw_request(cmd.cli_ctx, method, url, headers, uri_parameters, body, skip_authorization_header, resource, output_file) if not output_file and r.content: try: return r.json() except ValueError: logger.warning( 'Not a json response, outputting to stdout. For binary data ' 'suggest use "--output-file" to write to a file') print(r.text) return None
def update(cls, cmd, resource_group_name, name, container_app_envelope, no_wait=False): management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager api_version = NEW_API_VERSION sub_id = get_subscription_id(cmd.cli_ctx) url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/containerApps/{}?api-version={}" request_url = url_fmt.format(management_hostname.strip('/'), sub_id, resource_group_name, name, api_version) r = send_raw_request(cmd.cli_ctx, "PATCH", request_url, body=json.dumps(container_app_envelope)) if no_wait: return r.json() elif r.status_code == 201: url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/containerApps/{}?api-version={}" request_url = url_fmt.format(management_hostname.strip('/'), sub_id, resource_group_name, name, api_version) return poll(cmd, request_url, "inprogress") return r.json()
def raw_call(cmd, method, url, body=None): from azure.cli.core.util import send_raw_request r = send_raw_request(cmd.cli_ctx, method, url, body=body) if r.content: return r.json() return None
def create_or_update(cls, cmd, resource_group_name, env_name, name, storage_envelope, no_wait=False): management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager api_version = STABLE_API_VERSION sub_id = get_subscription_id(cmd.cli_ctx) url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/managedEnvironments/{}/storages/{}?api-version={}" request_url = url_fmt.format( management_hostname.strip('/'), sub_id, resource_group_name, env_name, name, api_version) r = send_raw_request(cmd.cli_ctx, "PUT", request_url, body=json.dumps(storage_envelope)) if no_wait: return r.json() elif r.status_code == 201: url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/managedEnvironments/{}/storages/{}?api-version={}" request_url = url_fmt.format( management_hostname.strip('/'), sub_id, resource_group_name, env_name, name, api_version) return poll(cmd, request_url, "waiting") return r.json()
def migration_create_func(cmd, client, resource_group_name, server_name, properties, migration_name=None): subscription_id = get_subscription_id(cmd.cli_ctx) properties_filepath = os.path.join(os.path.abspath(os.getcwd()), properties) if not os.path.exists(properties_filepath): raise FileOperationError( "Properties file does not exist in the given location") with open(properties_filepath, "r") as f: try: request_payload = json.load(f) request_payload.get("properties")['TriggerCutover'] = 'true' json_data = json.dumps(request_payload) except ValueError as err: logger.error(err) raise BadRequestError( "Invalid json file. Make sure that the json file content is properly formatted." ) if migration_name is None: # Convert a UUID to a string of hex digits in standard form migration_name = str(uuid.uuid4()) r = send_raw_request( cmd.cli_ctx, "put", "https://management.azure.com/subscriptions/{}/resourceGroups/{}/providers/Microsoft.DBforPostgreSQL/flexibleServers/{}/migrations/{}?api-version=2020-02-14-privatepreview" .format(subscription_id, resource_group_name, server_name, migration_name), None, None, json_data) return r.json()
def delete(cls, cmd, resource_group_name, env_name, name, no_wait=False): management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager api_version = STABLE_API_VERSION sub_id = get_subscription_id(cmd.cli_ctx) url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/managedEnvironments/{}/storages/{}?api-version={}" request_url = url_fmt.format( management_hostname.strip('/'), sub_id, resource_group_name, env_name, name, api_version) r = send_raw_request(cmd.cli_ctx, "DELETE", request_url) if no_wait: return # API doesn't return JSON (it returns no content) elif r.status_code in [200, 201, 202, 204]: url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/managedEnvironments/{}/storages/{}?api-version={}" request_url = url_fmt.format( management_hostname.strip('/'), sub_id, resource_group_name, env_name, name, api_version) if r.status_code == 200: # 200 successful delete, 204 means storage not found from azure.cli.core.azclierror import ResourceNotFoundError try: poll(cmd, request_url, "scheduledfordelete") except ResourceNotFoundError: pass logger.warning('Containerapp environment storage successfully deleted') return
def create_or_update(cls, cmd, resource_group_name, name, github_action_envelope, headers, no_wait=False): management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager api_version = STABLE_API_VERSION sub_id = get_subscription_id(cmd.cli_ctx) url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/containerApps/{}/sourcecontrols/current?api-version={}" request_url = url_fmt.format( management_hostname.strip('/'), sub_id, resource_group_name, name, api_version) r = send_raw_request(cmd.cli_ctx, "PUT", request_url, body=json.dumps(github_action_envelope), headers=headers) if no_wait: return r.json() elif r.status_code == 201: url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/containerApps/{}/sourcecontrols/current?api-version={}" request_url = url_fmt.format( management_hostname.strip('/'), sub_id, resource_group_name, name, api_version) return poll(cmd, request_url, "inprogress") return r.json()
def show_private_endpoint_connection(self, cmd, resource_group_name, resource_name, name): url = _build_connection_url_endpoint(resource_group_name, self.rp, resource_name, name, self.api_version) r = send_raw_request(cmd.cli_ctx, 'get', url) return r.json()
def confluent_offer_detail_show(cmd, publisher_id=None, offer_id=None): from azure.cli.core.util import send_raw_request from azure.cli.core.azclierror import ArgumentUsageError url = f"https://management.azure.com/providers/Microsoft.Marketplace/offers/{publisher_id}.{offer_id}?" \ "excludePublic=true&api-version=2018-08-01-beta" response = send_raw_request(cmd.cli_ctx, 'get', url) try: plans = response.json()['plans'] plans = [{ 'planId': plan['planId'], 'planName': plan['displayName'], 'offerId': offer_id, 'publisherId': publisher_id, 'termUnits': [{ 'price': item['price'], 'termDescription': item['termDescription'], 'termUnits': item['termUnits'] } for a in plan['availabilities'] for item in a['terms']] } for plan in plans] except KeyError as ex: raise ArgumentUsageError( 'Not able to get offer details for the provided publisher id and offer id.' ) from ex for plan in plans: for term in plan['termUnits']: if term['termUnits'] not in ['P1M', 'P1Y']: del term['termUnits'] return plans
def get_helm_registry(cmd, config_dp_endpoint, dp_endpoint_dogfood=None, release_train_dogfood=None): # Setting uri get_chart_location_url = "{}/{}/GetLatestHelmPackagePath?api-version=2019-11-01-preview".format(config_dp_endpoint, 'azure-arc-k8sagents') release_train = os.getenv('RELEASETRAIN') if os.getenv('RELEASETRAIN') else 'stable' if dp_endpoint_dogfood: get_chart_location_url = "{}/azure-arc-k8sagents/GetLatestHelmPackagePath?api-version=2019-11-01-preview".format(dp_endpoint_dogfood) if release_train_dogfood: release_train = release_train_dogfood uri_parameters = ["releaseTrain={}".format(release_train)] resource = cmd.cli_ctx.cloud.endpoints.active_directory_resource_id # Sending request try: r = send_raw_request(cmd.cli_ctx, 'post', get_chart_location_url, uri_parameters=uri_parameters, resource=resource) except Exception as e: telemetry.set_exception(exception=e, fault_type=consts.Get_HelmRegistery_Path_Fault_Type, summary='Error while fetching helm chart registry path') raise CLIError("Error while fetching helm chart registry path: " + str(e)) if r.content: try: return r.json().get('repositoryPath') except Exception as e: telemetry.set_exception(exception=e, fault_type=consts.Get_HelmRegistery_Path_Fault_Type, summary='Error while fetching helm chart registry path') raise CLIError("Error while fetching helm chart registry path from JSON response: " + str(e)) else: telemetry.set_exception(exception='No content in response', fault_type=consts.Get_HelmRegistery_Path_Fault_Type, summary='No content in acr path response') raise CLIError("No content was found in helm registry path response.")
def migration_create_func(cmd, client, resource_group_name, server_name, properties, migration_name=None): subscription_id = get_subscription_id(cmd.cli_ctx) properties_filepath = os.path.join(os.path.abspath(os.getcwd()), properties) if not os.path.exists(properties_filepath): raise FileOperationError( "Properties file does not exist in the given location") with open(properties_filepath, "r") as f: json_data = f.read() if migration_name is None: # Convert a UUID to a string of hex digits in standard form migration_name = str(uuid.uuid4()) r = send_raw_request( cmd.cli_ctx, "put", "https://management.azure.com/subscriptions/{}/resourceGroups/{}/providers/Microsoft.DBforPostgreSQL/flexibleServers/{}/migrations/{}?api-version=2020-02-14-privatepreview" .format(subscription_id, resource_group_name, server_name, migration_name), None, None, json_data) return r.json()
def delete(cls, cmd, resource_group_name, name, headers, no_wait=False): management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager api_version = STABLE_API_VERSION sub_id = get_subscription_id(cmd.cli_ctx) url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/containerApps/{}/sourcecontrols/current?api-version={}" request_url = url_fmt.format( management_hostname.strip('/'), sub_id, resource_group_name, name, api_version) r = send_raw_request(cmd.cli_ctx, "DELETE", request_url, headers=headers) if no_wait: return # API doesn't return JSON (it returns no content) elif r.status_code in [200, 201, 202, 204]: url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/containerApps/{}/sourcecontrols/current?api-version={}" request_url = url_fmt.format( management_hostname.strip('/'), sub_id, resource_group_name, name, api_version) if r.status_code == 202: from azure.cli.core.azclierror import ResourceNotFoundError try: poll(cmd, request_url, "cancelled") except ResourceNotFoundError: pass logger.warning('Containerapp github action successfully deleted') return
def _request(cls, cmd, resource_group, name, http_method="GET", body=None): management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager api_version = "2021-02-01" sub_id = get_subscription_id(cmd.cli_ctx) url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.Web/staticSites/{}?api-version={}" request_url = url_fmt.format(management_hostname.strip('/'), sub_id, resource_group, name, api_version) if body is not None: r = send_raw_request(cmd.cli_ctx, http_method, request_url, body=json.dumps(body)) else: r = send_raw_request(cmd.cli_ctx, http_method, request_url) return r
def get(cls, cmd, resource_group_name, container_app_name, auth_config_name): management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager api_version = STABLE_API_VERSION sub_id = get_subscription_id(cmd.cli_ctx) request_url = f"{management_hostname}subscriptions/{sub_id}/resourceGroups/{resource_group_name}/providers/Microsoft.App/containerApps/{container_app_name}/authConfigs/{auth_config_name}?api-version={api_version}" r = send_raw_request(cmd.cli_ctx, "GET", request_url) return r.json()
def list_private_endpoint_connection(self, cmd, resource_group_name, resource_name): if self.support_list: url = _build_connections_url_endpoint(resource_group_name, self.rp, resource_name, self.api_version) r = send_raw_request(cmd.cli_ctx, 'get', url) try: return r.json()['value'] except KeyError: pass return r.json() url = _build_resource_url_endpoint(resource_group_name, self.rp, resource_name, self.resource_get_api_version) r = send_raw_request(cmd.cli_ctx, 'get', url) return r.json()['properties']['privateEndpointConnections']
def list_private_link_resource(self, cmd, resource_group_name, name): url = _build_link_resource_url_endpoint(resource_group_name, self.rp, name, self.api_version) r = send_raw_request(cmd.cli_ctx, 'get', url) try: return r.json()['value'] except KeyError: pass return r.json()
def get_auth_token(cls, cmd, resource_group_name, name): management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager sub_id = get_subscription_id(cmd.cli_ctx) url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/containerApps/{}/authtoken?api-version={}" request_url = url_fmt.format(management_hostname.strip('/'), sub_id, resource_group_name, name, STABLE_API_VERSION) r = send_raw_request(cmd.cli_ctx, "POST", request_url) return r.json()
def show(cls, cmd, resource_group_name, name): management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager api_version = STABLE_API_VERSION sub_id = get_subscription_id(cmd.cli_ctx) url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/containerApps/{}/sourcecontrols/current?api-version={}" request_url = url_fmt.format(management_hostname.strip('/'), sub_id, resource_group_name, name, api_version) r = send_raw_request(cmd.cli_ctx, "GET", request_url) return r.json()
def is_auth_v2_app(cmd, resource_group_name, name, slot=None): resource_id = get_resource_id(cmd, resource_group_name, name, slot) management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager request_url = "{}/{}/{}?api-version={}".format( management_hostname.strip('/'), resource_id, "config/authSettings/list", "2020-12-01") # TODO: Replace ARM call with SDK API after fixing swagger issues r = send_raw_request(cmd.cli_ctx, "POST", request_url) return r.json()["properties"]["configVersion"] == "v2"
def show(cls, cmd, resource_group_name, environment_name, name): management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager api_version = PREVIEW_API_VERSION sub_id = get_subscription_id(cmd.cli_ctx) url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/managedEnvironments/{}/daprComponents/{}?api-version={}" request_url = url_fmt.format(management_hostname.strip('/'), sub_id, resource_group_name, environment_name, name, api_version) r = send_raw_request(cmd.cli_ctx, "GET", request_url) return r.json()
def remove_private_endpoint_connection(self, cmd, resource_group_name, resource_name, name): url = _build_connection_url_endpoint(resource_group_name, self.rp, resource_name, name, self.api_version) r = send_raw_request(cmd.cli_ctx, 'delete', url) if r.status_code in [201, 202, 204]: logger.warning( 'Deleting operation is asynchronous. ' 'Please use `az network private-endpoint-connection show to query the status.' )
def list_secrets(cls, cmd, resource_group_name, name): management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager api_version = PREVIEW_API_VERSION sub_id = get_subscription_id(cmd.cli_ctx) url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/containerApps/{}/listSecrets?api-version={}" request_url = url_fmt.format(management_hostname.strip('/'), sub_id, resource_group_name, name, api_version) r = send_raw_request(cmd.cli_ctx, "POST", request_url, body=None) return r.json()
def deactivate_revision(cls, cmd, resource_group_name, container_app_name, name): management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager api_version = NEW_API_VERSION sub_id = get_subscription_id(cmd.cli_ctx) url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/containerApps/{}/revisions/{}/deactivate?api-version={}" request_url = url_fmt.format(management_hostname.strip('/'), sub_id, resource_group_name, container_app_name, name, api_version) r = send_raw_request(cmd.cli_ctx, "POST", request_url) return r.json()
def migration_update_func(cmd, client, resource_group_name, server_name, migration_id, setup_logical_replication=None, db_names=None, overwrite_dbs=None, cutover=None): subscription_id = get_subscription_id(cmd.cli_ctx) operationSpecified = False if setup_logical_replication is True: operationSpecified = True properties = "{\"properties\": {\"setupLogicalReplicationOnSourceDBIfNeeded\": \"true\"} }" if db_names is not None: if operationSpecified is True: raise MutuallyExclusiveArgumentError( "Incorrect Usage: Can only specify one update operation.") operationSpecified = True prefix = "{ \"properties\": { \"dBsToMigrate\": [" db_names_str = "\"" + "\", \"".join(db_names) + "\"" suffix = "] } }" properties = prefix + db_names_str + suffix if overwrite_dbs is True: if operationSpecified is True: raise MutuallyExclusiveArgumentError( "Incorrect Usage: Can only specify one update operation.") operationSpecified = True properties = "{\"properties\": {\"overwriteDBsInTarget\": \"true\"} }" if cutover is True: if operationSpecified is True: raise MutuallyExclusiveArgumentError( "Incorrect Usage: Can only specify one update operation.") operationSpecified = True properties = "{\"properties\": {\"triggerCutover\": \"true\"} }" if operationSpecified is False: raise RequiredArgumentMissingError( "Incorrect Usage: Atleast one update operation needs to be specified." ) r = send_raw_request( cmd.cli_ctx, "patch", "https://management.azure.com/subscriptions/{}/resourceGroups/{}/providers/Microsoft.DBforPostgreSQL/flexibleServers/{}/migrations/{}?api-version=2020-02-14-privatepreview" .format(subscription_id, resource_group_name, server_name, migration_id), None, None, properties) return r.json()