Simplify "vm image list" so querying images gets straightforward (#198)

This commit is contained in:
Yugang Wang 2016-05-03 17:05:27 -07:00
Родитель 1d2461b316
Коммит 6522fc0b23
7 изменённых файлов: 596 добавлений и 23 удалений

Просмотреть файл

@ -1,4 +1,6 @@
import json
import json
import re
try:
from urllib.request import urlopen
except ImportError:
@ -113,45 +115,133 @@ def _vm_disk_detach(args, instance):
except StopIteration:
raise RuntimeError("No disk with the name '%s' found" % args.get('name'))
#temporary behavior, filters for publisher, sku, etc will be supported soon
@command_table.command('vm image list-aliases')
@command_table.description(L('a temporary command you can query for the most common images'
', and use the details to create a new VM.'))
def _list_images(_):
return read_images_from_aliases_doc()
def read_images_from_aliases_doc():
def _load_images_from_aliases_doc(publisher, offer, sku):
target_url = ('https://raw.githubusercontent.com/Azure/azure-rest-api-specs/'
'master/arm-compute/quickstart-templates/aliases.json')
txt = urlopen(target_url).read()
dic = json.loads(txt.decode())
try:
result = dic['outputs']['aliases']['value']
all_images = []
result = (dic['outputs']['aliases']['value'])
for v in result.values(): #loop around os
for vv in v.values(): #loop around distros
vv['urn'] = ':'.join([vv['publisher'], vv['offer'], vv['sku'], vv['version']])
return result
all_images.append({
'publisher': vv['publisher'],
'offer': vv['offer'],
'sku': vv['sku'],
'version': vv['version']
})
all_images = [i for i in all_images if (_partial_matched(publisher, i['publisher']) and
_partial_matched(offer, i['offer']) and
_partial_matched(sku, i['sku']))]
return all_images
except KeyError:
raise RuntimeError('Could not retrieve image list from {}'.format(target_url))
def _load_images_thru_services(publisher, offer, sku, location):
from concurrent.futures import ThreadPoolExecutor
all_images = []
client = _compute_client_factory({})
def _load_images_from_publisher(publisher):
offers = client.virtual_machine_images.list_offers(location, publisher)
if offer:
offers = [o for o in offers if _partial_matched(offer, o.name)]
for o in offers:
skus = client.virtual_machine_images.list_skus(location, publisher, o.name)
if sku:
skus = [s for s in skus if _partial_matched(sku, s.name)]
for s in skus:
images = client.virtual_machine_images.list(location, publisher, o.name, s.name)
for i in images:
all_images.append({
'publisher': publisher,
'offer': o.name,
'sku': s.name,
'version': i.name})
publishers = client.virtual_machine_images.list_publishers(location)
if publisher:
publishers = [p for p in publishers if _partial_matched(publisher, p.name)]
publisher_num = len(publishers)
if publisher_num > 1:
with ThreadPoolExecutor(max_workers=40) as executor:
for p in publishers:
executor.submit(_load_images_from_publisher, p.name)
elif publisher_num == 1:
_load_images_from_publisher(publishers[0].name)
return all_images
def _partial_matched(pattern, string):
if not pattern:
return True # empty pattern means wildcard-match
pattern = r'.*' + pattern
return re.match(pattern, string, re.I)
def _create_image_instance(publisher, offer, sku, version):
return {
'publisher': publisher,
'offer': offer,
'sku': sku,
'version': version
}
#
# Composite convenience commands for the CLI
#
def _parse_rg_name(strid):
'''From an ID, extract the contained (resource group, name) tuple
'''
import re
parts = re.split('/', strid)
if parts[3] != 'resourceGroups':
raise KeyError()
return (parts[4], parts[8])
class ConvenienceVmCommands(object): # pylint: disable=too-few-public-methods
def __init__(self, _):
pass
def list_ip_addresses(self, optional_resource_group_name=None, vm_name=None): # pylint: disable=no-self-use
# pylint: disable=no-self-use,too-many-arguments
def list_vm_images(self,
image_location=None,
publisher=None,
offer=None,
sku=None,
all=False): #pylint: disable=redefined-builtin
'''vm image list
:param str location:Image location
:param str publisher:Image publisher name
:param str offer:Image offer name
:param str sku:Image sku name
:param bool all:Retrieve all versions of images from all publishers
'''
load_thru_services = all
if load_thru_services and not image_location:
raise RuntimeError('Argument of --location/-l is required to use with --all flag')
if load_thru_services:
all_images = _load_images_thru_services(publisher,
offer,
sku,
image_location)
else:
all_images = _load_images_from_aliases_doc(publisher, offer, sku)
for i in all_images:
i['urn'] = ':'.join([i['publisher'], i['offer'], i['sku'], i['version']])
return all_images
def list_ip_addresses(self,
optional_resource_group_name=None,
vm_name=None):
''' Get IP addresses from one or more Virtual Machines
:param str optional_resource_group_name:Name of resource group.
:param str vm_name:Name of virtual machine.
@ -204,3 +294,5 @@ class ConvenienceVmCommands(object): # pylint: disable=too-few-public-methods
})
return result

Просмотреть файл

@ -76,7 +76,6 @@ build_operation("vm image",
_compute_client_factory,
[
AutoCommandDefinition(VirtualMachineImagesOperations.get, 'VirtualMachineImage', command_alias='show'),
AutoCommandDefinition(VirtualMachineImagesOperations.list, '[VirtualMachineImageResource]'),
AutoCommandDefinition(VirtualMachineImagesOperations.list_offers, '[VirtualMachineImageResource]'),
AutoCommandDefinition(VirtualMachineImagesOperations.list_publishers, '[VirtualMachineImageResource]'),
AutoCommandDefinition(VirtualMachineImagesOperations.list_skus, '[VirtualMachineImageResource]'),
@ -262,3 +261,16 @@ build_operation('vm',
command_table,
vm_param_aliases,
extra_parameters)
build_operation("vm image",
None,
ConvenienceVmCommands,
[
AutoCommandDefinition(ConvenienceVmCommands.list_vm_images, 'object', 'list')
],
command_table,
_patch_aliases({
#get rid of the alias with work on https://www.pivotaltracker.com/projects/1535539/stories/118884633
'image_location' : {'name': '--location -l', 'help': 'Image location'}
}))

Просмотреть файл

@ -1,4 +1,27 @@
# AZURE CLI VM TEST DEFINITIONS
# AZURE CLI VM TEST DEFINITIONS
from azure.cli.utils.command_test_script import CommandTestScript
#pylint: disable=method-hidden
class VMImageListByAliasesScenarioTest(CommandTestScript):
def test_body(self):
result = self.run('vm image list --offer ubuntu -o tsv')
assert result.index('14.04.4-LTS') >= 0
def __init__(self):
super(VMImageListByAliasesScenarioTest, self).__init__(None, self.test_body, None)
class VMImageListThruServiceScenarioTest(CommandTestScript):
def test_body(self):
cmd = ('vm image list -l westus --publisher Canonical --offer '
'Ubuntu_Snappy_Core -o tsv --all')
result = self.run(cmd)
assert result.index('15.04') >= 0
def __init__(self):
super(VMImageListThruServiceScenarioTest, self).__init__(None, self.test_body, None)
ENV_VAR = {}
@ -10,5 +33,15 @@ TEST_DEF = [
{
'test_name': 'vm_list_from_group',
'command': 'vm list --resource-group XPLATTESTGEXTENSION9085',
},
{
'test_name': 'vm_images_list_by_aliases',
'command': VMImageListByAliasesScenarioTest()
},
{
'test_name': 'vm_images_list_thru_services',
'command': VMImageListThruServiceScenarioTest()
}
]

Просмотреть файл

@ -1,4 +1,6 @@
{
"test_vm_images_list_by_aliases": "",
"test_vm_images_list_thru_services": "",
"test_vm_list_from_group": "Availability Set : None\nId : /subscriptions/0b1f6471-1bf0-4dda-aec3-cb9272f09590/resourceGroups/XPLATTESTGEXTENSION9085/providers/Microsoft.Compute/virtualMachines/xplatvmExt1314\nInstance View : None\nLicense Type : None\nLocation : southeastasia\nName : xplatvmExt1314\nPlan : None\nProvisioning State : Succeeded\nResource Group : XPLATTESTGEXTENSION9085\nResources : None\nType : Microsoft.Compute/virtualMachines\nDiagnostics Profile :\n Boot Diagnostics :\n Enabled : True\n Storage Uri : https://xplatstoragext4633.blob.core.windows.net/\nHardware Profile :\n Vm Size : Standard_A1\nNetwork Profile :\n Network Interfaces :\n Id : /subscriptions/0b1f6471-1bf0-4dda-aec3-cb9272f09590/resourceGroups/xplatTestGExtension9085/providers/Microsoft.Network/networkInterfaces/xplatnicExt4843\n Primary : None\n Resource Group : xplatTestGExtension9085\nOs Profile :\n Admin Password : None\n Admin Username : azureuser\n Computer Name : xplatvmExt1314\n Custom Data : None\n Linux Configuration : None\n Secrets :\n None\n Windows Configuration :\n Additional Unattend Content : None\n Enable Automatic Updates : True\n Provision Vm Agent : True\n Time Zone : None\n Win Rm : None\nStorage Profile :\n Data Disks :\n None\n Image Reference :\n Offer : WindowsServerEssentials\n Publisher : MicrosoftWindowsServerEssentials\n Sku : WindowsServerEssentials\n Version : 1.0.20131018\n Os Disk :\n Caching : ReadWrite\n Create Option : fromImage\n Disk Size Gb : None\n Encryption Settings : None\n Image : None\n Name : cli1eaed78b36def353-os-1453419539945\n Os Type : Windows\n Vhd :\n Uri : https://xplatstoragext4633.blob.core.windows.net/xplatstoragecntext1789/cli1eaed78b36def353-os-1453419539945.vhd\nTags :\n None\n\n\n",
"test_vm_usage_list_westus": "[\n {\n \"currentValue\": 0,\n \"limit\": 2000,\n \"name\": {\n \"localizedValue\": \"Availability Sets\",\n \"value\": \"availabilitySets\"\n },\n \"unit\": \"Count\"\n },\n {\n \"currentValue\": 7,\n \"limit\": 100,\n \"name\": {\n \"localizedValue\": \"Total Regional Cores\",\n \"value\": \"cores\"\n },\n \"unit\": \"Count\"\n },\n {\n \"currentValue\": 5,\n \"limit\": 10000,\n \"name\": {\n \"localizedValue\": \"Virtual Machines\",\n \"value\": \"virtualMachines\"\n },\n \"unit\": \"Count\"\n },\n {\n \"currentValue\": 0,\n \"limit\": 50,\n \"name\": {\n \"localizedValue\": \"Virtual Machine Scale Sets\",\n \"value\": \"virtualMachineScaleSets\"\n },\n \"unit\": \"Count\"\n },\n {\n \"currentValue\": 1,\n \"limit\": 100,\n \"name\": {\n \"localizedValue\": \"Standard D Family Cores\",\n \"value\": \"standardDFamily\"\n },\n \"unit\": \"Count\"\n },\n {\n \"currentValue\": 6,\n \"limit\": 100,\n \"name\": {\n \"localizedValue\": \"Standard A0-A7 Family Cores\",\n \"value\": \"standardA0_A7Family\"\n },\n \"unit\": \"Count\"\n }\n]\n"
}

Просмотреть файл

@ -0,0 +1,71 @@
interactions:
- request:
body: null
headers:
Connection: [close]
Host: [raw.githubusercontent.com]
User-Agent: [Python-urllib/3.5]
method: GET
uri: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/master/arm-compute/quickstart-templates/aliases.json
response:
body: {string: "{\n \"$schema\":\"http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json\"\
,\n \"contentVersion\":\"1.0.0.0\",\n \"parameters\":{},\n \"variables\"\
:{},\n \"resources\":[],\n\n \"outputs\":{\n \"aliases\":{\n \"\
metadata\":{\n \"description\":\"This list of aliases is used by Azure\
\ XPLAT CLI, Azure Powershell, and Azure Portal as shorthands for commonly\
\ used VM images. If you change this file, please verify that this doesn't\
\ break VMSS creation from Portal :).\"\n },\n \"type\":\"object\"\
,\n \"value\":{\n\n \"Linux\":{\n \"CentOS\":{\n \
\ \"publisher\":\"OpenLogic\",\n \"offer\":\"CentOS\",\n\
\ \"sku\":\"7.2\",\n \"version\":\"latest\"\n \
\ },\n \"CoreOS\":{\n \"publisher\":\"CoreOS\",\n \
\ \"offer\":\"CoreOS\",\n \"sku\":\"Stable\",\n \
\ \"version\":\"latest\"\n },\n \"Debian\":{\n \
\ \"publisher\":\"credativ\",\n \"offer\":\"Debian\",\n\
\ \"sku\":\"8\",\n \"version\":\"latest\"\n \
\ },\n \"openSUSE\":{\n \"publisher\":\"SUSE\",\n \
\ \"offer\":\"openSUSE\",\n \"sku\":\"13.2\",\n \
\ \"version\":\"latest\"\n },\n \"RHEL\":{\n \
\ \"publisher\":\"RedHat\",\n \"offer\":\"RHEL\",\n \
\ \"sku\":\"7.2\",\n \"version\":\"latest\"\n },\n\
\ \"SLES\":{\n \"publisher\":\"SUSE\",\n \"\
offer\":\"SLES\",\n \"sku\":\"12-SP1\",\n \"version\"\
:\"latest\"\n },\n \"UbuntuLTS\":{\n \"publisher\"\
:\"Canonical\",\n \"offer\":\"UbuntuServer\",\n \"sku\"\
:\"14.04.4-LTS\",\n \"version\":\"latest\"\n }\n \
\ },\n\n \"Windows\":{\n \"Win2012R2Datacenter\":{\n \
\ \"publisher\":\"MicrosoftWindowsServer\",\n \"offer\"\
:\"WindowsServer\",\n \"sku\":\"2012-R2-Datacenter\",\n \
\ \"version\":\"latest\"\n },\n \"Win2012Datacenter\"\
:{\n \"publisher\":\"MicrosoftWindowsServer\",\n \"\
offer\":\"WindowsServer\",\n \"sku\":\"2012-Datacenter\",\n \
\ \"version\":\"latest\"\n },\n \"Win2008R2SP1\"\
:{\n \"publisher\":\"MicrosoftWindowsServer\",\n \"\
offer\":\"WindowsServer\",\n \"sku\":\"2008-R2-SP1\",\n \
\ \"version\":\"latest\"\n }\n }\n }\n }\n }\n\
}\n"}
headers:
Accept-Ranges: [bytes]
Access-Control-Allow-Origin: ['*']
Cache-Control: [max-age=300]
Connection: [close]
Content-Length: ['2297']
Content-Security-Policy: [default-src 'none'; style-src 'unsafe-inline']
Content-Type: [text/plain; charset=utf-8]
Date: ['Tue, 03 May 2016 03:40:49 GMT']
ETag: ['"db78eb36618a060181b32ac2de91b1733f382e01"']
Expires: ['Tue, 03 May 2016 03:45:49 GMT']
Source-Age: ['0']
Strict-Transport-Security: [max-age=31536000]
Vary: ['Authorization,Accept-Encoding']
Via: [1.1 varnish]
X-Cache: [MISS]
X-Cache-Hits: ['0']
X-Content-Type-Options: [nosniff]
X-Fastly-Request-ID: [13192701239be1866c66d0f0c6155cadff9d7f9d]
X-Frame-Options: [deny]
X-GitHub-Request-Id: ['17EB2F14:6091:7F1D34B:57281DC1']
X-Served-By: [cache-sjc3122-SJC]
X-XSS-Protection: [1; mode=block]
status: {code: 200, message: OK}
version: 1

Просмотреть файл

@ -0,0 +1,363 @@
interactions:
- request:
body: null
headers:
Accept: [application/json]
Accept-Encoding: ['gzip, deflate']
Connection: [keep-alive]
Content-Type: [application/json; charset=utf-8]
User-Agent: [python/3.5.0 requests/2.9.1 msrest/0.3.0 msrest_azure/0.3.0 computemanagementclient/2015-06-15
Azure-SDK-For-Python AZURECLI_0.0.32]
accept-language: [en-US]
method: GET
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Compute/locations/westus/publishers?api-version=2015-06-15
response:
body:
string: !!binary |
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
headers:
Cache-Control: [no-cache]
Content-Encoding: [gzip]
Content-Type: [application/json; charset=utf-8]
Date: ['Tue, 03 May 2016 03:52:45 GMT']
Expires: ['-1']
Pragma: [no-cache]
Server: [Microsoft-HTTPAPI/2.0, Microsoft-HTTPAPI/2.0]
Strict-Transport-Security: [max-age=31536000; includeSubDomains]
Vary: [Accept-Encoding]
status: {code: 200, message: OK}
- request:
body: null
headers:
Accept: [application/json]
Accept-Encoding: ['gzip, deflate']
Connection: [keep-alive]
Content-Type: [application/json; charset=utf-8]
User-Agent: [python/3.5.0 requests/2.9.1 msrest/0.3.0 msrest_azure/0.3.0 computemanagementclient/2015-06-15
Azure-SDK-For-Python AZURECLI_0.0.32]
accept-language: [en-US]
method: GET
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Compute/locations/westus/publishers/Canonical/artifacttypes/vmimage/offers?api-version=2015-06-15
response:
body:
string: !!binary |
H4sIAAAAAAAEAO29B2AcSZYlJi9tynt/SvVK1+B0oQiAYBMk2JBAEOzBiM3mkuwdaUcjKasqgcpl
VmVdZhZAzO2dvPfee++999577733ujudTif33/8/XGZkAWz2zkrayZ4hgKrIHz9+fB8/Ir73Gydp
+ovxT5p+VFbTrC2q5UeP0o+u8qZdNx+N9Ktltsjx8VeT9bJd794f7+y/Xmar1bVtUczw/d3X60kz
rYsV4DR3dya755/uP9jd3p2c72zvz2bZdpZP721PJw/3Huyd7zy8/3Dn7su6uixmed3c/aKY1lVT
nbfjk2qxWrf53eeKUnNXELr7cj0pi2aO1ifZsloW06y8e1y3xXk2bd9cr/Lm7k9+cbbILvK7X56f
o1kfZWD8SxjvDxn502r6Nq9tu//vjF8RB95fkwp1VZbF8kLA2Tb/L6dAiDRw/pqjf53Xl0Q/8+X/
y4et2ALZrzne319I9vufVHVum/y/fNQBzkD5Gxj776+CY1r+f4gEBnVg/kt+4+T7/w+0FbQ39wUA
AA==
headers:
Cache-Control: [no-cache]
Content-Encoding: [gzip]
Content-Type: [application/json; charset=utf-8]
Date: ['Tue, 03 May 2016 03:52:45 GMT']
Expires: ['-1']
Pragma: [no-cache]
Server: [Microsoft-HTTPAPI/2.0, Microsoft-HTTPAPI/2.0]
Strict-Transport-Security: [max-age=31536000; includeSubDomains]
Vary: [Accept-Encoding]
status: {code: 200, message: OK}
- request:
body: null
headers:
Accept: [application/json]
Accept-Encoding: ['gzip, deflate']
Connection: [keep-alive]
Content-Type: [application/json; charset=utf-8]
User-Agent: [python/3.5.0 requests/2.9.1 msrest/0.3.0 msrest_azure/0.3.0 computemanagementclient/2015-06-15
Azure-SDK-For-Python AZURECLI_0.0.32]
accept-language: [en-US]
method: GET
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Compute/locations/westus/publishers/Canonical/artifacttypes/vmimage/offers/Ubuntu_Snappy_Core/skus?api-version=2015-06-15
response:
body:
string: !!binary |
H4sIAAAAAAAEAO29B2AcSZYlJi9tynt/SvVK1+B0oQiAYBMk2JBAEOzBiM3mkuwdaUcjKasqgcpl
VmVdZhZAzO2dvPfee++999577733ujudTif33/8/XGZkAWz2zkrayZ4hgKrIHz9+fB8/Ir73Gydp
+ovxT5p+VFbTrC2q5UeP0o+u8qZdNx+N9Ktltsjx8e798c6+/bSY4bO7r9eTZloXK7zb3N2Z7J5/
uv9gd3t3cr6zvT+bZdtZPr23PZ083Huwd77z8P7Dnbsv6+qymOV1c/eLYlpXTXXejk+qxWrd5nef
KxrNXUHi7sv1pCyaOVqfZMtqWUyz8u5x3Rbn2bR9c73Km7s/+cXZIrvI7355fo5mX03Wy3b9+79e
ZqvV9e9/UtX53ddvCZKgD+x/CY/hPUb+qirLYnlhP///3NjNAID/L/mNk+//P29+Lmz7AQAA
headers:
Cache-Control: [no-cache]
Content-Encoding: [gzip]
Content-Type: [application/json; charset=utf-8]
Date: ['Tue, 03 May 2016 03:52:45 GMT']
Expires: ['-1']
Pragma: [no-cache]
Server: [Microsoft-HTTPAPI/2.0, Microsoft-HTTPAPI/2.0]
Strict-Transport-Security: [max-age=31536000; includeSubDomains]
Vary: [Accept-Encoding]
status: {code: 200, message: OK}
- request:
body: null
headers:
Accept: [application/json]
Accept-Encoding: ['gzip, deflate']
Connection: [keep-alive]
Content-Type: [application/json; charset=utf-8]
User-Agent: [python/3.5.0 requests/2.9.1 msrest/0.3.0 msrest_azure/0.3.0 computemanagementclient/2015-06-15
Azure-SDK-For-Python AZURECLI_0.0.32]
accept-language: [en-US]
method: GET
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Compute/locations/westus/publishers/Canonical/artifacttypes/vmimage/offers/Ubuntu_Snappy_Core/skus/15.04/versions?api-version=2015-06-15
response:
body:
string: !!binary |
H4sIAAAAAAAEAO29B2AcSZYlJi9tynt/SvVK1+B0oQiAYBMk2JBAEOzBiM3mkuwdaUcjKasqgcpl
VmVdZhZAzO2dvPfee++999577733ujudTif33/8/XGZkAWz2zkrayZ4hgKrIHz9+fB8/Ir73Gydp
+ovxT5p+VFbTrC2q5UeP0o+u8qZdNx+N9Ktltsjx8d7O7v3xzsHew/HOp/fv2a+LGb68+3o9aaZ1
sQKQ5u7OZPf80/0Hu9u7k/Od7f3ZLNvO8um97enk4d6DvfOdh/cf7tx9WVeXxSyvm7tfFNO6aqrz
dnxSLVbrNr/7XPFp7go2d1+uJ2XRzNH6JFtWy2KalXeP67Y4z6btm+tV3tz9yS/OFtlFfvfL83M0
+2qyXrbr3//1Mlutrn//k6rO775+S5Awiv27P0lNGH5nWBjVL+GxvTdpHu7tj3cP7t+3X///gzR2
WBjV1yHNp+OdPcAAec3X/z8gjT8sjOprk+b+mP7//z/S6LAwqq9NmofjvR2CYb7+/wtpdFgY1dck
zb3dg/Hug/t79uv/f5DGDguj+hDSPNx/aL/+/xFpMCyM6pf8xsn3/x81FIciwAcAAA==
headers:
Cache-Control: [no-cache]
Content-Encoding: [gzip]
Content-Type: [application/json; charset=utf-8]
Date: ['Tue, 03 May 2016 03:52:46 GMT']
Expires: ['-1']
Pragma: [no-cache]
Server: [Microsoft-HTTPAPI/2.0, Microsoft-HTTPAPI/2.0]
Strict-Transport-Security: [max-age=31536000; includeSubDomains]
Vary: [Accept-Encoding]
status: {code: 200, message: OK}
- request:
body: null
headers:
Accept: [application/json]
Accept-Encoding: ['gzip, deflate']
Connection: [keep-alive]
Content-Type: [application/json; charset=utf-8]
User-Agent: [python/3.5.0 requests/2.9.1 msrest/0.3.0 msrest_azure/0.3.0 computemanagementclient/2015-06-15
Azure-SDK-For-Python AZURECLI_0.0.32]
accept-language: [en-US]
method: GET
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Compute/locations/westus/publishers/Canonical/artifacttypes/vmimage/offers/Ubuntu_Snappy_Core/skus/Rolling/versions?api-version=2015-06-15
response:
body:
string: !!binary |
H4sIAAAAAAAEAO29B2AcSZYlJi9tynt/SvVK1+B0oQiAYBMk2JBAEOzBiM3mkuwdaUcjKasqgcpl
VmVdZhZAzO2dvPfee++999577733ujudTif33/8/XGZkAWz2zkrayZ4hgKrIHz9+fB8/Ir73/f8H
KbtMDQIAAAA=
headers:
Cache-Control: [no-cache]
Content-Encoding: [gzip]
Content-Type: [application/json; charset=utf-8]
Date: ['Tue, 03 May 2016 03:52:46 GMT']
Expires: ['-1']
Pragma: [no-cache]
Server: [Microsoft-HTTPAPI/2.0, Microsoft-HTTPAPI/2.0]
Strict-Transport-Security: [max-age=31536000; includeSubDomains]
Vary: [Accept-Encoding]
status: {code: 200, message: OK}
- request:
body: null
headers:
Accept: [application/json]
Accept-Encoding: ['gzip, deflate']
Connection: [keep-alive]
Content-Type: [application/json; charset=utf-8]
User-Agent: [python/3.5.0 requests/2.9.1 msrest/0.3.0 msrest_azure/0.3.0 computemanagementclient/2015-06-15
Azure-SDK-For-Python AZURECLI_0.0.32]
accept-language: [en-US]
method: GET
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Compute/locations/westus/publishers/Canonical/artifacttypes/vmimage/offers/Ubuntu_Snappy_Core_Docker/skus?api-version=2015-06-15
response:
body:
string: !!binary |
H4sIAAAAAAAEAO29B2AcSZYlJi9tynt/SvVK1+B0oQiAYBMk2JBAEOzBiM3mkuwdaUcjKasqgcpl
VmVdZhZAzO2dvPfee++999577733ujudTif33/8/XGZkAWz2zkrayZ4hgKrIHz9+fB8/Ir73Gydp
+ovxT5p+VFbTrC2q5UeP0o+u8qZdNx+N9Ktltsjx8e798c6+/bSY4bO7r9eTZloXK7zb3N2Z7J5/
uv9gd3t3cr6zvT+bZdtZPr23PZ083Huwd77z8P7Dnbsv6+qymOV1c/eLYlpXTXXejk+qxWrd5nef
KxrNXUHi7sv1pCyaOVqfZMtqWUyz8u5x3Rbn2bR9c73Km7s/+cXZIrvI7355fo5mX03Wy3b9+79e
ZqvV9e9/UtX57/+0mr7N67uv3xJAGQUG8Ut+4+T7/w9aDaNvBAEAAA==
headers:
Cache-Control: [no-cache]
Content-Encoding: [gzip]
Content-Type: [application/json; charset=utf-8]
Date: ['Tue, 03 May 2016 03:52:47 GMT']
Expires: ['-1']
Pragma: [no-cache]
Server: [Microsoft-HTTPAPI/2.0, Microsoft-HTTPAPI/2.0]
Strict-Transport-Security: [max-age=31536000; includeSubDomains]
Vary: [Accept-Encoding]
status: {code: 200, message: OK}
- request:
body: null
headers:
Accept: [application/json]
Accept-Encoding: ['gzip, deflate']
Connection: [keep-alive]
Content-Type: [application/json; charset=utf-8]
User-Agent: [python/3.5.0 requests/2.9.1 msrest/0.3.0 msrest_azure/0.3.0 computemanagementclient/2015-06-15
Azure-SDK-For-Python AZURECLI_0.0.32]
accept-language: [en-US]
method: GET
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Compute/locations/westus/publishers/Canonical/artifacttypes/vmimage/offers/Ubuntu_Snappy_Core_Docker/skus/15.04/versions?api-version=2015-06-15
response:
body:
string: !!binary |
H4sIAAAAAAAEAO29B2AcSZYlJi9tynt/SvVK1+B0oQiAYBMk2JBAEOzBiM3mkuwdaUcjKasqgcpl
VmVdZhZAzO2dvPfee++999577733ujudTif33/8/XGZkAWz2zkrayZ4hgKrIHz9+fB8/Ir73Gydp
+ovxT5p+VFbTrC2q5UeP0o+u8qZdNx+N9Ktltsjx8d7O7v3xzoOdg/Huw90H9utihi/vvl5Pmmld
rACkubsz2T3/dP/B7vbu5Hxne382y7azfHpvezp5uPdg73zn4f2HO3df1tVlMcvr5u4XxbSumuq8
HZ9Ui9W6ze8+V3yau4LN3ZfrSVk0c7Q+yZbVsphm5d3jui3Os2n75nqVN3d/8ouzRXaR3/3y/BzN
vpqsl+3693+9zFar69//pKrz3/9pNX2b13dfvyWAGMz+3Z+kltxNZ3QY3C/hIb43hQ72DsZ79/Y/
tV///4pCdnQY3C/5jZPv/z+2HDgHRwIAAA==
headers:
Cache-Control: [no-cache]
Content-Encoding: [gzip]
Content-Type: [application/json; charset=utf-8]
Date: ['Tue, 03 May 2016 03:52:47 GMT']
Expires: ['-1']
Pragma: [no-cache]
Server: [Microsoft-HTTPAPI/2.0, Microsoft-HTTPAPI/2.0]
Strict-Transport-Security: [max-age=31536000; includeSubDomains]
Vary: [Accept-Encoding]
status: {code: 200, message: OK}
version: 1

Просмотреть файл

@ -1,8 +1,8 @@
import os.path
import os.path
import unittest
import mock
from azure.cli.command_modules.vm.custom import read_images_from_aliases_doc
from azure.cli.command_modules.vm.custom import _load_images_from_aliases_doc
class TestVMImage(unittest.TestCase):
@mock.patch('azure.cli.command_modules.vm.custom.urlopen', autospec=True)
@ -17,14 +17,14 @@ class TestVMImage(unittest.TestCase):
mock_urlopen.return_value = mock_read
#action
images = read_images_from_aliases_doc()
images = _load_images_from_aliases_doc(None, None, None)
#assert
self.assertEqual(images['Windows']['Win2012Datacenter']['publisher'],
'MicrosoftWindowsServer')
self.assertEqual(images['Linux']['UbuntuLTS']['publisher'], 'Canonical')
self.assertEqual(images['Linux']['UbuntuLTS']['urn'],
'Canonical:UbuntuServer:14.04.4-LTS:latest')
win_images = [i for i in images if i['publisher'] == 'MicrosoftWindowsServer']
self.assertTrue(len(win_images) > 0)
ubuntu_image = next(i for i in images if i['publisher'] == 'Canonical')
self.assertEqual(ubuntu_image['publisher'], 'Canonical')
self.assertEqual(ubuntu_image['offer'], 'UbuntuServer')
if __name__ == '__main__':
unittest.main()