diff --git a/doc/sphinx/azhelpgen/doc_source_map.json b/doc/sphinx/azhelpgen/doc_source_map.json index 36ce8a085bf..e394a321312 100644 --- a/doc/sphinx/azhelpgen/doc_source_map.json +++ b/doc/sphinx/azhelpgen/doc_source_map.json @@ -37,6 +37,7 @@ "provider": "src/command_modules/azure-cli-resource/azure/cli/command_modules/resource/_help.py", "rdbms": "src/command_modules/azure-cli-rdbms/azure/cli/command_modules/rdbms/_help.py", "redis": "src/command_modules/azure-cli-redis/azure/cli/command_modules/redis/_help.py", + "reservations": "src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/_help.py", "resource": "src/command_modules/azure-cli-resource/azure/cli/command_modules/resource/_help.py", "role": "src/command_modules/azure-cli-role/azure/cli/command_modules/role/_help.py", "sql": "src/command_modules/azure-cli-sql/azure/cli/command_modules/sql/_help.py", diff --git a/src/azure-cli/setup.py b/src/azure-cli/setup.py index 489634931fa..53eb5a15f2d 100644 --- a/src/azure-cli/setup.py +++ b/src/azure-cli/setup.py @@ -81,6 +81,7 @@ 'azure-cli-profile', 'azure-cli-rdbms', 'azure-cli-redis', + 'azure-cli-reservations', 'azure-cli-resource', 'azure-cli-role', 'azure-cli-sql', diff --git a/src/command_modules/azure-cli-reservations/HISTORY.rst b/src/command_modules/azure-cli-reservations/HISTORY.rst new file mode 100644 index 00000000000..22ad515b6cf --- /dev/null +++ b/src/command_modules/azure-cli-reservations/HISTORY.rst @@ -0,0 +1,9 @@ +.. :changelog: + +Release History +=============== + +0.1.0 ++++++ + +* Initial release. diff --git a/src/command_modules/azure-cli-reservations/MANIFEST.in b/src/command_modules/azure-cli-reservations/MANIFEST.in new file mode 100644 index 00000000000..f3eb9637aa5 --- /dev/null +++ b/src/command_modules/azure-cli-reservations/MANIFEST.in @@ -0,0 +1 @@ +include *.rst \ No newline at end of file diff --git a/src/command_modules/azure-cli-reservations/README.rst b/src/command_modules/azure-cli-reservations/README.rst new file mode 100644 index 00000000000..a9b0e6ddec4 --- /dev/null +++ b/src/command_modules/azure-cli-reservations/README.rst @@ -0,0 +1,5 @@ +Microsoft Azure CLI 'reservations' Command Module +================================================= + +This package is for the 'reservations' module. +i.e. 'az reservations' diff --git a/src/command_modules/azure-cli-reservations/azure/__init__.py b/src/command_modules/azure-cli-reservations/azure/__init__.py new file mode 100644 index 00000000000..a9dfa5391b9 --- /dev/null +++ b/src/command_modules/azure-cli-reservations/azure/__init__.py @@ -0,0 +1,7 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- + +import pkg_resources +pkg_resources.declare_namespace(__name__) diff --git a/src/command_modules/azure-cli-reservations/azure/cli/__init__.py b/src/command_modules/azure-cli-reservations/azure/cli/__init__.py new file mode 100644 index 00000000000..a9dfa5391b9 --- /dev/null +++ b/src/command_modules/azure-cli-reservations/azure/cli/__init__.py @@ -0,0 +1,7 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- + +import pkg_resources +pkg_resources.declare_namespace(__name__) diff --git a/src/command_modules/azure-cli-reservations/azure/cli/command_modules/__init__.py b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/__init__.py new file mode 100644 index 00000000000..a9dfa5391b9 --- /dev/null +++ b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/__init__.py @@ -0,0 +1,7 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- + +import pkg_resources +pkg_resources.declare_namespace(__name__) diff --git a/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/__init__.py b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/__init__.py new file mode 100644 index 00000000000..92e9247585c --- /dev/null +++ b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/__init__.py @@ -0,0 +1,14 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- + +import azure.cli.command_modules.reservations._help # pylint: disable=unused-import + + +def load_params(_): + import azure.cli.command_modules.reservations._params # pylint: disable=redefined-outer-name, unused-variable + + +def load_commands(): + import azure.cli.command_modules.reservations.commands # pylint: disable=redefined-outer-name, unused-variable diff --git a/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/_client_factory.py b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/_client_factory.py new file mode 100644 index 00000000000..2c7bd987586 --- /dev/null +++ b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/_client_factory.py @@ -0,0 +1,18 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- + + +def cf_reservations(**_): + from azure.cli.core.commands.client_factory import get_mgmt_service_client + from azure.mgmt.reservations.azure_reservation_api import AzureReservationAPI + return get_mgmt_service_client(AzureReservationAPI, subscription_bound=False) + + +def reservation_mgmt_client_factory(kwargs): + return cf_reservations(**kwargs).reservation + + +def reservation_order_mgmt_client_factory(kwargs): + return cf_reservations(**kwargs).reservation_order diff --git a/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/_exception_handler.py b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/_exception_handler.py new file mode 100644 index 00000000000..24699f5143b --- /dev/null +++ b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/_exception_handler.py @@ -0,0 +1,17 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- + +from azure.cli.core.util import CLIError + + +def reservations_exception_handler(ex): + from azure.mgmt.reservations.models import Error + if isinstance(ex, Error): + message = ex.error.error.message + raise CLIError(message) + else: + import sys + from six import reraise + reraise(*sys.exc_info()) diff --git a/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/_help.py b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/_help.py new file mode 100644 index 00000000000..d91885e5c51 --- /dev/null +++ b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/_help.py @@ -0,0 +1,156 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- + +from azure.cli.core.help_files import helps + +helps['reservations'] = """ + type: group + short-summary: Manage Azure Reservations. +""" + +helps['reservations catalog'] = """ + type: group + short-summary: See catalog of available reservations +""" + +helps['reservations reservation'] = """ + type: group + short-summary: Manage reservation entities +""" + +helps['reservations reservation-order'] = """ + type: group + short-summary: Manage reservation order, which is container for reservations +""" + +helps['reservations reservation-order-id'] = """ + type: group + short-summary: See reservation order ids that are applied to subscription +""" + +helps['reservations reservation-order list'] = """ + type: command + short-summary: Get all reservation orders + long-summary: | + List of all the reservation orders that the user has access to in the current tenant. +""" + +helps['reservations reservation-order show'] = """ + type: command + short-summary: Get a specific reservation order. + long-summary: Get the details of the reservation order. + parameters: + - name: --reservation-order-id + type: string + short-summary: Id of reservation order to look up +""" + +helps['reservations reservation-order-id list'] = """ + type: command + short-summary: Get list of applicable reservation order ids. + long-summary: | + Get applicable reservations that are applied to this subscription. + parameters: + - name: --subscription-id + type: string + short-summary: Id of the subscription to look up applied reservations +""" + +helps['reservations catalog show'] = """ + type: command + short-summary: Get catalog of available reservation. + long-summary: | + Get the regions and skus that are available for RI purchase for the specified Azure subscription. + parameters: + - name: --subscription-id + type: string + short-summary: Id of the subscription to get the catalog for +""" + +helps['reservations reservation list'] = """ + type: command + short-summary: Get all reservations. + long-summary: | + List all reservations within a reservation order. + parameters: + - name: --reservation-order-id + type: string + short-summary: Id of container reservation order +""" + +helps['reservations reservation show'] = """ + type: command + short-summary: Get details of a reservation. + parameters: + - name: --reservation-order-id + type: string + short-summary: Order id of reservation to look up + - name: --reservation-id + type: string + short-summary: Reservation id of reservation to look up +""" + +helps['reservations reservation update'] = """ + type: command + short-summary: Updates the applied scopes of the reservation. + parameters: + - name: --reservation-order-id + type: string + short-summary: Order id of reservation to update + - name: --reservation-id + type: string + short-summary: Reservation id of reservation to update + - name: --applied-scope-type -t + type: string + short-summary: 'Type is either Single or Shared' + - name: --applied-scopes -s + type: string + short-summary: 'If applied scope type is Single, this field must be provided' +""" + +helps['reservations reservation split'] = """ + type: command + short-summary: Split a reservation. + parameters: + - name: --reservation-order-id + type: string + short-summary: Order id of original reservation + - name: --reservation-id + type: string + short-summary: Reservation id of original reservation + - name: --quantity-1 -1 + type: int + short-summary: Quantity of the first reservation that will be created from split operation + - name: --quantity-2 -2 + type: int + short-summary: Quantity of the second reservation that will be created from split operation +""" + +helps['reservations reservation merge'] = """ + type: command + short-summary: Merge two reservations. + parameters: + - name: --reservation-order-id + type: string + short-summary: Order id of original reservation + - name: --reservation-id-1 -1 + type: string + short-summary: Id of the first reservation to merge + - name: --reservation-id-2 -2 + type: string + short-summary: Id of the second reservation to merge +""" + +helps['reservations reservation list-history'] = """ + type: command + short-summary: Get history of a reservation. + parameters: + - name: --reservation-order-id + type: string + short-summary: Order id of the reservation + - name: --reservation-id + type: string + short-summary: Reservation id of the reservation +""" diff --git a/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/_params.py b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/_params.py new file mode 100644 index 00000000000..da935af54f7 --- /dev/null +++ b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/_params.py @@ -0,0 +1,14 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- + +# pylint: disable=line-too-long +from azure.cli.core.commands import register_cli_argument + +register_cli_argument('reservations reservation update', 'applied_scope_type', options_list=('--applied-scope-type', '-t'), required=True) +register_cli_argument('reservations reservation update', 'applied_scopes', options_list=('--applied-scopes', '-s')) +register_cli_argument('reservations reservation split', 'quantity_1', options_list=('--quantity-1', '-1'), required=True) +register_cli_argument('reservations reservation split', 'quantity_2', options_list=('--quantity-2', '-2'), required=True) +register_cli_argument('reservations reservation merge', 'reservation_id_1', options_list=('--reservation-id-1', '-1'), required=True) +register_cli_argument('reservations reservation merge', 'reservation_id_2', options_list=('--reservation-id-2', '-2'), required=True) diff --git a/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/commands.py b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/commands.py new file mode 100644 index 00000000000..142d2dd9259 --- /dev/null +++ b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/commands.py @@ -0,0 +1,31 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- + +# pylint: disable=line-too-long + +from azure.cli.core.commands import cli_command +from azure.cli.command_modules.reservations._client_factory import reservation_mgmt_client_factory, reservation_order_mgmt_client_factory +from ._exception_handler import reservations_exception_handler + +reservation_path = 'azure.mgmt.reservations.operations.reservation_operations#' +reservation_order_path = 'azure.mgmt.reservations.operations.reservation_order_operations#' +custom_path = 'azure.cli.command_modules.reservations.custom#' +reservation_client_path = 'azure.mgmt.reservations.azure_reservation_api#' + + +def reservation_command(*args, **kwargs): + cli_command(*args, exception_handler=reservations_exception_handler, **kwargs) + + +reservation_command(__name__, 'reservations reservation-order list', reservation_order_path + 'ReservationOrderOperations.list', reservation_order_mgmt_client_factory) +reservation_command(__name__, 'reservations reservation-order show', reservation_order_path + 'ReservationOrderOperations.get', reservation_order_mgmt_client_factory) +reservation_command(__name__, 'reservations reservation-order-id list', reservation_client_path + 'AzureReservationAPI.get_applied_reservation_list', reservation_order_mgmt_client_factory) +reservation_command(__name__, 'reservations catalog show', reservation_client_path + 'AzureReservationAPI.get_catalog', reservation_order_mgmt_client_factory) +reservation_command(__name__, 'reservations reservation list', reservation_path + 'ReservationOperations.list', reservation_mgmt_client_factory) +reservation_command(__name__, 'reservations reservation show', reservation_path + 'ReservationOperations.get', reservation_mgmt_client_factory) +reservation_command(__name__, 'reservations reservation update', custom_path + 'cli_reservation_update_reservation', reservation_mgmt_client_factory) +reservation_command(__name__, 'reservations reservation split', custom_path + 'cli_reservation_split_reservation', reservation_mgmt_client_factory) +reservation_command(__name__, 'reservations reservation merge', custom_path + 'cli_reservation_merge_reservation', reservation_mgmt_client_factory) +reservation_command(__name__, 'reservations reservation list-history', reservation_path + 'ReservationOperations.list_revisions', reservation_mgmt_client_factory) diff --git a/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/custom.py b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/custom.py new file mode 100644 index 00000000000..2158019e131 --- /dev/null +++ b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/custom.py @@ -0,0 +1,33 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- + +from azure.mgmt.reservations.models.patch import Patch +from azure.mgmt.reservations.models.split_request import SplitRequest +from azure.mgmt.reservations.models.merge_request import MergeRequest + + +def cli_reservation_update_reservation(client, reservation_order_id, reservation_id, + applied_scope_type, applied_scopes=None): + if applied_scopes: + patch = Patch(applied_scope_type, [applied_scopes]) + else: + patch = Patch(applied_scope_type) + return client.update(reservation_order_id, reservation_id, patch) + + +def create_resource_id(reservation_order_id, reservation_id): + template = '/providers/Microsoft.Capacity/reservationOrders/{0}/reservations/{1}' + return template.format(reservation_order_id, reservation_id) + + +def cli_reservation_split_reservation(client, reservation_order_id, reservation_id, quantity_1, quantity_2): + split = SplitRequest([quantity_1, quantity_2], create_resource_id(reservation_order_id, reservation_id)) + return client.split(reservation_order_id, split) + + +def cli_reservation_merge_reservation(client, reservation_order_id, reservation_id_1, reservation_id_2): + merge = MergeRequest([create_resource_id(reservation_order_id, reservation_id_1), + create_resource_id(reservation_order_id, reservation_id_2)]) + return client.merge(reservation_order_id, merge) diff --git a/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/tests/recordings/latest/test_get_applied_reservation_order_ids.yaml b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/tests/recordings/latest/test_get_applied_reservation_order_ids.yaml new file mode 100644 index 00000000000..63921a80ff1 --- /dev/null +++ b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/tests/recordings/latest/test_get_applied_reservation_order_ids.yaml @@ -0,0 +1,30 @@ +interactions: +- request: + body: null + headers: + Accept: [application/json] + Accept-Encoding: ['gzip, deflate'] + CommandName: [reservations reservation-order-id list] + Connection: [keep-alive] + Content-Type: [application/json; charset=utf-8] + User-Agent: [python/3.5.4 (Windows-10-10.0.14393-SP0) requests/2.18.4 msrest/0.4.18 + msrest_azure/0.4.16 azurereservationapi/0.1.0 Azure-SDK-For-Python AZURECLI/2.0.21] + accept-language: [en-US] + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Capacity/appliedReservations?api-version=2017-11-01 + response: + body: {string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/microsoft.capacity/AppliedReservations/default","type":"Microsoft.Capacity/AppliedReservations","name":"default","properties":{"reservationOrderIds":{"value":["/providers/Microsoft.Capacity/reservationorders/f8dc1a06-c795-4513-b387-11416b058f51","/providers/Microsoft.Capacity/reservationorders/8c165114-9981-4e50-9cf2-da5145f1a9a5","/providers/Microsoft.Capacity/reservationorders/86d9870a-bf1e-4635-94c8-b0f08932bc3a"]}}}'} + headers: + cache-control: [no-cache] + content-length: ['492'] + content-type: [application/json; charset=utf-8] + date: ['Mon, 06 Nov 2017 19:00:14 GMT'] + expires: ['-1'] + pragma: [no-cache] + server: [Microsoft-IIS/8.5] + strict-transport-security: [max-age=31536000; includeSubDomains] + transfer-encoding: [chunked] + vary: ['Accept-Encoding,Accept-Encoding'] + x-content-type-options: [nosniff] + status: {code: 200, message: OK} +version: 1 diff --git a/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/tests/recordings/latest/test_get_catalog.yaml b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/tests/recordings/latest/test_get_catalog.yaml new file mode 100644 index 00000000000..e06af5e6749 --- /dev/null +++ b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/tests/recordings/latest/test_get_catalog.yaml @@ -0,0 +1,31 @@ +interactions: +- request: + body: null + headers: + Accept: [application/json] + Accept-Encoding: ['gzip, deflate'] + CommandName: [reservations catalog show] + Connection: [keep-alive] + Content-Type: [application/json; charset=utf-8] + User-Agent: [python/3.5.4 (Windows-10-10.0.14393-SP0) requests/2.18.4 msrest/0.4.18 + msrest_azure/0.4.16 azurereservationapi/0.1.0 Azure-SDK-For-Python AZURECLI/2.0.21] + accept-language: [en-US] + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Capacity/catalogs?api-version=2017-11-01 + response: + body: {string: '[{"capabilities": null,"locations": ["eastus"],"name": "Standard_DS3_v2","resourceType": "virtualMachines","restrictions": [],"size": "DS3_v2","terms": ["P1Y","P3Y"],"tier": "Standard"},{"capabilities": null,"locations": ["eastus"],"name": "Standard_DS2_v2","resourceType": "virtualMachines","restrictions": [],"size": "DS2_v2","terms": ["P1Y","P3Y"],"tier": "Standard"},{"capabilities": null,"locations": ["eastus"],"name": "Standard_DS1_v2","resourceType": "virtualMachines","restrictions": [],"size": "DS1_v2","terms": ["P1Y","P3Y"],"tier": "Standard"}]' +} + headers: + cache-control: [no-cache] + content-length: ['293720'] + content-type: [application/json; charset=utf-8] + date: ['Mon, 06 Nov 2017 21:56:45 GMT'] + expires: ['-1'] + pragma: [no-cache] + server: [Microsoft-IIS/8.5] + strict-transport-security: [max-age=31536000; includeSubDomains] + transfer-encoding: [chunked] + vary: ['Accept-Encoding,Accept-Encoding'] + x-content-type-options: [nosniff] + status: {code: 200, message: OK} +version: 1 diff --git a/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/tests/recordings/latest/test_get_reservation.yaml b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/tests/recordings/latest/test_get_reservation.yaml new file mode 100644 index 00000000000..31ec2301a5b --- /dev/null +++ b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/tests/recordings/latest/test_get_reservation.yaml @@ -0,0 +1,30 @@ +interactions: +- request: + body: null + headers: + Accept: [application/json] + Accept-Encoding: ['gzip, deflate'] + CommandName: [reservations reservation show] + Connection: [keep-alive] + Content-Type: [application/json; charset=utf-8] + User-Agent: [python/3.5.4 (Windows-10-10.0.14393-SP0) requests/2.18.4 msrest/0.4.18 + msrest_azure/0.4.16 azurereservationapi/0.1.0 Azure-SDK-For-Python AZURECLI/2.0.21] + accept-language: [en-US] + method: GET + uri: https://management.azure.com/providers/Microsoft.Capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/0532ae1c-3c80-48a9-ae18-19cc2b6f4791?api-version=2017-11-01 + response: + body: {string: '{"sku":{"name":"Standard_DS1"},"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/0532ae1c-3c80-48a9-ae18-19cc2b6f4791","type":"Microsoft.Capacity/reservationOrders/reservations","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a/0532ae1c-3c80-48a9-ae18-19cc2b6f4791","etag":2,"kind":"Microsoft.Compute","location":"japaneast","properties":{"appliedScopes":["/subscriptions/00000000-0000-0000-0000-000000000000"],"appliedScopeType":"Single","quantity":3,"provisioningState":"Succeeded","expiryDate":"2018-11-02","displayName":"hyo_TestYong","effectiveDateTime":"2017-11-06T18:34:04.8870098Z","lastUpdatedDateTime":"2017-11-06T18:34:09.6682436Z","splitProperties":{"splitSource":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/a5748744-7432-477d-bc3c-b5f734be5f8d"}}}'} + headers: + cache-control: [no-cache] + content-length: ['864'] + content-type: [application/json; charset=utf-8] + date: ['Mon, 06 Nov 2017 21:41:31 GMT'] + expires: ['-1'] + pragma: [no-cache] + server: [Microsoft-IIS/8.5] + strict-transport-security: [max-age=31536000; includeSubDomains] + transfer-encoding: [chunked] + vary: ['Accept-Encoding,Accept-Encoding'] + x-content-type-options: [nosniff] + status: {code: 200, message: OK} +version: 1 diff --git a/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/tests/recordings/latest/test_get_reservation_order.yaml b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/tests/recordings/latest/test_get_reservation_order.yaml new file mode 100644 index 00000000000..2278a9c7e26 --- /dev/null +++ b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/tests/recordings/latest/test_get_reservation_order.yaml @@ -0,0 +1,30 @@ +interactions: +- request: + body: null + headers: + Accept: [application/json] + Accept-Encoding: ['gzip, deflate'] + CommandName: [reservations reservation-order show] + Connection: [keep-alive] + Content-Type: [application/json; charset=utf-8] + User-Agent: [python/3.5.4 (Windows-10-10.0.14393-SP0) requests/2.18.4 msrest/0.4.18 + msrest_azure/0.4.16 azurereservationapi/0.1.0 Azure-SDK-For-Python AZURECLI/2.0.21] + accept-language: [en-US] + method: GET + uri: https://management.azure.com/providers/Microsoft.Capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a?api-version=2017-11-01 + response: + body: {string: '{"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a","type":"Microsoft.Capacity/reservationOrders","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a","etag":16,"properties":{"displayName":"hyo_TestYong","requestDateTime":"2017-11-02T19:38:26.684952Z","createdDateTime":"2017-11-02T19:42:55.5893862Z","expiryDate":"2018-11-02","term":"P1Y","provisioningState":"Succeeded","reservations":[{"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/b17accea-8a13-4a80-9ca9-cc3bb7772f39"},{"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/36beb8e4-db5f-4502-ae42-630e464a5437"},{"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/7f08f1bc-0f4a-4bb7-9d50-d1d8d656179b"},{"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/97830c1b-372b-4787-8b86-a54eb55be675"},{"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/c4d9378b-b98e-4e95-9b8f-c3025663c854"},{"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/9b84716e-9cb2-4651-bb4d-e4e8619ebd7b"},{"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/fd31d466-7f10-48c7-98ab-be52e5f2dac8"},{"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/211e6c2c-32ee-4f6f-b101-620888e5be39"},{"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/d1c424c4-f30f-403a-a900-e9f5f36bb57c"},{"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/1b98862a-6ae2-4c20-ade6-dd55322994b4"},{"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/770a14fc-e075-4583-afe3-af486bce2cea"},{"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/3bc6c3ec-5678-4838-aabb-513ddef65bfc"},{"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/a5748744-7432-477d-bc3c-b5f734be5f8d"},{"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/09ee4b20-caad-489c-ace1-523e06a8584e"},{"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/0532ae1c-3c80-48a9-ae18-19cc2b6f4791"}],"originalQuantity":5}}'} + headers: + cache-control: [no-cache] + content-length: ['2605'] + content-type: [application/json; charset=utf-8] + date: ['Mon, 06 Nov 2017 21:32:39 GMT'] + expires: ['-1'] + pragma: [no-cache] + server: [Microsoft-IIS/8.5] + strict-transport-security: [max-age=31536000; includeSubDomains] + transfer-encoding: [chunked] + vary: ['Accept-Encoding,Accept-Encoding'] + x-content-type-options: [nosniff] + status: {code: 200, message: OK} +version: 1 diff --git a/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/tests/recordings/latest/test_list_reservation.yaml b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/tests/recordings/latest/test_list_reservation.yaml new file mode 100644 index 00000000000..05c32af4822 --- /dev/null +++ b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/tests/recordings/latest/test_list_reservation.yaml @@ -0,0 +1,43 @@ +interactions: +- request: + body: null + headers: + Accept: [application/json] + Accept-Encoding: ['gzip, deflate'] + CommandName: [reservations reservation list] + Connection: [keep-alive] + Content-Type: [application/json; charset=utf-8] + User-Agent: [python/3.5.4 (Windows-10-10.0.14393-SP0) requests/2.18.4 msrest/0.4.18 + msrest_azure/0.4.16 azurereservationapi/0.1.0 Azure-SDK-For-Python AZURECLI/2.0.21] + accept-language: [en-US] + method: GET + uri: https://management.azure.com/providers/Microsoft.Capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations?api-version=2017-11-01 + response: + body: {string: '{"value":[{"sku":{"name":"Standard_DS1"},"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/b17accea-8a13-4a80-9ca9-cc3bb7772f39","type":"Microsoft.Capacity/reservationOrders/reservations","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a/b17accea-8a13-4a80-9ca9-cc3bb7772f39","etag":10,"kind":"Microsoft.Compute","location":"japaneast","properties":{"appliedScopes":["/subscriptions/00000000-0000-0000-0000-000000000000"],"appliedScopeType":"Single","quantity":5,"provisioningState":"Cancelled","expiryDate":"2018-11-02","displayName":"hyo_TestYong","effectiveDateTime":"2017-11-02T23:35:10.7654585Z","extendedStatusInfo":{"statusCode":"Split","message":"This + reservation was split and is no longer active."},"lastUpdatedDateTime":"2017-11-02T23:35:16.7966447Z","splitProperties":{"splitDestinations":["/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/36beb8e4-db5f-4502-ae42-630e464a5437","/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/7f08f1bc-0f4a-4bb7-9d50-d1d8d656179b"]}}},{"sku":{"name":"Standard_DS1"},"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/36beb8e4-db5f-4502-ae42-630e464a5437","type":"Microsoft.Capacity/reservationOrders/reservations","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a/36beb8e4-db5f-4502-ae42-630e464a5437","etag":5,"kind":"Microsoft.Compute","location":"japaneast","properties":{"appliedScopes":["/subscriptions/00000000-0000-0000-0000-000000000000"],"appliedScopeType":"Single","quantity":2,"provisioningState":"Cancelled","expiryDate":"2018-11-02","displayName":"hyo_TestYong","effectiveDateTime":"2017-11-02T23:39:36.6014952Z","extendedStatusInfo":{"statusCode":"Merged","message":"This + reservation was merged and is no longer active."},"lastUpdatedDateTime":"2017-11-02T23:39:36.6014952Z","splitProperties":{"splitSource":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/b17accea-8a13-4a80-9ca9-cc3bb7772f39"},"mergeProperties":{"mergeDestination":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/97830c1b-372b-4787-8b86-a54eb55be675"}}},{"sku":{"name":"Standard_DS1"},"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/7f08f1bc-0f4a-4bb7-9d50-d1d8d656179b","type":"Microsoft.Capacity/reservationOrders/reservations","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a/7f08f1bc-0f4a-4bb7-9d50-d1d8d656179b","etag":4,"kind":"Microsoft.Compute","location":"japaneast","properties":{"appliedScopes":["/subscriptions/00000000-0000-0000-0000-000000000000"],"appliedScopeType":"Single","quantity":3,"provisioningState":"Cancelled","expiryDate":"2018-11-02","displayName":"hyo_TestYong","effectiveDateTime":"2017-11-02T23:39:36.6014952Z","extendedStatusInfo":{"statusCode":"Merged","message":"This + reservation was merged and is no longer active."},"lastUpdatedDateTime":"2017-11-02T23:39:36.6014952Z","splitProperties":{"splitSource":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/b17accea-8a13-4a80-9ca9-cc3bb7772f39"},"mergeProperties":{"mergeDestination":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/97830c1b-372b-4787-8b86-a54eb55be675"}}},{"sku":{"name":"Standard_DS1"},"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/97830c1b-372b-4787-8b86-a54eb55be675","type":"Microsoft.Capacity/reservationOrders/reservations","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a/97830c1b-372b-4787-8b86-a54eb55be675","etag":5,"kind":"Microsoft.Compute","location":"japaneast","properties":{"appliedScopes":["/subscriptions/00000000-0000-0000-0000-000000000000"],"appliedScopeType":"Single","quantity":5,"provisioningState":"Cancelled","expiryDate":"2018-11-02","displayName":"hyo_TestYong","effectiveDateTime":"2017-11-02T23:41:56.5483119Z","extendedStatusInfo":{"statusCode":"Split","message":"This + reservation was split and is no longer active."},"lastUpdatedDateTime":"2017-11-02T23:42:01.1972545Z","splitProperties":{"splitDestinations":["/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/c4d9378b-b98e-4e95-9b8f-c3025663c854","/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/9b84716e-9cb2-4651-bb4d-e4e8619ebd7b"]},"mergeProperties":{"mergeSources":["/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/36beb8e4-db5f-4502-ae42-630e464a5437","/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/7f08f1bc-0f4a-4bb7-9d50-d1d8d656179b"]}}},{"sku":{"name":"Standard_DS1"},"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/c4d9378b-b98e-4e95-9b8f-c3025663c854","type":"Microsoft.Capacity/reservationOrders/reservations","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a/c4d9378b-b98e-4e95-9b8f-c3025663c854","etag":5,"kind":"Microsoft.Compute","location":"japaneast","properties":{"appliedScopes":["/subscriptions/00000000-0000-0000-0000-000000000000"],"appliedScopeType":"Single","quantity":2,"provisioningState":"Cancelled","expiryDate":"2018-11-02","displayName":"hyo_TestYong","effectiveDateTime":"2017-11-06T06:17:35.8628591Z","extendedStatusInfo":{"statusCode":"Merged","message":"This + reservation was merged and is no longer active."},"lastUpdatedDateTime":"2017-11-06T06:17:35.8628591Z","splitProperties":{"splitSource":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/97830c1b-372b-4787-8b86-a54eb55be675"},"mergeProperties":{"mergeDestination":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/fd31d466-7f10-48c7-98ab-be52e5f2dac8"}}},{"sku":{"name":"Standard_DS1"},"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/9b84716e-9cb2-4651-bb4d-e4e8619ebd7b","type":"Microsoft.Capacity/reservationOrders/reservations","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a/9b84716e-9cb2-4651-bb4d-e4e8619ebd7b","etag":4,"kind":"Microsoft.Compute","location":"japaneast","properties":{"appliedScopes":["/subscriptions/00000000-0000-0000-0000-000000000000"],"appliedScopeType":"Single","quantity":3,"provisioningState":"Cancelled","expiryDate":"2018-11-02","displayName":"hyo_TestYong","effectiveDateTime":"2017-11-06T06:17:35.8628591Z","extendedStatusInfo":{"statusCode":"Merged","message":"This + reservation was merged and is no longer active."},"lastUpdatedDateTime":"2017-11-06T06:17:35.8628591Z","splitProperties":{"splitSource":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/97830c1b-372b-4787-8b86-a54eb55be675"},"mergeProperties":{"mergeDestination":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/fd31d466-7f10-48c7-98ab-be52e5f2dac8"}}},{"sku":{"name":"Standard_DS1"},"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/fd31d466-7f10-48c7-98ab-be52e5f2dac8","type":"Microsoft.Capacity/reservationOrders/reservations","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a/fd31d466-7f10-48c7-98ab-be52e5f2dac8","etag":5,"kind":"Microsoft.Compute","location":"japaneast","properties":{"appliedScopes":["/subscriptions/00000000-0000-0000-0000-000000000000"],"appliedScopeType":"Single","quantity":5,"provisioningState":"Cancelled","expiryDate":"2018-11-02","displayName":"hyo_TestYong","effectiveDateTime":"2017-11-06T18:07:47.5122373Z","extendedStatusInfo":{"statusCode":"Split","message":"This + reservation was split and is no longer active."},"lastUpdatedDateTime":"2017-11-06T18:07:53.543412Z","splitProperties":{"splitDestinations":["/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/211e6c2c-32ee-4f6f-b101-620888e5be39","/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/d1c424c4-f30f-403a-a900-e9f5f36bb57c"]},"mergeProperties":{"mergeSources":["/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/c4d9378b-b98e-4e95-9b8f-c3025663c854","/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/9b84716e-9cb2-4651-bb4d-e4e8619ebd7b"]}}},{"sku":{"name":"Standard_DS1"},"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/211e6c2c-32ee-4f6f-b101-620888e5be39","type":"Microsoft.Capacity/reservationOrders/reservations","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a/211e6c2c-32ee-4f6f-b101-620888e5be39","etag":5,"kind":"Microsoft.Compute","location":"japaneast","properties":{"appliedScopes":["/subscriptions/00000000-0000-0000-0000-000000000000"],"appliedScopeType":"Single","quantity":2,"provisioningState":"Cancelled","expiryDate":"2018-11-02","displayName":"hyo_TestYong","effectiveDateTime":"2017-11-06T18:10:32.3498846Z","extendedStatusInfo":{"statusCode":"Merged","message":"This + reservation was merged and is no longer active."},"lastUpdatedDateTime":"2017-11-06T18:10:32.3498846Z","splitProperties":{"splitSource":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/fd31d466-7f10-48c7-98ab-be52e5f2dac8"},"mergeProperties":{"mergeDestination":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/1b98862a-6ae2-4c20-ade6-dd55322994b4"}}},{"sku":{"name":"Standard_DS1"},"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/d1c424c4-f30f-403a-a900-e9f5f36bb57c","type":"Microsoft.Capacity/reservationOrders/reservations","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a/d1c424c4-f30f-403a-a900-e9f5f36bb57c","etag":4,"kind":"Microsoft.Compute","location":"japaneast","properties":{"appliedScopes":["/subscriptions/00000000-0000-0000-0000-000000000000"],"appliedScopeType":"Single","quantity":3,"provisioningState":"Cancelled","expiryDate":"2018-11-02","displayName":"hyo_TestYong","effectiveDateTime":"2017-11-06T18:10:32.3498846Z","extendedStatusInfo":{"statusCode":"Merged","message":"This + reservation was merged and is no longer active."},"lastUpdatedDateTime":"2017-11-06T18:10:32.3498846Z","splitProperties":{"splitSource":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/fd31d466-7f10-48c7-98ab-be52e5f2dac8"},"mergeProperties":{"mergeDestination":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/1b98862a-6ae2-4c20-ade6-dd55322994b4"}}},{"sku":{"name":"Standard_DS1"},"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/1b98862a-6ae2-4c20-ade6-dd55322994b4","type":"Microsoft.Capacity/reservationOrders/reservations","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a/1b98862a-6ae2-4c20-ade6-dd55322994b4","etag":5,"kind":"Microsoft.Compute","location":"japaneast","properties":{"appliedScopes":["/subscriptions/00000000-0000-0000-0000-000000000000"],"appliedScopeType":"Single","quantity":5,"provisioningState":"Cancelled","expiryDate":"2018-11-02","displayName":"hyo_TestYong","effectiveDateTime":"2017-11-06T18:11:34.2984722Z","extendedStatusInfo":{"statusCode":"Split","message":"This + reservation was split and is no longer active."},"lastUpdatedDateTime":"2017-11-06T18:11:37.5953464Z","splitProperties":{"splitDestinations":["/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/770a14fc-e075-4583-afe3-af486bce2cea","/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/3bc6c3ec-5678-4838-aabb-513ddef65bfc"]},"mergeProperties":{"mergeSources":["/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/211e6c2c-32ee-4f6f-b101-620888e5be39","/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/d1c424c4-f30f-403a-a900-e9f5f36bb57c"]}}},{"sku":{"name":"Standard_DS1"},"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/770a14fc-e075-4583-afe3-af486bce2cea","type":"Microsoft.Capacity/reservationOrders/reservations","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a/770a14fc-e075-4583-afe3-af486bce2cea","etag":5,"kind":"Microsoft.Compute","location":"japaneast","properties":{"appliedScopes":["/subscriptions/00000000-0000-0000-0000-000000000000"],"appliedScopeType":"Single","quantity":2,"provisioningState":"Cancelled","expiryDate":"2018-11-02","displayName":"hyo_TestYong","effectiveDateTime":"2017-11-06T18:11:55.4522619Z","extendedStatusInfo":{"statusCode":"Merged","message":"This + reservation was merged and is no longer active."},"lastUpdatedDateTime":"2017-11-06T18:11:55.4522619Z","splitProperties":{"splitSource":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/1b98862a-6ae2-4c20-ade6-dd55322994b4"},"mergeProperties":{"mergeDestination":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/a5748744-7432-477d-bc3c-b5f734be5f8d"}}},{"sku":{"name":"Standard_DS1"},"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/3bc6c3ec-5678-4838-aabb-513ddef65bfc","type":"Microsoft.Capacity/reservationOrders/reservations","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a/3bc6c3ec-5678-4838-aabb-513ddef65bfc","etag":4,"kind":"Microsoft.Compute","location":"japaneast","properties":{"appliedScopes":["/subscriptions/00000000-0000-0000-0000-000000000000"],"appliedScopeType":"Single","quantity":3,"provisioningState":"Cancelled","expiryDate":"2018-11-02","displayName":"hyo_TestYong","effectiveDateTime":"2017-11-06T18:11:55.4522619Z","extendedStatusInfo":{"statusCode":"Merged","message":"This + reservation was merged and is no longer active."},"lastUpdatedDateTime":"2017-11-06T18:11:55.4522619Z","splitProperties":{"splitSource":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/1b98862a-6ae2-4c20-ade6-dd55322994b4"},"mergeProperties":{"mergeDestination":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/a5748744-7432-477d-bc3c-b5f734be5f8d"}}},{"sku":{"name":"Standard_DS1"},"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/a5748744-7432-477d-bc3c-b5f734be5f8d","type":"Microsoft.Capacity/reservationOrders/reservations","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a/a5748744-7432-477d-bc3c-b5f734be5f8d","etag":5,"kind":"Microsoft.Compute","location":"japaneast","properties":{"appliedScopes":["/subscriptions/00000000-0000-0000-0000-000000000000"],"appliedScopeType":"Single","quantity":5,"provisioningState":"Cancelled","expiryDate":"2018-11-02","displayName":"hyo_TestYong","effectiveDateTime":"2017-11-06T18:34:04.8870098Z","extendedStatusInfo":{"statusCode":"Split","message":"This + reservation was split and is no longer active."},"lastUpdatedDateTime":"2017-11-06T18:34:09.6682436Z","splitProperties":{"splitDestinations":["/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/09ee4b20-caad-489c-ace1-523e06a8584e","/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/0532ae1c-3c80-48a9-ae18-19cc2b6f4791"]},"mergeProperties":{"mergeSources":["/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/770a14fc-e075-4583-afe3-af486bce2cea","/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/3bc6c3ec-5678-4838-aabb-513ddef65bfc"]}}},{"sku":{"name":"Standard_DS1"},"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/09ee4b20-caad-489c-ace1-523e06a8584e","type":"Microsoft.Capacity/reservationOrders/reservations","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a/09ee4b20-caad-489c-ace1-523e06a8584e","etag":2,"kind":"Microsoft.Compute","location":"japaneast","properties":{"appliedScopes":["/subscriptions/00000000-0000-0000-0000-000000000000"],"appliedScopeType":"Single","quantity":2,"provisioningState":"Succeeded","expiryDate":"2018-11-02","displayName":"hyo_TestYong","effectiveDateTime":"2017-11-06T18:34:04.8870098Z","lastUpdatedDateTime":"2017-11-06T18:34:09.6682436Z","splitProperties":{"splitSource":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/a5748744-7432-477d-bc3c-b5f734be5f8d"}}},{"sku":{"name":"Standard_DS1"},"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/0532ae1c-3c80-48a9-ae18-19cc2b6f4791","type":"Microsoft.Capacity/reservationOrders/reservations","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a/0532ae1c-3c80-48a9-ae18-19cc2b6f4791","etag":2,"kind":"Microsoft.Compute","location":"japaneast","properties":{"appliedScopes":["/subscriptions/00000000-0000-0000-0000-000000000000"],"appliedScopeType":"Single","quantity":3,"provisioningState":"Succeeded","expiryDate":"2018-11-02","displayName":"hyo_TestYong","effectiveDateTime":"2017-11-06T18:34:04.8870098Z","lastUpdatedDateTime":"2017-11-06T18:34:09.6682436Z","splitProperties":{"splitSource":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/a5748744-7432-477d-bc3c-b5f734be5f8d"}}}]}'} + headers: + cache-control: [no-cache] + content-length: ['17783'] + content-type: [application/json; charset=utf-8] + date: ['Mon, 06 Nov 2017 21:39:22 GMT'] + expires: ['-1'] + pragma: [no-cache] + server: [Microsoft-IIS/8.5] + strict-transport-security: [max-age=31536000; includeSubDomains] + transfer-encoding: [chunked] + vary: ['Accept-Encoding,Accept-Encoding'] + x-content-type-options: [nosniff] + status: {code: 200, message: OK} +version: 1 diff --git a/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/tests/recordings/latest/test_list_reservation_history.yaml b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/tests/recordings/latest/test_list_reservation_history.yaml new file mode 100644 index 00000000000..4f149ca8fa4 --- /dev/null +++ b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/tests/recordings/latest/test_list_reservation_history.yaml @@ -0,0 +1,30 @@ +interactions: +- request: + body: null + headers: + Accept: [application/json] + Accept-Encoding: ['gzip, deflate'] + CommandName: [reservations reservation list-history] + Connection: [keep-alive] + Content-Type: [application/json; charset=utf-8] + User-Agent: [python/3.5.4 (Windows-10-10.0.14393-SP0) requests/2.18.4 msrest/0.4.18 + msrest_azure/0.4.16 azurereservationapi/0.1.0 Azure-SDK-For-Python AZURECLI/2.0.21] + accept-language: [en-US] + method: GET + uri: https://management.azure.com/providers/Microsoft.Capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/0532ae1c-3c80-48a9-ae18-19cc2b6f4791/revisions?api-version=2017-11-01 + response: + body: {string: '{"value":[{"sku":{"name":"Standard_DS1"},"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/0532ae1c-3c80-48a9-ae18-19cc2b6f4791/revisions/2","type":"Microsoft.Capacity/reservationOrders/reservations/revisions","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a/0532ae1c-3c80-48a9-ae18-19cc2b6f4791/2","etag":2,"kind":"Microsoft.Compute","location":"japaneast","properties":{"appliedScopes":["/subscriptions/00000000-0000-0000-0000-000000000000"],"appliedScopeType":"Single","quantity":3,"provisioningState":"Succeeded","expiryDate":"2018-11-02","displayName":"hyo_TestYong","effectiveDateTime":"2017-11-06T18:34:04.8870098Z","lastUpdatedDateTime":"2017-11-06T18:34:09.6682436Z","splitProperties":{"splitSource":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/a5748744-7432-477d-bc3c-b5f734be5f8d"}}},{"sku":{"name":"Standard_DS1"},"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/0532ae1c-3c80-48a9-ae18-19cc2b6f4791/revisions/1","type":"Microsoft.Capacity/reservationOrders/reservations/revisions","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a/0532ae1c-3c80-48a9-ae18-19cc2b6f4791/1","etag":1,"kind":"Microsoft.Compute","location":"japaneast","properties":{"appliedScopes":["/subscriptions/00000000-0000-0000-0000-000000000000"],"appliedScopeType":"Single","quantity":3,"provisioningState":"Creating","expiryDate":"2018-11-02","displayName":"hyo_TestYong","effectiveDateTime":"2017-11-06T18:34:04.8870098Z","lastUpdatedDateTime":"2017-11-06T18:34:04.8870098Z","splitProperties":{"splitSource":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/a5748744-7432-477d-bc3c-b5f734be5f8d"}}}]}'} + headers: + cache-control: [no-cache] + content-length: ['1788'] + content-type: [application/json; charset=utf-8] + date: ['Mon, 06 Nov 2017 21:49:20 GMT'] + expires: ['-1'] + pragma: [no-cache] + server: [Microsoft-IIS/8.5] + strict-transport-security: [max-age=31536000; includeSubDomains] + transfer-encoding: [chunked] + vary: ['Accept-Encoding,Accept-Encoding'] + x-content-type-options: [nosniff] + status: {code: 200, message: OK} +version: 1 diff --git a/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/tests/recordings/latest/test_list_reservation_order.yaml b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/tests/recordings/latest/test_list_reservation_order.yaml new file mode 100644 index 00000000000..676725140dc --- /dev/null +++ b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/tests/recordings/latest/test_list_reservation_order.yaml @@ -0,0 +1,30 @@ +interactions: +- request: + body: null + headers: + Accept: [application/json] + Accept-Encoding: ['gzip, deflate'] + CommandName: [reservations reservation-order list] + Connection: [keep-alive] + Content-Type: [application/json; charset=utf-8] + User-Agent: [python/3.5.4 (Windows-10-10.0.14393-SP0) requests/2.18.4 msrest/0.4.18 + msrest_azure/0.4.16 azurereservationapi/0.1.0 Azure-SDK-For-Python AZURECLI/2.0.21] + accept-language: [en-US] + method: GET + uri: https://management.azure.com/providers/Microsoft.Capacity/reservationOrders?api-version=2017-11-01 + response: + body: {string: '{"value":[{"id":"/providers/microsoft.capacity/reservationOrders/32dfb8a1-6ccc-40db-8de4-b63ebd87e3b3","type":"Microsoft.Capacity/reservationOrders","name":"32dfb8a1-6ccc-40db-8de4-b63ebd87e3b3","etag":4,"properties":{"displayName":"juhle_tip_test","requestDateTime":"2017-10-28T00:16:12.6224301Z","term":"P1Y","provisioningState":"Failed","reservations":[{"id":"/providers/microsoft.capacity/reservationOrders/32dfb8a1-6ccc-40db-8de4-b63ebd87e3b3/reservations/8bea0236-491f-4aca-86ce-8a7a2994feb3"}],"originalQuantity":2}},{"id":"/providers/microsoft.capacity/reservationOrders/655e3df6-8aa8-4bcc-8707-9e1a6976a582","type":"Microsoft.Capacity/reservationOrders","name":"655e3df6-8aa8-4bcc-8707-9e1a6976a582","etag":4,"properties":{"displayName":"aceritest1102wd02","requestDateTime":"2017-11-02T20:28:59.4443012Z","term":"P1Y","provisioningState":"Failed","reservations":[{"id":"/providers/microsoft.capacity/reservationOrders/655e3df6-8aa8-4bcc-8707-9e1a6976a582/reservations/fe3cad77-a849-4fee-9b43-930c3ee4b85a"}],"originalQuantity":1}},{"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a","type":"Microsoft.Capacity/reservationOrders","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a","etag":16,"properties":{"displayName":"hyo_TestYong","requestDateTime":"2017-11-02T19:38:26.684952Z","createdDateTime":"2017-11-02T19:42:55.5893862Z","expiryDate":"2018-11-02","term":"P1Y","provisioningState":"Succeeded","reservations":[{"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/b17accea-8a13-4a80-9ca9-cc3bb7772f39"},{"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/36beb8e4-db5f-4502-ae42-630e464a5437"},{"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/7f08f1bc-0f4a-4bb7-9d50-d1d8d656179b"},{"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/97830c1b-372b-4787-8b86-a54eb55be675"},{"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/c4d9378b-b98e-4e95-9b8f-c3025663c854"},{"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/9b84716e-9cb2-4651-bb4d-e4e8619ebd7b"},{"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/fd31d466-7f10-48c7-98ab-be52e5f2dac8"},{"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/211e6c2c-32ee-4f6f-b101-620888e5be39"},{"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/d1c424c4-f30f-403a-a900-e9f5f36bb57c"},{"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/1b98862a-6ae2-4c20-ade6-dd55322994b4"},{"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/770a14fc-e075-4583-afe3-af486bce2cea"},{"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/3bc6c3ec-5678-4838-aabb-513ddef65bfc"},{"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/a5748744-7432-477d-bc3c-b5f734be5f8d"},{"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/09ee4b20-caad-489c-ace1-523e06a8584e"},{"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/0532ae1c-3c80-48a9-ae18-19cc2b6f4791"}],"originalQuantity":5}},{"id":"/providers/microsoft.capacity/reservationOrders/8c165114-9981-4e50-9cf2-da5145f1a9a5","type":"Microsoft.Capacity/reservationOrders","name":"8c165114-9981-4e50-9cf2-da5145f1a9a5","etag":8,"properties":{"displayName":"hyo_TestYong","requestDateTime":"2017-11-02T17:30:56.178593Z","createdDateTime":"2017-11-02T17:33:00.679415Z","expiryDate":"2018-11-02","term":"P1Y","provisioningState":"Succeeded","reservations":[{"id":"/providers/microsoft.capacity/reservationOrders/8c165114-9981-4e50-9cf2-da5145f1a9a5/reservations/f8a24bce-46a0-4fb2-b8d3-13c2f6298d1e"},{"id":"/providers/microsoft.capacity/reservationOrders/8c165114-9981-4e50-9cf2-da5145f1a9a5/reservations/b8b97f3c-7c2d-44a3-8ad4-80c32dfc62c5"},{"id":"/providers/microsoft.capacity/reservationOrders/8c165114-9981-4e50-9cf2-da5145f1a9a5/reservations/ad2b3e47-9fe6-4fb9-91e2-ae83efe7b213"}],"originalQuantity":5}},{"id":"/providers/microsoft.capacity/reservationOrders/c2639b73-933d-4a7f-8556-68070e33dab9","type":"Microsoft.Capacity/reservationOrders","name":"c2639b73-933d-4a7f-8556-68070e33dab9","etag":4,"properties":{"displayName":"juhle_tip_test","requestDateTime":"2017-10-28T00:21:38.9233147Z","term":"P1Y","provisioningState":"Failed","reservations":[{"id":"/providers/microsoft.capacity/reservationOrders/c2639b73-933d-4a7f-8556-68070e33dab9/reservations/df985ee8-aab1-4639-be24-17a726241e9b"}],"originalQuantity":2}},{"id":"/providers/microsoft.capacity/reservationOrders/c7d79bbc-5f96-4aa6-b4cb-3c148f14920e","type":"Microsoft.Capacity/reservationOrders","name":"c7d79bbc-5f96-4aa6-b4cb-3c148f14920e","etag":4,"properties":{"displayName":"aceritest1027wd01","requestDateTime":"2017-10-27T23:46:17.9947639Z","term":"P1Y","provisioningState":"Failed","reservations":[{"id":"/providers/microsoft.capacity/reservationOrders/c7d79bbc-5f96-4aa6-b4cb-3c148f14920e/reservations/1f2d5dc7-b015-4bc8-887e-012dbcf4d03d"}],"originalQuantity":2}},{"id":"/providers/microsoft.capacity/reservationOrders/c8f59d02-7109-4399-84f6-7171b604e597","type":"Microsoft.Capacity/reservationOrders","name":"c8f59d02-7109-4399-84f6-7171b604e597","etag":4,"properties":{"displayName":"hyo_TestYong","requestDateTime":"2017-11-02T17:24:47.6253778Z","term":"P1Y","provisioningState":"Failed","reservations":[{"id":"/providers/microsoft.capacity/reservationOrders/c8f59d02-7109-4399-84f6-7171b604e597/reservations/e7a3e8e2-f9ac-4467-937d-f3a2f5cfddb1"}],"originalQuantity":5}},{"id":"/providers/microsoft.capacity/reservationOrders/d12fbaf6-3149-4ee6-a784-47760b59e883","type":"Microsoft.Capacity/reservationOrders","name":"d12fbaf6-3149-4ee6-a784-47760b59e883","etag":4,"properties":{"displayName":"aceritest1027wd01","requestDateTime":"2017-10-30T17:55:30.0567671Z","term":"P1Y","provisioningState":"Failed","reservations":[{"id":"/providers/microsoft.capacity/reservationOrders/d12fbaf6-3149-4ee6-a784-47760b59e883/reservations/5571624d-bec4-44c7-b32e-daaffccff15c"}],"originalQuantity":2}},{"id":"/providers/microsoft.capacity/reservationOrders/d5d9085b-1b35-427e-8fb0-9700a3cee3f3","type":"Microsoft.Capacity/reservationOrders","name":"d5d9085b-1b35-427e-8fb0-9700a3cee3f3","etag":4,"properties":{"displayName":"aceritest1027wd02","requestDateTime":"2017-10-27T23:53:11.7813636Z","term":"P1Y","provisioningState":"Failed","reservations":[{"id":"/providers/microsoft.capacity/reservationOrders/d5d9085b-1b35-427e-8fb0-9700a3cee3f3/reservations/4a1d3c58-4701-4272-aa1c-6a4983cc2a25"}],"originalQuantity":1}},{"id":"/providers/microsoft.capacity/reservationOrders/f7d8c8b2-9605-4489-bd48-b17673d96007","type":"Microsoft.Capacity/reservationOrders","name":"f7d8c8b2-9605-4489-bd48-b17673d96007","etag":4,"properties":{"displayName":"aceritest1102wd01","requestDateTime":"2017-11-02T20:12:33.10219Z","term":"P1Y","provisioningState":"Failed","reservations":[{"id":"/providers/microsoft.capacity/reservationOrders/f7d8c8b2-9605-4489-bd48-b17673d96007/reservations/5eff80aa-bf95-4a63-8c8c-bdb39f8f846c"}],"originalQuantity":1}},{"id":"/providers/microsoft.capacity/reservationOrders/f8dc1a06-c795-4513-b387-11416b058f51","type":"Microsoft.Capacity/reservationOrders","name":"f8dc1a06-c795-4513-b387-11416b058f51","etag":11,"properties":{"displayName":"juhle_tip_test","requestDateTime":"2017-10-28T00:32:16.8005213Z","createdDateTime":"2017-10-28T00:34:08.6776098Z","expiryDate":"2018-10-28","term":"P1Y","provisioningState":"Pending","reservations":[{"id":"/providers/microsoft.capacity/reservationOrders/f8dc1a06-c795-4513-b387-11416b058f51/reservations/bd80ffbf-57e1-4bfc-bd35-bfed89bf9056"},{"id":"/providers/microsoft.capacity/reservationOrders/f8dc1a06-c795-4513-b387-11416b058f51/reservations/c71eb668-da1d-4369-8437-1880ade8991b"},{"id":"/providers/microsoft.capacity/reservationOrders/f8dc1a06-c795-4513-b387-11416b058f51/reservations/a3be0e49-6ff0-4b6e-b94a-df329aece7be"}],"originalQuantity":2}}]}'} + headers: + cache-control: [no-cache] + content-length: ['8495'] + content-type: [application/json; charset=utf-8] + date: ['Mon, 06 Nov 2017 21:30:24 GMT'] + expires: ['-1'] + pragma: [no-cache] + server: [Microsoft-IIS/8.5] + strict-transport-security: [max-age=31536000; includeSubDomains] + transfer-encoding: [chunked] + vary: ['Accept-Encoding,Accept-Encoding'] + x-content-type-options: [nosniff] + status: {code: 200, message: OK} +version: 1 diff --git a/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/tests/recordings/latest/test_split_and_merge.yaml b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/tests/recordings/latest/test_split_and_merge.yaml new file mode 100644 index 00000000000..803c2559866 --- /dev/null +++ b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/tests/recordings/latest/test_split_and_merge.yaml @@ -0,0 +1,155 @@ +interactions: +- request: + body: null + headers: + Accept: [application/json] + Accept-Encoding: ['gzip, deflate'] + CommandName: [reservations reservation show] + Connection: [keep-alive] + Content-Type: [application/json; charset=utf-8] + User-Agent: [python/3.5.4 (Windows-10-10.0.14393-SP0) requests/2.18.4 msrest/0.4.18 + msrest_azure/0.4.16 azurereservationapi/0.1.0 Azure-SDK-For-Python AZURECLI/2.0.21] + accept-language: [en-US] + method: GET + uri: https://management.azure.com/providers/Microsoft.Capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/1b98862a-6ae2-4c20-ade6-dd55322994b4?api-version=2017-11-01 + response: + body: {string: '{"sku":{"name":"Standard_DS1"},"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/1b98862a-6ae2-4c20-ade6-dd55322994b4","type":"Microsoft.Capacity/reservationOrders/reservations","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a/1b98862a-6ae2-4c20-ade6-dd55322994b4","etag":2,"kind":"Microsoft.Compute","location":"japaneast","properties":{"appliedScopes":["/subscriptions/00000000-0000-0000-0000-000000000000"],"appliedScopeType":"Single","quantity":5,"provisioningState":"Succeeded","expiryDate":"2018-11-02","displayName":"hyo_TestYong","effectiveDateTime":"2017-11-06T18:10:32.3498846Z","lastUpdatedDateTime":"2017-11-06T18:10:32.3498846Z","mergeProperties":{"mergeSources":["/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/211e6c2c-32ee-4f6f-b101-620888e5be39","/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/d1c424c4-f30f-403a-a900-e9f5f36bb57c"]}}}'} + headers: + cache-control: [no-cache] + content-length: ['1004'] + content-type: [application/json; charset=utf-8] + date: ['Mon, 06 Nov 2017 18:11:32 GMT'] + expires: ['-1'] + pragma: [no-cache] + server: [Microsoft-IIS/8.5] + strict-transport-security: [max-age=31536000; includeSubDomains] + transfer-encoding: [chunked] + vary: ['Accept-Encoding,Accept-Encoding'] + x-content-type-options: [nosniff] + status: {code: 200, message: OK} +- request: + body: '{"properties": {"quantities": [2, 3], "reservationId": "/providers/Microsoft.Capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/1b98862a-6ae2-4c20-ade6-dd55322994b4"}}' + headers: + Accept: [application/json] + Accept-Encoding: ['gzip, deflate'] + CommandName: [reservations reservation split] + Connection: [keep-alive] + Content-Length: ['193'] + Content-Type: [application/json; charset=utf-8] + User-Agent: [python/3.5.4 (Windows-10-10.0.14393-SP0) requests/2.18.4 msrest/0.4.18 + msrest_azure/0.4.16 azurereservationapi/0.1.0 Azure-SDK-For-Python AZURECLI/2.0.21] + accept-language: [en-US] + method: POST + uri: https://management.azure.com/providers/Microsoft.Capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/split?api-version=2017-11-01 + response: + body: {string: '[{"sku":{"name":"Standard_DS1"},"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/770a14fc-e075-4583-afe3-af486bce2cea","type":"Microsoft.Capacity/reservationOrders/reservations","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a/770a14fc-e075-4583-afe3-af486bce2cea","etag":2,"kind":"Microsoft.Compute","location":"japaneast","properties":{"appliedScopes":["/subscriptions/00000000-0000-0000-0000-000000000000"],"appliedScopeType":"Single","quantity":2,"provisioningState":"Succeeded","expiryDate":"2018-11-02","displayName":"hyo_TestYong","effectiveDateTime":"2017-11-06T18:11:34.2984722Z","lastUpdatedDateTime":"2017-11-06T18:11:37.5953464Z","splitProperties":{"splitSource":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/1b98862a-6ae2-4c20-ade6-dd55322994b4"}}},{"sku":{"name":"Standard_DS1"},"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/3bc6c3ec-5678-4838-aabb-513ddef65bfc","type":"Microsoft.Capacity/reservationOrders/reservations","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a/3bc6c3ec-5678-4838-aabb-513ddef65bfc","etag":2,"kind":"Microsoft.Compute","location":"japaneast","properties":{"appliedScopes":["/subscriptions/00000000-0000-0000-0000-000000000000"],"appliedScopeType":"Single","quantity":3,"provisioningState":"Succeeded","expiryDate":"2018-11-02","displayName":"hyo_TestYong","effectiveDateTime":"2017-11-06T18:11:34.2984722Z","lastUpdatedDateTime":"2017-11-06T18:11:37.5953464Z","splitProperties":{"splitSource":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/1b98862a-6ae2-4c20-ade6-dd55322994b4"}}},{"sku":{"name":"Standard_DS1"},"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/1b98862a-6ae2-4c20-ade6-dd55322994b4","type":"Microsoft.Capacity/reservationOrders/reservations","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a/1b98862a-6ae2-4c20-ade6-dd55322994b4","etag":5,"kind":"Microsoft.Compute","location":"japaneast","properties":{"appliedScopes":["/subscriptions/00000000-0000-0000-0000-000000000000"],"appliedScopeType":"Single","quantity":5,"provisioningState":"Cancelled","expiryDate":"2018-11-02","displayName":"hyo_TestYong","effectiveDateTime":"2017-11-06T18:11:34.2984722Z","extendedStatusInfo":{"statusCode":"Split","message":"This + reservation was split and is no longer active."},"lastUpdatedDateTime":"2017-11-06T18:11:37.5953464Z","splitProperties":{"splitDestinations":["/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/770a14fc-e075-4583-afe3-af486bce2cea","/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/3bc6c3ec-5678-4838-aabb-513ddef65bfc"]},"mergeProperties":{"mergeSources":["/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/211e6c2c-32ee-4f6f-b101-620888e5be39","/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/d1c424c4-f30f-403a-a900-e9f5f36bb57c"]}}}]'} + headers: + cache-control: [no-cache] + content-length: ['3160'] + content-type: [application/json; charset=utf-8] + date: ['Mon, 06 Nov 2017 18:11:36 GMT'] + expires: ['-1'] + location: ['https://management.azure.com/providers/Microsoft.Capacity/reservationorders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/split/operationresults/1b98862a-6ae2-4c20-ade6-dd55322994b4_3?api-version=2017-11-01'] + pragma: [no-cache] + server: [Microsoft-IIS/8.5] + strict-transport-security: [max-age=31536000; includeSubDomains] + transfer-encoding: [chunked] + vary: ['Accept-Encoding,Accept-Encoding'] + x-content-type-options: [nosniff] + x-ms-ratelimit-remaining-tenant-writes: ['1198'] + status: {code: 200, message: OK} +- request: + body: null + headers: + Accept: [application/json] + Accept-Encoding: ['gzip, deflate'] + CommandName: [reservations reservation split] + Connection: [keep-alive] + Content-Type: [application/json; charset=utf-8] + User-Agent: [python/3.5.4 (Windows-10-10.0.14393-SP0) requests/2.18.4 msrest/0.4.18 + msrest_azure/0.4.16 azurereservationapi/0.1.0 Azure-SDK-For-Python AZURECLI/2.0.21] + accept-language: [en-US] + method: GET + uri: https://management.azure.com/providers/Microsoft.Capacity/reservationorders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/split/operationresults/1b98862a-6ae2-4c20-ade6-dd55322994b4_3?api-version=2017-11-01 + response: + body: {string: '[{"sku":{"name":"Standard_DS1"},"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/770a14fc-e075-4583-afe3-af486bce2cea","type":"Microsoft.Capacity/reservationOrders/reservations","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a/770a14fc-e075-4583-afe3-af486bce2cea","etag":2,"kind":"Microsoft.Compute","location":"japaneast","properties":{"appliedScopes":["/subscriptions/00000000-0000-0000-0000-000000000000"],"appliedScopeType":"Single","quantity":2,"provisioningState":"Succeeded","expiryDate":"2018-11-02","displayName":"hyo_TestYong","effectiveDateTime":"2017-11-06T18:11:34.2984722Z","lastUpdatedDateTime":"2017-11-06T18:11:37.5953464Z","splitProperties":{"splitSource":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/1b98862a-6ae2-4c20-ade6-dd55322994b4"}}},{"sku":{"name":"Standard_DS1"},"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/3bc6c3ec-5678-4838-aabb-513ddef65bfc","type":"Microsoft.Capacity/reservationOrders/reservations","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a/3bc6c3ec-5678-4838-aabb-513ddef65bfc","etag":2,"kind":"Microsoft.Compute","location":"japaneast","properties":{"appliedScopes":["/subscriptions/00000000-0000-0000-0000-000000000000"],"appliedScopeType":"Single","quantity":3,"provisioningState":"Succeeded","expiryDate":"2018-11-02","displayName":"hyo_TestYong","effectiveDateTime":"2017-11-06T18:11:34.2984722Z","lastUpdatedDateTime":"2017-11-06T18:11:37.5953464Z","splitProperties":{"splitSource":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/1b98862a-6ae2-4c20-ade6-dd55322994b4"}}},{"sku":{"name":"Standard_DS1"},"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/1b98862a-6ae2-4c20-ade6-dd55322994b4","type":"Microsoft.Capacity/reservationOrders/reservations","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a/1b98862a-6ae2-4c20-ade6-dd55322994b4","etag":5,"kind":"Microsoft.Compute","location":"japaneast","properties":{"appliedScopes":["/subscriptions/00000000-0000-0000-0000-000000000000"],"appliedScopeType":"Single","quantity":5,"provisioningState":"Cancelled","expiryDate":"2018-11-02","displayName":"hyo_TestYong","effectiveDateTime":"2017-11-06T18:11:34.2984722Z","extendedStatusInfo":{"statusCode":"Split","message":"This + reservation was split and is no longer active."},"lastUpdatedDateTime":"2017-11-06T18:11:37.5953464Z","splitProperties":{"splitDestinations":["/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/770a14fc-e075-4583-afe3-af486bce2cea","/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/3bc6c3ec-5678-4838-aabb-513ddef65bfc"]},"mergeProperties":{"mergeSources":["/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/211e6c2c-32ee-4f6f-b101-620888e5be39","/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/d1c424c4-f30f-403a-a900-e9f5f36bb57c"]}}}]'} + headers: + cache-control: [no-cache] + content-length: ['3160'] + content-type: [application/json; charset=utf-8] + date: ['Mon, 06 Nov 2017 18:11:49 GMT'] + expires: ['-1'] + pragma: [no-cache] + server: [Microsoft-IIS/8.5] + strict-transport-security: [max-age=31536000; includeSubDomains] + transfer-encoding: [chunked] + vary: ['Accept-Encoding,Accept-Encoding'] + x-content-type-options: [nosniff] + status: {code: 200, message: OK} +- request: + body: '{"properties": {"sources": ["/providers/Microsoft.Capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/770a14fc-e075-4583-afe3-af486bce2cea", + "/providers/Microsoft.Capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/3bc6c3ec-5678-4838-aabb-513ddef65bfc"]}}' + headers: + Accept: [application/json] + Accept-Encoding: ['gzip, deflate'] + CommandName: [reservations reservation merge] + Connection: [keep-alive] + Content-Length: ['305'] + Content-Type: [application/json; charset=utf-8] + User-Agent: [python/3.5.4 (Windows-10-10.0.14393-SP0) requests/2.18.4 msrest/0.4.18 + msrest_azure/0.4.16 azurereservationapi/0.1.0 Azure-SDK-For-Python AZURECLI/2.0.21] + accept-language: [en-US] + method: POST + uri: https://management.azure.com/providers/Microsoft.Capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/merge?api-version=2017-11-01 + response: + body: {string: '[{"sku":{"name":"Standard_DS1"},"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/770a14fc-e075-4583-afe3-af486bce2cea","type":"Microsoft.Capacity/reservationOrders/reservations","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a/770a14fc-e075-4583-afe3-af486bce2cea","etag":5,"kind":"Microsoft.Compute","location":"japaneast","properties":{"appliedScopes":["/subscriptions/00000000-0000-0000-0000-000000000000"],"appliedScopeType":"Single","quantity":2,"provisioningState":"Cancelled","expiryDate":"2018-11-02","displayName":"hyo_TestYong","effectiveDateTime":"2017-11-06T18:11:55.4522619Z","extendedStatusInfo":{"statusCode":"Merged","message":"This + reservation was merged and is no longer active."},"lastUpdatedDateTime":"2017-11-06T18:11:55.4522619Z","splitProperties":{"splitSource":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/1b98862a-6ae2-4c20-ade6-dd55322994b4"},"mergeProperties":{"mergeDestination":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/a5748744-7432-477d-bc3c-b5f734be5f8d"}}},{"sku":{"name":"Standard_DS1"},"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/3bc6c3ec-5678-4838-aabb-513ddef65bfc","type":"Microsoft.Capacity/reservationOrders/reservations","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a/3bc6c3ec-5678-4838-aabb-513ddef65bfc","etag":4,"kind":"Microsoft.Compute","location":"japaneast","properties":{"appliedScopes":["/subscriptions/00000000-0000-0000-0000-000000000000"],"appliedScopeType":"Single","quantity":3,"provisioningState":"Cancelled","expiryDate":"2018-11-02","displayName":"hyo_TestYong","effectiveDateTime":"2017-11-06T18:11:55.4522619Z","extendedStatusInfo":{"statusCode":"Merged","message":"This + reservation was merged and is no longer active."},"lastUpdatedDateTime":"2017-11-06T18:11:55.4522619Z","splitProperties":{"splitSource":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/1b98862a-6ae2-4c20-ade6-dd55322994b4"},"mergeProperties":{"mergeDestination":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/a5748744-7432-477d-bc3c-b5f734be5f8d"}}},{"sku":{"name":"Standard_DS1"},"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/a5748744-7432-477d-bc3c-b5f734be5f8d","type":"Microsoft.Capacity/reservationOrders/reservations","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a/a5748744-7432-477d-bc3c-b5f734be5f8d","etag":2,"kind":"Microsoft.Compute","location":"japaneast","properties":{"appliedScopes":["/subscriptions/00000000-0000-0000-0000-000000000000"],"appliedScopeType":"Single","quantity":5,"provisioningState":"Succeeded","expiryDate":"2018-11-02","displayName":"hyo_TestYong","effectiveDateTime":"2017-11-06T18:11:55.4522619Z","lastUpdatedDateTime":"2017-11-06T18:11:55.4522619Z","mergeProperties":{"mergeSources":["/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/770a14fc-e075-4583-afe3-af486bce2cea","/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/3bc6c3ec-5678-4838-aabb-513ddef65bfc"]}}}]'} + headers: + cache-control: [no-cache] + content-length: ['3308'] + content-type: [application/json; charset=utf-8] + date: ['Mon, 06 Nov 2017 18:11:56 GMT'] + expires: ['-1'] + location: ['https://management.azure.com/providers/Microsoft.Capacity/reservationorders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/merge/operationresults/770a14fc-e075-4583-afe3-af486bce2cea_3?api-version=2017-11-01'] + pragma: [no-cache] + server: [Microsoft-IIS/8.5] + strict-transport-security: [max-age=31536000; includeSubDomains] + transfer-encoding: [chunked] + vary: ['Accept-Encoding,Accept-Encoding'] + x-content-type-options: [nosniff] + x-ms-ratelimit-remaining-tenant-writes: ['1199'] + status: {code: 200, message: OK} +- request: + body: null + headers: + Accept: [application/json] + Accept-Encoding: ['gzip, deflate'] + CommandName: [reservations reservation merge] + Connection: [keep-alive] + Content-Type: [application/json; charset=utf-8] + User-Agent: [python/3.5.4 (Windows-10-10.0.14393-SP0) requests/2.18.4 msrest/0.4.18 + msrest_azure/0.4.16 azurereservationapi/0.1.0 Azure-SDK-For-Python AZURECLI/2.0.21] + accept-language: [en-US] + method: GET + uri: https://management.azure.com/providers/Microsoft.Capacity/reservationorders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/merge/operationresults/770a14fc-e075-4583-afe3-af486bce2cea_3?api-version=2017-11-01 + response: + body: {string: '[{"sku":{"name":"Standard_DS1"},"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/770a14fc-e075-4583-afe3-af486bce2cea","type":"Microsoft.Capacity/reservationOrders/reservations","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a/770a14fc-e075-4583-afe3-af486bce2cea","etag":5,"kind":"Microsoft.Compute","location":"japaneast","properties":{"appliedScopes":["/subscriptions/00000000-0000-0000-0000-000000000000"],"appliedScopeType":"Single","quantity":2,"provisioningState":"Cancelled","expiryDate":"2018-11-02","displayName":"hyo_TestYong","effectiveDateTime":"2017-11-06T18:11:55.4522619Z","extendedStatusInfo":{"statusCode":"Merged","message":"This + reservation was merged and is no longer active."},"lastUpdatedDateTime":"2017-11-06T18:11:55.4522619Z","splitProperties":{"splitSource":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/1b98862a-6ae2-4c20-ade6-dd55322994b4"},"mergeProperties":{"mergeDestination":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/a5748744-7432-477d-bc3c-b5f734be5f8d"}}},{"sku":{"name":"Standard_DS1"},"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/3bc6c3ec-5678-4838-aabb-513ddef65bfc","type":"Microsoft.Capacity/reservationOrders/reservations","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a/3bc6c3ec-5678-4838-aabb-513ddef65bfc","etag":4,"kind":"Microsoft.Compute","location":"japaneast","properties":{"appliedScopes":["/subscriptions/00000000-0000-0000-0000-000000000000"],"appliedScopeType":"Single","quantity":3,"provisioningState":"Cancelled","expiryDate":"2018-11-02","displayName":"hyo_TestYong","effectiveDateTime":"2017-11-06T18:11:55.4522619Z","extendedStatusInfo":{"statusCode":"Merged","message":"This + reservation was merged and is no longer active."},"lastUpdatedDateTime":"2017-11-06T18:11:55.4522619Z","splitProperties":{"splitSource":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/1b98862a-6ae2-4c20-ade6-dd55322994b4"},"mergeProperties":{"mergeDestination":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/a5748744-7432-477d-bc3c-b5f734be5f8d"}}},{"sku":{"name":"Standard_DS1"},"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/a5748744-7432-477d-bc3c-b5f734be5f8d","type":"Microsoft.Capacity/reservationOrders/reservations","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a/a5748744-7432-477d-bc3c-b5f734be5f8d","etag":2,"kind":"Microsoft.Compute","location":"japaneast","properties":{"appliedScopes":["/subscriptions/00000000-0000-0000-0000-000000000000"],"appliedScopeType":"Single","quantity":5,"provisioningState":"Succeeded","expiryDate":"2018-11-02","displayName":"hyo_TestYong","effectiveDateTime":"2017-11-06T18:11:55.4522619Z","lastUpdatedDateTime":"2017-11-06T18:11:55.4522619Z","mergeProperties":{"mergeSources":["/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/770a14fc-e075-4583-afe3-af486bce2cea","/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/3bc6c3ec-5678-4838-aabb-513ddef65bfc"]}}}]'} + headers: + cache-control: [no-cache] + content-length: ['3308'] + content-type: [application/json; charset=utf-8] + date: ['Mon, 06 Nov 2017 18:12:08 GMT'] + expires: ['-1'] + pragma: [no-cache] + server: [Microsoft-IIS/8.5] + strict-transport-security: [max-age=31536000; includeSubDomains] + transfer-encoding: [chunked] + vary: ['Accept-Encoding,Accept-Encoding'] + x-content-type-options: [nosniff] + status: {code: 200, message: OK} +version: 1 diff --git a/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/tests/recordings/latest/test_update_reservation.yaml b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/tests/recordings/latest/test_update_reservation.yaml new file mode 100644 index 00000000000..0f69fe89172 --- /dev/null +++ b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/tests/recordings/latest/test_update_reservation.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: '{"properties": {"appliedScopeType": "Shared"}}' + headers: + Accept: [application/json] + Accept-Encoding: ['gzip, deflate'] + CommandName: [reservations reservation update] + Connection: [keep-alive] + Content-Length: ['46'] + Content-Type: [application/json; charset=utf-8] + User-Agent: [python/3.5.4 (Windows-10-10.0.14393-SP0) requests/2.18.4 msrest/0.4.18 + msrest_azure/0.4.16 azurereservationapi/0.1.0 Azure-SDK-For-Python AZURECLI/2.0.21] + accept-language: [en-US] + method: PATCH + uri: https://management.azure.com/providers/Microsoft.Capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/0532ae1c-3c80-48a9-ae18-19cc2b6f4791?api-version=2017-11-01 + response: + body: {string: '{"sku":{"name":"Standard_DS1"},"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/0532ae1c-3c80-48a9-ae18-19cc2b6f4791","type":"Microsoft.Capacity/reservationOrders/reservations","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a/0532ae1c-3c80-48a9-ae18-19cc2b6f4791","etag":4,"kind":"Microsoft.Compute","location":"japaneast","properties":{"appliedScopeType":"Shared","quantity":3,"provisioningState":"Succeeded","expiryDate":"2018-11-02","displayName":"hyo_TestYong","effectiveDateTime":"2017-11-06T22:03:15.852805Z","lastUpdatedDateTime":"2017-11-06T22:03:30.9112488Z","splitProperties":{"splitSource":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/a5748744-7432-477d-bc3c-b5f734be5f8d"}}}'} + headers: + cache-control: [no-cache] + content-length: ['791'] + content-type: [application/json; charset=utf-8] + date: ['Mon, 06 Nov 2017 22:03:42 GMT'] + expires: ['-1'] + pragma: [no-cache] + server: [Microsoft-IIS/8.5] + strict-transport-security: [max-age=31536000; includeSubDomains] + transfer-encoding: [chunked] + vary: ['Accept-Encoding,Accept-Encoding'] + x-content-type-options: [nosniff] + x-ms-ratelimit-remaining-tenant-writes: ['1199'] + status: {code: 200, message: OK} +- request: + body: '{"properties": {"appliedScopes": ["/subscriptions/00000000-0000-0000-0000-000000000000"], + "appliedScopeType": "Single"}}' + headers: + Accept: [application/json] + Accept-Encoding: ['gzip, deflate'] + CommandName: [reservations reservation update] + Connection: [keep-alive] + Content-Length: ['120'] + Content-Type: [application/json; charset=utf-8] + User-Agent: [python/3.5.4 (Windows-10-10.0.14393-SP0) requests/2.18.4 msrest/0.4.18 + msrest_azure/0.4.16 azurereservationapi/0.1.0 Azure-SDK-For-Python AZURECLI/2.0.21] + accept-language: [en-US] + method: PATCH + uri: https://management.azure.com/providers/Microsoft.Capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/0532ae1c-3c80-48a9-ae18-19cc2b6f4791?api-version=2017-11-01 + response: + body: {string: '{"sku":{"name":"Standard_DS1"},"id":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/0532ae1c-3c80-48a9-ae18-19cc2b6f4791","type":"Microsoft.Capacity/reservationOrders/reservations","name":"86d9870a-bf1e-4635-94c8-b0f08932bc3a/0532ae1c-3c80-48a9-ae18-19cc2b6f4791","etag":6,"kind":"Microsoft.Compute","location":"japaneast","properties":{"appliedScopes":["/subscriptions/00000000-0000-0000-0000-000000000000"],"appliedScopeType":"Single","quantity":3,"provisioningState":"Succeeded","expiryDate":"2018-11-02","displayName":"hyo_TestYong","effectiveDateTime":"2017-11-06T22:03:53.9441856Z","lastUpdatedDateTime":"2017-11-06T22:04:00.7194287Z","splitProperties":{"splitSource":"/providers/microsoft.capacity/reservationOrders/86d9870a-bf1e-4635-94c8-b0f08932bc3a/reservations/a5748744-7432-477d-bc3c-b5f734be5f8d"}}}'} + headers: + cache-control: [no-cache] + content-length: ['864'] + content-type: [application/json; charset=utf-8] + date: ['Mon, 06 Nov 2017 22:04:01 GMT'] + expires: ['-1'] + pragma: [no-cache] + server: [Microsoft-IIS/8.5] + strict-transport-security: [max-age=31536000; includeSubDomains] + transfer-encoding: [chunked] + vary: ['Accept-Encoding,Accept-Encoding'] + x-content-type-options: [nosniff] + x-ms-ratelimit-remaining-tenant-writes: ['1199'] + status: {code: 200, message: OK} +version: 1 diff --git a/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/tests/test_reservations_commands.py b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/tests/test_reservations_commands.py new file mode 100644 index 00000000000..09814e1344f --- /dev/null +++ b/src/command_modules/azure-cli-reservations/azure/cli/command_modules/reservations/tests/test_reservations_commands.py @@ -0,0 +1,132 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- + +from azure.cli.testsdk import ScenarioTest + + +class AzureReservationsTests(ScenarioTest): + + def _validate_reservation_order(self, reservation_order): + self.assertIsNotNone(reservation_order) + self.assertTrue(reservation_order['etag']) + self.assertTrue(reservation_order['id']) + self.assertTrue(reservation_order['name']) + self.assertTrue(reservation_order['reservationsProperty']) + self.assertTrue(reservation_order['displayName']) + + def _validate_reservation(self, reservation): + self.assertIsNotNone(reservation) + self.assertTrue(reservation['id']) + self.assertTrue(reservation['name']) + self.assertTrue(reservation['kind']) + self.assertTrue(reservation['sku']) + self.assertTrue(reservation['properties']) + self.assertTrue(reservation['type']) + + def test_get_applied_reservation_order_ids(self): + result = self.cmd('az reservations reservation-order-id list --subscription-id 00000000-0000-0000-0000-000000000000').get_output_in_json() + for order_id in result['reservationOrderIds']['value']: + self.assertIn('/providers/Microsoft.Capacity/reservationorders/', order_id) + + def test_list_reservation_order(self): + reservation_order_list = self.cmd('reservations reservation-order list').get_output_in_json() + self.assertIsNotNone(reservation_order_list) + for order in reservation_order_list: + self._validate_reservation_order(order) + self.assertIn('/providers/microsoft.capacity/reservationOrders/', order['id']) + self.assertGreater(order['etag'], 0) + self.assertGreater(len(order['reservationsProperty']), 0) + + def test_get_reservation_order(self): + reservation_order_id = "86d9870a-bf1e-4635-94c8-b0f08932bc3a" + command = 'reservations reservation-order show --reservation-order-id {}'.format(reservation_order_id) + reservation_order = self.cmd(command).get_output_in_json() + self._validate_reservation_order(reservation_order) + self.assertIn('/providers/microsoft.capacity/reservationOrders/', reservation_order['id']) + self.assertGreater(reservation_order['etag'], 0) + self.assertGreater(len(reservation_order['reservationsProperty']), 0) + + def test_list_reservation(self): + reservation_order_id = "86d9870a-bf1e-4635-94c8-b0f08932bc3a" + reservation_list = self.cmd('reservations reservation list --reservation-order-id {}'.format(reservation_order_id)).get_output_in_json() + self.assertIsNotNone(reservation_list) + for reservation in reservation_list: + self.assertIn(reservation_order_id, reservation['name']) + self.assertGreater(reservation['etag'], 0) + self.assertEqual('Microsoft.Capacity/reservationOrders/reservations', reservation['type']) + + def test_get_reservation(self): + reservation_order_id = "86d9870a-bf1e-4635-94c8-b0f08932bc3a" + reservation_id = "0532ae1c-3c80-48a9-ae18-19cc2b6f4791" + get_command = 'reservations reservation show --reservation-order-id {} --reservation-id {}'.format(reservation_order_id, reservation_id) + reservation = self.cmd(get_command).get_output_in_json() + self.assertIn(reservation_order_id, reservation['name']) + self.assertGreater(reservation['etag'], 0) + self.assertGreater(reservation['properties']['quantity'], 0) + self.assertEqual('Microsoft.Capacity/reservationOrders/reservations', reservation['type']) + + def test_list_reservation_history(self): + reservation_order_id = "86d9870a-bf1e-4635-94c8-b0f08932bc3a" + reservation_id = "0532ae1c-3c80-48a9-ae18-19cc2b6f4791" + command = 'reservations reservation list-history --reservation-order-id {} --reservation-id {}'.format(reservation_order_id, reservation_id) + history = self.cmd(command).get_output_in_json() + self.assertGreater(len(history), 0) + for entry in history: + self.assertGreater(entry['etag'], 0) + name_format = '{}/{}'.format(reservation_order_id, reservation_id) + self.assertIn(name_format, entry['name']) + + def test_get_catalog(self): + catalog = self.cmd('az reservations catalog show --subscription-id 00000000-0000-0000-0000-000000000000').get_output_in_json() + self.assertGreater(len(catalog), 0) + for entry in catalog: + self.assertGreater(len(entry['terms']), 0) + self.assertGreater(len(entry['locations']), 0) + self.assertIsNotNone(entry['resourceType']) + self.assertIsNotNone(entry['name']) + self.assertIsNotNone(entry['size']) + + def test_update_reservation(self): + reservation_order_id = "86d9870a-bf1e-4635-94c8-b0f08932bc3a" + reservation_id = "0532ae1c-3c80-48a9-ae18-19cc2b6f4791" + + update_shared = 'reservations reservation update --reservation-order-id {} --reservation-id {} -t Shared'.format(reservation_order_id, reservation_id) + shared_reservation = self.cmd(update_shared).get_output_in_json() + self.assertEqual('Shared', shared_reservation['properties']['appliedScopeType']) + + scope = '/subscriptions/917b6752-3ac4-4087-84d7-b587adcca91b' + update_single = 'reservations reservation update --reservation-order-id {} --reservation-id {} -t Single -s {}'.format(reservation_order_id, reservation_id, scope) + single_reservation = self.cmd(update_single).get_output_in_json() + self.assertEqual('Single', single_reservation['properties']['appliedScopeType']) + + def test_split_and_merge(self): + reservation_order_id = '86d9870a-bf1e-4635-94c8-b0f08932bc3a' + reservation_id = '1b98862a-6ae2-4c20-ade6-dd55322994b4' + get_command = 'reservations reservation show --reservation-order-id {} --reservation-id {}'.format(reservation_order_id, reservation_id) + original_reservation = self.cmd(get_command).get_output_in_json() + original_quantity = original_reservation['properties']['quantity'] + + split_command = 'reservations reservation split --reservation-order-id {} --reservation-id {} -1 2 -2 3'.format(reservation_order_id, reservation_id) + split_items = self.cmd(split_command).get_output_in_json() + self.assertIsNotNone(split_items) + + quantity_sum = 0 + split_ids = [] + for item in split_items: + self._validate_reservation(item) + if 'Succeeded' in item['properties']['provisioningState']: + item_id = item['name'].split('/')[1] + split_ids.append(item_id) + quantity_sum += item['properties']['quantity'] + self.assertEqual(original_quantity, quantity_sum) + self.assertEqual(2, len(split_ids)) + + merge_command = 'reservations reservation merge --reservation-order-id {} -1 {} -2 {}'.format(reservation_order_id, split_ids[0], split_ids[1]) + merge_items = self.cmd(merge_command).get_output_in_json() + self.assertIsNotNone(merge_items) + for item in merge_items: + self._validate_reservation(item) + if 'Succeeded' in item['properties']['provisioningState']: + self.assertEqual(quantity_sum, item['properties']['quantity']) diff --git a/src/command_modules/azure-cli-reservations/azure_bdist_wheel.py b/src/command_modules/azure-cli-reservations/azure_bdist_wheel.py new file mode 100644 index 00000000000..61ec571a974 --- /dev/null +++ b/src/command_modules/azure-cli-reservations/azure_bdist_wheel.py @@ -0,0 +1,533 @@ +""" +"wheel" copyright (c) 2012-2017 Daniel Holth and +contributors. + +The MIT License + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Create a Azure wheel (.whl) distribution (a wheel is a built archive format). + +This file is a copy of the official bdist_wheel file from wheel 0.30.0a0, enhanced +of the bottom with some Microsoft extension for Azure SDK for Python + +""" + +import csv +import hashlib +import os +import subprocess +import warnings +import shutil +import json +import sys + +try: + import sysconfig +except ImportError: # pragma nocover + # Python < 2.7 + import distutils.sysconfig as sysconfig + +import pkg_resources + +safe_name = pkg_resources.safe_name +safe_version = pkg_resources.safe_version + +from shutil import rmtree +from email.generator import Generator + +from distutils.core import Command +from distutils.sysconfig import get_python_version + +from distutils import log as logger + +from wheel.pep425tags import get_abbr_impl, get_impl_ver, get_abi_tag, get_platform +from wheel.util import native, open_for_csv +from wheel.archive import archive_wheelfile +from wheel.pkginfo import read_pkg_info, write_pkg_info +from wheel.metadata import pkginfo_to_dict +from wheel import pep425tags, metadata +from wheel import __version__ as wheel_version + +def safer_name(name): + return safe_name(name).replace('-', '_') + +def safer_version(version): + return safe_version(version).replace('-', '_') + +class bdist_wheel(Command): + + description = 'create a wheel distribution' + + user_options = [('bdist-dir=', 'b', + "temporary directory for creating the distribution"), + ('plat-name=', 'p', + "platform name to embed in generated filenames " + "(default: %s)" % get_platform()), + ('keep-temp', 'k', + "keep the pseudo-installation tree around after " + + "creating the distribution archive"), + ('dist-dir=', 'd', + "directory to put final built distributions in"), + ('skip-build', None, + "skip rebuilding everything (for testing/debugging)"), + ('relative', None, + "build the archive using relative paths" + "(default: false)"), + ('owner=', 'u', + "Owner name used when creating a tar file" + " [default: current user]"), + ('group=', 'g', + "Group name used when creating a tar file" + " [default: current group]"), + ('universal', None, + "make a universal wheel" + " (default: false)"), + ('python-tag=', None, + "Python implementation compatibility tag" + " (default: py%s)" % get_impl_ver()[0]), + ] + + boolean_options = ['keep-temp', 'skip-build', 'relative', 'universal'] + + def initialize_options(self): + self.bdist_dir = None + self.data_dir = None + self.plat_name = None + self.plat_tag = None + self.format = 'zip' + self.keep_temp = False + self.dist_dir = None + self.distinfo_dir = None + self.egginfo_dir = None + self.root_is_pure = None + self.skip_build = None + self.relative = False + self.owner = None + self.group = None + self.universal = False + self.python_tag = 'py' + get_impl_ver()[0] + self.plat_name_supplied = False + + def finalize_options(self): + if self.bdist_dir is None: + bdist_base = self.get_finalized_command('bdist').bdist_base + self.bdist_dir = os.path.join(bdist_base, 'wheel') + + self.data_dir = self.wheel_dist_name + '.data' + self.plat_name_supplied = self.plat_name is not None + + need_options = ('dist_dir', 'plat_name', 'skip_build') + + self.set_undefined_options('bdist', + *zip(need_options, need_options)) + + self.root_is_pure = not (self.distribution.has_ext_modules() + or self.distribution.has_c_libraries()) + + # Support legacy [wheel] section for setting universal + wheel = self.distribution.get_option_dict('wheel') + if 'universal' in wheel: + # please don't define this in your global configs + val = wheel['universal'][1].strip() + if val.lower() in ('1', 'true', 'yes'): + self.universal = True + + @property + def wheel_dist_name(self): + """Return distribution full name with - replaced with _""" + return '-'.join((safer_name(self.distribution.get_name()), + safer_version(self.distribution.get_version()))) + + def get_tag(self): + # bdist sets self.plat_name if unset, we should only use it for purepy + # wheels if the user supplied it. + if self.plat_name_supplied: + plat_name = self.plat_name + elif self.root_is_pure: + plat_name = 'any' + else: + plat_name = self.plat_name or get_platform() + if plat_name in ('linux-x86_64', 'linux_x86_64') and sys.maxsize == 2147483647: + plat_name = 'linux_i686' + plat_name = plat_name.replace('-', '_').replace('.', '_') + + + if self.root_is_pure: + if self.universal: + impl = 'py2.py3' + else: + impl = self.python_tag + tag = (impl, 'none', plat_name) + else: + impl_name = get_abbr_impl() + impl_ver = get_impl_ver() + # PEP 3149 + abi_tag = str(get_abi_tag()).lower() + tag = (impl_name + impl_ver, abi_tag, plat_name) + supported_tags = pep425tags.get_supported( + supplied_platform=plat_name if self.plat_name_supplied else None) + # XXX switch to this alternate implementation for non-pure: + assert tag == supported_tags[0], "%s != %s" % (tag, supported_tags[0]) + return tag + + def get_archive_basename(self): + """Return archive name without extension""" + + impl_tag, abi_tag, plat_tag = self.get_tag() + + archive_basename = "%s-%s-%s-%s" % ( + self.wheel_dist_name, + impl_tag, + abi_tag, + plat_tag) + return archive_basename + + def run(self): + build_scripts = self.reinitialize_command('build_scripts') + build_scripts.executable = 'python' + + if not self.skip_build: + self.run_command('build') + + install = self.reinitialize_command('install', + reinit_subcommands=True) + install.root = self.bdist_dir + install.compile = False + install.skip_build = self.skip_build + install.warn_dir = False + + # A wheel without setuptools scripts is more cross-platform. + # Use the (undocumented) `no_ep` option to setuptools' + # install_scripts command to avoid creating entry point scripts. + install_scripts = self.reinitialize_command('install_scripts') + install_scripts.no_ep = True + + # Use a custom scheme for the archive, because we have to decide + # at installation time which scheme to use. + for key in ('headers', 'scripts', 'data', 'purelib', 'platlib'): + setattr(install, + 'install_' + key, + os.path.join(self.data_dir, key)) + + basedir_observed = '' + + if os.name == 'nt': + # win32 barfs if any of these are ''; could be '.'? + # (distutils.command.install:change_roots bug) + basedir_observed = os.path.normpath(os.path.join(self.data_dir, '..')) + self.install_libbase = self.install_lib = basedir_observed + + setattr(install, + 'install_purelib' if self.root_is_pure else 'install_platlib', + basedir_observed) + + logger.info("installing to %s", self.bdist_dir) + + self.run_command('install') + + archive_basename = self.get_archive_basename() + + pseudoinstall_root = os.path.join(self.dist_dir, archive_basename) + if not self.relative: + archive_root = self.bdist_dir + else: + archive_root = os.path.join( + self.bdist_dir, + self._ensure_relative(install.install_base)) + + self.set_undefined_options( + 'install_egg_info', ('target', 'egginfo_dir')) + self.distinfo_dir = os.path.join(self.bdist_dir, + '%s.dist-info' % self.wheel_dist_name) + self.egg2dist(self.egginfo_dir, + self.distinfo_dir) + + self.write_wheelfile(self.distinfo_dir) + + self.write_record(self.bdist_dir, self.distinfo_dir) + + # Make the archive + if not os.path.exists(self.dist_dir): + os.makedirs(self.dist_dir) + wheel_name = archive_wheelfile(pseudoinstall_root, archive_root) + + # Sign the archive + if 'WHEEL_TOOL' in os.environ: + subprocess.call([os.environ['WHEEL_TOOL'], 'sign', wheel_name]) + + # Add to 'Distribution.dist_files' so that the "upload" command works + getattr(self.distribution, 'dist_files', []).append( + ('bdist_wheel', get_python_version(), wheel_name)) + + if not self.keep_temp: + if self.dry_run: + logger.info('removing %s', self.bdist_dir) + else: + rmtree(self.bdist_dir) + + def write_wheelfile(self, wheelfile_base, generator='bdist_wheel (' + wheel_version + ')'): + from email.message import Message + msg = Message() + msg['Wheel-Version'] = '1.0' # of the spec + msg['Generator'] = generator + msg['Root-Is-Purelib'] = str(self.root_is_pure).lower() + + # Doesn't work for bdist_wininst + impl_tag, abi_tag, plat_tag = self.get_tag() + for impl in impl_tag.split('.'): + for abi in abi_tag.split('.'): + for plat in plat_tag.split('.'): + msg['Tag'] = '-'.join((impl, abi, plat)) + + wheelfile_path = os.path.join(wheelfile_base, 'WHEEL') + logger.info('creating %s', wheelfile_path) + with open(wheelfile_path, 'w') as f: + Generator(f, maxheaderlen=0).flatten(msg) + + def _ensure_relative(self, path): + # copied from dir_util, deleted + drive, path = os.path.splitdrive(path) + if path[0:1] == os.sep: + path = drive + path[1:] + return path + + def _pkginfo_to_metadata(self, egg_info_path, pkginfo_path): + return metadata.pkginfo_to_metadata(egg_info_path, pkginfo_path) + + def license_file(self): + """Return license filename from a license-file key in setup.cfg, or None.""" + metadata = self.distribution.get_option_dict('metadata') + if not 'license_file' in metadata: + return None + return metadata['license_file'][1] + + def setupcfg_requirements(self): + """Generate requirements from setup.cfg as + ('Requires-Dist', 'requirement; qualifier') tuples. From a metadata + section in setup.cfg: + + [metadata] + provides-extra = extra1 + extra2 + requires-dist = requirement; qualifier + another; qualifier2 + unqualified + + Yields + + ('Provides-Extra', 'extra1'), + ('Provides-Extra', 'extra2'), + ('Requires-Dist', 'requirement; qualifier'), + ('Requires-Dist', 'another; qualifier2'), + ('Requires-Dist', 'unqualified') + """ + metadata = self.distribution.get_option_dict('metadata') + + # our .ini parser folds - to _ in key names: + for key, title in (('provides_extra', 'Provides-Extra'), + ('requires_dist', 'Requires-Dist')): + if not key in metadata: + continue + field = metadata[key] + for line in field[1].splitlines(): + line = line.strip() + if not line: + continue + yield (title, line) + + def add_requirements(self, metadata_path): + """Add additional requirements from setup.cfg to file metadata_path""" + additional = list(self.setupcfg_requirements()) + if not additional: return + pkg_info = read_pkg_info(metadata_path) + if 'Provides-Extra' in pkg_info or 'Requires-Dist' in pkg_info: + warnings.warn('setup.cfg requirements overwrite values from setup.py') + del pkg_info['Provides-Extra'] + del pkg_info['Requires-Dist'] + for k, v in additional: + pkg_info[k] = v + write_pkg_info(metadata_path, pkg_info) + + def egg2dist(self, egginfo_path, distinfo_path): + """Convert an .egg-info directory into a .dist-info directory""" + def adios(p): + """Appropriately delete directory, file or link.""" + if os.path.exists(p) and not os.path.islink(p) and os.path.isdir(p): + shutil.rmtree(p) + elif os.path.exists(p): + os.unlink(p) + + adios(distinfo_path) + + if not os.path.exists(egginfo_path): + # There is no egg-info. This is probably because the egg-info + # file/directory is not named matching the distribution name used + # to name the archive file. Check for this case and report + # accordingly. + import glob + pat = os.path.join(os.path.dirname(egginfo_path), '*.egg-info') + possible = glob.glob(pat) + err = "Egg metadata expected at %s but not found" % (egginfo_path,) + if possible: + alt = os.path.basename(possible[0]) + err += " (%s found - possible misnamed archive file?)" % (alt,) + + raise ValueError(err) + + if os.path.isfile(egginfo_path): + # .egg-info is a single file + pkginfo_path = egginfo_path + pkg_info = self._pkginfo_to_metadata(egginfo_path, egginfo_path) + os.mkdir(distinfo_path) + else: + # .egg-info is a directory + pkginfo_path = os.path.join(egginfo_path, 'PKG-INFO') + pkg_info = self._pkginfo_to_metadata(egginfo_path, pkginfo_path) + + # ignore common egg metadata that is useless to wheel + shutil.copytree(egginfo_path, distinfo_path, + ignore=lambda x, y: set(('PKG-INFO', + 'requires.txt', + 'SOURCES.txt', + 'not-zip-safe',))) + + # delete dependency_links if it is only whitespace + dependency_links_path = os.path.join(distinfo_path, 'dependency_links.txt') + with open(dependency_links_path, 'r') as dependency_links_file: + dependency_links = dependency_links_file.read().strip() + if not dependency_links: + adios(dependency_links_path) + + write_pkg_info(os.path.join(distinfo_path, 'METADATA'), pkg_info) + + # XXX deprecated. Still useful for current distribute/setuptools. + metadata_path = os.path.join(distinfo_path, 'METADATA') + self.add_requirements(metadata_path) + + # XXX intentionally a different path than the PEP. + metadata_json_path = os.path.join(distinfo_path, 'metadata.json') + pymeta = pkginfo_to_dict(metadata_path, + distribution=self.distribution) + + if 'description' in pymeta: + description_filename = 'DESCRIPTION.rst' + description_text = pymeta.pop('description') + description_path = os.path.join(distinfo_path, + description_filename) + with open(description_path, "wb") as description_file: + description_file.write(description_text.encode('utf-8')) + pymeta['extensions']['python.details']['document_names']['description'] = description_filename + + # XXX heuristically copy any LICENSE/LICENSE.txt? + license = self.license_file() + if license: + license_filename = 'LICENSE.txt' + shutil.copy(license, os.path.join(self.distinfo_dir, license_filename)) + pymeta['extensions']['python.details']['document_names']['license'] = license_filename + + with open(metadata_json_path, "w") as metadata_json: + json.dump(pymeta, metadata_json, sort_keys=True) + + adios(egginfo_path) + + def write_record(self, bdist_dir, distinfo_dir): + from wheel.util import urlsafe_b64encode + + record_path = os.path.join(distinfo_dir, 'RECORD') + record_relpath = os.path.relpath(record_path, bdist_dir) + + def walk(): + for dir, dirs, files in os.walk(bdist_dir): + dirs.sort() + for f in sorted(files): + yield os.path.join(dir, f) + + def skip(path): + """Wheel hashes every possible file.""" + return (path == record_relpath) + + with open_for_csv(record_path, 'w+') as record_file: + writer = csv.writer(record_file) + for path in walk(): + relpath = os.path.relpath(path, bdist_dir) + if skip(relpath): + hash = '' + size = '' + else: + with open(path, 'rb') as f: + data = f.read() + digest = hashlib.sha256(data).digest() + hash = 'sha256=' + native(urlsafe_b64encode(digest)) + size = len(data) + record_path = os.path.relpath( + path, bdist_dir).replace(os.path.sep, '/') + writer.writerow((record_path, hash, size)) + + +#------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for +# license information. +#-------------------------------------------------------------------------- + +from distutils import log as logger +import os.path + +#from wheel.bdist_wheel import bdist_wheel +class azure_bdist_wheel(bdist_wheel): + + description = "Create an Azure wheel distribution" + + user_options = bdist_wheel.user_options + \ + [('azure-namespace-package=', None, + "Name of the deepest nspkg used")] + + def initialize_options(self): + bdist_wheel.initialize_options(self) + self.azure_namespace_package = None + + def finalize_options(self): + bdist_wheel.finalize_options(self) + if self.azure_namespace_package and not self.azure_namespace_package.endswith("-nspkg"): + raise ValueError("azure_namespace_package must finish by -nspkg") + + def run(self): + if not self.distribution.install_requires: + self.distribution.install_requires = [] + self.distribution.install_requires.append( + "{}>=2.0.0".format(self.azure_namespace_package)) + bdist_wheel.run(self) + + def write_record(self, bdist_dir, distinfo_dir): + if self.azure_namespace_package: + # Split and remove last part, assuming it's "nspkg" + subparts = self.azure_namespace_package.split('-')[0:-1] + folder_with_init = [os.path.join(*subparts[0:i+1]) for i in range(len(subparts))] + for azure_sub_package in folder_with_init: + init_file = os.path.join(bdist_dir, azure_sub_package, '__init__.py') + if os.path.isfile(init_file): + logger.info("manually remove {} while building the wheel".format(init_file)) + os.remove(init_file) + else: + raise ValueError("Unable to find {}. Are you sure of your namespace package?".format(init_file)) + bdist_wheel.write_record(self, bdist_dir, distinfo_dir) +cmdclass = { + 'bdist_wheel': azure_bdist_wheel, +} diff --git a/src/command_modules/azure-cli-reservations/setup.cfg b/src/command_modules/azure-cli-reservations/setup.cfg new file mode 100644 index 00000000000..a50dd75dc1c --- /dev/null +++ b/src/command_modules/azure-cli-reservations/setup.cfg @@ -0,0 +1,3 @@ +[bdist_wheel] +universal=1 +azure-namespace-package=azure-cli-command_modules-nspkg \ No newline at end of file diff --git a/src/command_modules/azure-cli-reservations/setup.py b/src/command_modules/azure-cli-reservations/setup.py new file mode 100644 index 00000000000..88b432ce09c --- /dev/null +++ b/src/command_modules/azure-cli-reservations/setup.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python + +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- + +from codecs import open +from setuptools import setup + +try: + from azure_bdist_wheel import cmdclass +except ImportError: + from distutils import log as logger + logger.warn("Wheel is not available, disabling bdist_wheel hook") + cmdclass = {} + +VERSION = "0.1.0" +# The full list of classifiers is available at +# https://pypi.python.org/pypi?%3Aaction=list_classifiers +CLASSIFIERS = [ + 'Development Status :: 4 - Beta', + 'Intended Audience :: Developers', + 'Intended Audience :: System Administrators', + 'Programming Language :: Python', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'License :: OSI Approved :: MIT License', +] + +DEPENDENCIES = [ + 'azure-mgmt-reservations==0.1.0', + 'azure-cli-core' +] + +with open('README.rst', 'r', encoding='utf-8') as f: + README = f.read() +with open('HISTORY.rst', 'r', encoding='utf-8') as f: + HISTORY = f.read() + +setup( + name='azure-cli-reservations', + version=VERSION, + description='Microsoft Azure Command-Line Tools Reservations Command Module', + long_description=README + '\n\n' + HISTORY, + license='MIT', + author='Microsoft Corporation', + author_email='azpycli@microsoft.com', + url='https://github.com/azure/azure-cli', + classifiers=CLASSIFIERS, + packages=[ + 'azure', + 'azure.cli', + 'azure.cli.command_modules', + 'azure.cli.command_modules.reservations', + ], + install_requires=DEPENDENCIES, + cmdclass=cmdclass +)