def body(self): s = self share1 = s.share1 share2 = s.share2 _get_connection_string(self) s.cmd('storage share create --name {} --fail-on-exist'.format(share1), checks=JMESPathCheck('success', True)) s.cmd( 'storage share create -n {} --fail-on-exist --metadata foo=bar cat=hat' .format(share2), checks=JMESPathCheck('success', True)) s.cmd('storage share exists -n {}'.format(share1), checks=JMESPathCheck('exists', True)) s.cmd( 'storage share metadata show --name {}'.format(share2), checks=[JMESPathCheck('cat', 'hat'), JMESPathCheck('foo', 'bar')]) res = [x['name'] for x in s.cmd('storage share list')] assert share1 in res assert share2 in res # verify metadata can be set, queried, and cleared s.cmd('storage share metadata update --name {} --metadata a=b c=d'. format(share1)) s.cmd('storage share metadata show -n {}'.format(share1), checks=[JMESPathCheck('a', 'b'), JMESPathCheck('c', 'd')]) s.cmd('storage share metadata update -n {}'.format(share1)) s.cmd('storage share metadata show -n {}'.format(share1), checks=NoneCheck()) s.cmd('storage share update --name {} --quota 3'.format(share1)) s.cmd('storage share show --name {}'.format(share1), checks=JMESPathCheck('properties.quota', 3)) self._storage_file_scenario(share1) self._storage_directory_scenario(share1)
def _storage_directory_scenario(self, share): s = self dir = 'testdir01' s.cmd('storage directory create --share-name {} --name {} --fail-on-exist'.format(share, dir), checks=JMESPathCheck('created', True)) s.cmd('storage directory list -s {}'.format(share), checks=JMESPathCheck('length(@)', 1)) s.cmd('storage directory exists --share-name {} -n {}'.format(share, dir), checks=JMESPathCheck('exists', True)) s.cmd('storage directory metadata update --share-name {} -n {} --metadata a=b c=d'.format(share, dir)) s.cmd('storage directory metadata show --share-name {} -n {}'.format(share, dir), checks=[ JMESPathCheck('a', 'b'), JMESPathCheck('c', 'd') ]) s.cmd('storage directory show --share-name {} -n {}'.format(share, dir), checks=[ JMESPathCheck('metadata', {'a': 'b', 'c': 'd'}), JMESPathCheck('name', dir) ]) s.cmd('storage directory metadata update --share-name {} --name {}'.format(share, dir)) s.cmd('storage directory metadata show --share-name {} --name {}'.format(share, dir), checks=NoneCheck()) s._storage_file_in_subdir_scenario(share, dir) s.cmd('storage directory delete --share-name {} --name {} --fail-not-exist'.format(share, dir), checks=JMESPathCheck('deleted', True)) s.cmd('storage directory exists --share-name {} --name {}'.format(share, dir), checks=JMESPathCheck('exists', False)) # verify a directory can be created with metadata and then delete dir = 'testdir02' s.cmd('storage directory create --share-name {} --name {} --fail-on-exist --metadata foo=bar cat=hat'.format(share, dir), checks=JMESPathCheck('created', True)) s.cmd('storage directory metadata show --share-name {} -n {}'.format(share, dir), checks=[ JMESPathCheck('cat', 'hat'), JMESPathCheck('foo', 'bar') ]) s.cmd('storage directory delete --share-name {} --name {} --fail-not-exist'.format(share, dir), checks=JMESPathCheck('deleted', True))
def body(self): if self.playback: subscription_id = MOCKED_SUBSCRIPTION_ID else: subscription_id = self.cmd( 'account list --query "[?isDefault].id" -o tsv') role_name = 'cli-test-role' template = { "Name": "Contoso On-call", "Description": "Can monitor compute, network and storage, and restart virtual machines", "Actions": [ "Microsoft.Compute/*/read", "Microsoft.Compute/virtualMachines/start/action", "Microsoft.Compute/virtualMachines/restart/action", "Microsoft.Network/*/read", "Microsoft.Storage/*/read", "Microsoft.Authorization/*/read", "Microsoft.Resources/subscriptions/resourceGroups/read", "Microsoft.Resources/subscriptions/resourceGroups/resources/read", "Microsoft.Insights/alertRules/*", "Microsoft.Support/*" ], "AssignableScopes": ["/subscriptions/{}".format(subscription_id)] } template['Name'] = role_name _, temp_file = tempfile.mkstemp() with open(temp_file, 'w') as f: json.dump(template, f) self.cmd( 'role create --role-definition {}'.format( temp_file.replace('\\', '\\\\')), None) self.cmd('role list -n {}'.format(role_name), checks=[JMESPathCheck('[0].properties.roleName', role_name)]) self.cmd('role delete -n {}'.format(role_name), None) self.cmd('role list -n {}'.format(role_name), NoneCheck())
def body(self): nsg_name = 'nsg1' self.cmd( 'network nsg create -n {} -g {}'.format(nsg_name, self.resource_group), None) result = self.cmd( 'network nsg show -n {} -g {}'.format(nsg_name, self.resource_group), None) resource_id = result['id'] #test role assignments on a resource group self.cmd( 'role assignment create --assignee {} --role contributor -g {}'. format(self.user, self.resource_group), None) self.cmd('role assignment list -g {}'.format(self.resource_group), checks=[JMESPathCheck("length([])", 1)]) self.cmd('role assignment list --assignee {} --role contributor -g {}'. format(self.user, self.resource_group), checks=[JMESPathCheck("length([])", 1)]) #test couple of more general filters result = self.cmd( 'role assignment list -g {} --include-inherited'.format( self.resource_group), None) self.assertTrue(len(result) >= 1) result = self.cmd( 'role assignment list --all'.format(self.user, self.resource_group), None) self.assertTrue(len(result) >= 1) self.cmd( 'role assignment delete --assignee {} --role contributor -g {}'. format(self.user, self.resource_group), None) self.cmd('role assignment list -g {}'.format(self.resource_group), checks=NoneCheck()) #test role assignments on a resource self.cmd( 'role assignment create --assignee {} --role contributor --scope {}' .format(self.user, resource_id), None) self.cmd( 'role assignment list --assignee {} --role contributor --scope {}'. format(self.user, resource_id), checks=[JMESPathCheck("length([])", 1)]) self.cmd( 'role assignment delete --assignee {} --role contributor --scope {}' .format(self.user, resource_id), None) self.cmd('role assignment list --scope {}'.format(resource_id), checks=NoneCheck()) #test role assignment on subscription level self.cmd( 'role assignment create --assignee {} --role reader'.format( self.user), None) self.cmd('role assignment list --assignee {} --role reader'.format( self.user), checks=[JMESPathCheck("length([])", 1)]) self.cmd('role assignment list --assignee {}'.format(self.user), checks=[JMESPathCheck("length([])", 1)]) self.cmd( 'role assignment delete --assignee {} --role reader'.format( self.user), None)
def body(self): _create_keyvault(self, self.keyvault_name, self.resource_group, self.location) kv = self.keyvault_name # create a secret secret = self.cmd( 'keyvault secret set --vault-name {} -n secret1 --value ABC123'. format(kv), checks=JMESPathCheck('value', 'ABC123')) first_kid = secret['id'] first_version = first_kid.rsplit('/', 1)[1] # list secrets self.cmd('keyvault secret list --vault-name {}'.format(kv), checks=JMESPathCheck('length(@)', 1)) # create a new secret version secret = self.cmd( 'keyvault secret set --vault-name {} -n secret1 --value DEF456 --tags test=foo --description "test type"' .format(kv), checks=[ JMESPathCheck('value', 'DEF456'), JMESPathCheck('tags', { 'file-encoding': 'utf-8', 'test': 'foo' }), JMESPathCheck('contentType', 'test type') ]) second_kid = secret['id'] # list secret versions self.cmd( 'keyvault secret list-versions --vault-name {} -n secret1'.format( kv), checks=JMESPathCheck('length(@)', 2)) # show secret (latest) self.cmd('keyvault secret show --vault-name {} -n secret1'.format(kv), checks=JMESPathCheck('id', second_kid)) # show secret (specific version) self.cmd( 'keyvault secret show --vault-name {} -n secret1 -v {}'.format( kv, first_version), checks=JMESPathCheck('id', first_kid)) # set secret attributes self.cmd( 'keyvault secret set-attributes --vault-name {} -n secret1 --enabled false' .format(kv), checks=[ JMESPathCheck('id', second_kid), JMESPathCheck('attributes.enabled', False) ]) # delete secret self.cmd( 'keyvault secret delete --vault-name {} -n secret1'.format(kv)) self.cmd('keyvault secret list --vault-name {}'.format(kv), checks=NoneCheck()) self._test_download_secret()
def _storage_file_scenario(self, share): source_file = os.path.join(TEST_DIR, 'testfile.rst') dest_file = os.path.join(TEST_DIR, 'download_test.rst') filename = 'testfile.rst' s = self s.cmd( 'storage file upload --share-name {} --source "{}" -p "{}"'.format( share, source_file, filename)) s.cmd('storage file exists --share-name {} -p "{}"'.format( share, filename), checks=JMESPathCheck('exists', True)) if os.path.isfile(dest_file): os.remove(dest_file) s.cmd( 'storage file download --share-name {} -p "{}" --dest "{}"'.format( share, filename, dest_file)) if os.path.isfile(dest_file): os.remove(dest_file) else: raise CLIError('\nDownload failed. Test failed!') # test resize command s.cmd('storage file resize --share-name {} -p "{}" --size 1234'.format( share, filename)) s.cmd('storage file show --share-name {} -p "{}"'.format( share, filename), checks=JMESPathCheck('properties.contentLength', 1234)) # test ability to set and reset metadata s.cmd( 'storage file metadata update --share-name {} -p "{}" --metadata a=b c=d' .format(share, filename)) s.cmd('storage file metadata show --share-name {} -p "{}"'.format( share, filename), checks=[JMESPathCheck('a', 'b'), JMESPathCheck('c', 'd')]) s.cmd('storage file metadata update --share-name {} -p "{}"'.format( share, filename)) s.cmd('storage file metadata show --share-name {} -p "{}"'.format( share, filename), checks=NoneCheck()) file_url = 'https://{}.file.core.windows.net/{}/{}'.format( s.account, share, filename) s.cmd('storage file url --share-name {} -p "{}"'.format( share, filename), checks=StringCheck(file_url)) for res in s.cmd('storage file list -s {}'.format(share)): assert filename in res['name'] sas = s.cmd('storage file generate-sas -s {} -p {}'.format( share, filename)) sas_keys = dict(pair.split('=') for pair in sas.split('&')) assert u'sig' in sas_keys s.cmd('storage file update -s {} -p {} --content-type "test/type"'. format(share, filename)) s.cmd('storage file show -s {} -p {}'.format(share, filename), checks=JMESPathCheck('properties.contentSettings.contentType', 'test/type')) s.cmd('storage file delete --share-name {} -p "{}"'.format( share, filename)) s.cmd('storage file exists --share-name {} -p "{}"'.format( share, filename), checks=JMESPathCheck('exists', False))
def _test_acr(self, registry_name, storage_account_for_update, storage_account_for_create=None): resource_group = self.resource_group location = self.location # test acr create self.cmd('acr check-name -n {}'.format(registry_name), checks=[JMESPathCheck('nameAvailable', True)]) if storage_account_for_create is None: self.cmd('acr create -n {} -g {} -l {}'.format( registry_name, resource_group, location), checks=[ JMESPathCheck('name', registry_name), JMESPathCheck('location', location), JMESPathCheck('adminUserEnabled', False) ]) else: self.cmd('acr create -n {} -g {} -l {} --storage-account-name {}'. format(registry_name, resource_group, location, storage_account_for_create), checks=[ JMESPathCheck('name', registry_name), JMESPathCheck('location', location), JMESPathCheck('adminUserEnabled', False), JMESPathCheck('storageAccount.name', storage_account_for_create) ]) self.cmd('acr check-name -n {}'.format(registry_name), checks=[ JMESPathCheck('nameAvailable', False), JMESPathCheck('reason', 'AlreadyExists') ]) self.cmd('acr list -g {}'.format(resource_group), checks=[ JMESPathCheck('[0].name', registry_name), JMESPathCheck('[0].location', location), JMESPathCheck('[0].adminUserEnabled', False) ]) self.cmd('acr show -n {} -g {}'.format(registry_name, resource_group), checks=[ JMESPathCheck('name', registry_name), JMESPathCheck('location', location), JMESPathCheck('adminUserEnabled', False) ]) # enable admin user self.cmd('acr update -n {} -g {} --admin-enabled true'.format( registry_name, resource_group), checks=[ JMESPathCheck('name', registry_name), JMESPathCheck('location', location), JMESPathCheck('adminUserEnabled', True) ]) # test credential module credential = self.cmd('acr credential show -n {} -g {}'.format( registry_name, resource_group)) username = credential['username'] password = credential['password'] assert username and password credential = self.cmd('acr credential renew -n {} -g {}'.format( registry_name, resource_group)) renewed_username = credential['username'] renewed_password = credential['password'] assert renewed_username and renewed_password assert username == renewed_username assert password != renewed_password # test repository module login_server = self.cmd('acr show -n {} -g {}'.format( registry_name, resource_group))['loginServer'] assert login_server self.cmd('acr repository list -n {}'.format(registry_name), checks=NoneCheck()) # test acr update self.cmd( 'acr update -n {} -g {} --tags foo=bar cat --admin-enabled false --storage-account-name {}' .format(registry_name, resource_group, storage_account_for_update), checks=[ JMESPathCheck('name', registry_name), JMESPathCheck('location', location), JMESPathCheck('tags', { 'cat': '', 'foo': 'bar' }), JMESPathCheck('adminUserEnabled', False), JMESPathCheck('storageAccount.name', storage_account_for_update) ]) # test acr delete self.cmd('acr delete -n {} -g {}'.format(registry_name, resource_group))
def body(self): rg = self.resource_group loc = self.location user = self.admin_login password = self.admin_password firewall_rule_1 = 'rule1' start_ip_address_1 = '0.0.0.0' end_ip_address_1 = '255.255.255.255' firewall_rule_2 = 'rule2' start_ip_address_2 = '123.123.123.123' end_ip_address_2 = '123.123.123.124' # allow_all_azure_ips_rule = 'AllowAllAzureIPs' # allow_all_azure_ips_address = '0.0.0.0' # test create sql server with minimal required parameters self.cmd('sql server create -g {} --name {} -l {} ' '--admin-user {} --admin-password {}'.format( rg, self.sql_server_name, loc, user, password), checks=[ JMESPathCheck('name', self.sql_server_name), JMESPathCheck('resourceGroup', rg), JMESPathCheck('administratorLogin', user) ]) # test sql server firewall-rule create self.cmd('sql server firewall-rule create --name {} -g {} --server {} ' '--start-ip-address {} --end-ip-address {}'.format( firewall_rule_1, rg, self.sql_server_name, start_ip_address_1, end_ip_address_1), checks=[ JMESPathCheck('name', firewall_rule_1), JMESPathCheck('resourceGroup', rg), JMESPathCheck('startIpAddress', start_ip_address_1), JMESPathCheck('endIpAddress', end_ip_address_1) ]) # test sql server firewall-rule show self.cmd( 'sql server firewall-rule show --name {} -g {} --server {}'.format( firewall_rule_1, rg, self.sql_server_name), checks=[ JMESPathCheck('name', firewall_rule_1), JMESPathCheck('resourceGroup', rg), JMESPathCheck('startIpAddress', start_ip_address_1), JMESPathCheck('endIpAddress', end_ip_address_1) ]) # test sql server firewall-rule update self.cmd('sql server firewall-rule update --name {} -g {} --server {} ' '--start-ip-address {} --end-ip-address {}'.format( firewall_rule_1, rg, self.sql_server_name, start_ip_address_2, end_ip_address_2), checks=[ JMESPathCheck('name', firewall_rule_1), JMESPathCheck('resourceGroup', rg), JMESPathCheck('startIpAddress', start_ip_address_2), JMESPathCheck('endIpAddress', end_ip_address_2) ]) self.cmd('sql server firewall-rule update --name {} -g {} --server {} ' '--start-ip-address {}'.format(firewall_rule_1, rg, self.sql_server_name, start_ip_address_1), checks=[ JMESPathCheck('name', firewall_rule_1), JMESPathCheck('resourceGroup', rg), JMESPathCheck('startIpAddress', start_ip_address_1), JMESPathCheck('endIpAddress', end_ip_address_2) ]) self.cmd('sql server firewall-rule update --name {} -g {} --server {} ' '--end-ip-address {}'.format(firewall_rule_1, rg, self.sql_server_name, end_ip_address_1), checks=[ JMESPathCheck('name', firewall_rule_1), JMESPathCheck('resourceGroup', rg), JMESPathCheck('startIpAddress', start_ip_address_1), JMESPathCheck('endIpAddress', end_ip_address_1) ]) # test sql server firewall-rule create another rule self.cmd('sql server firewall-rule create --name {} -g {} --server {} ' '--start-ip-address {} --end-ip-address {}'.format( firewall_rule_2, rg, self.sql_server_name, start_ip_address_2, end_ip_address_2), checks=[ JMESPathCheck('name', firewall_rule_2), JMESPathCheck('resourceGroup', rg), JMESPathCheck('startIpAddress', start_ip_address_2), JMESPathCheck('endIpAddress', end_ip_address_2) ]) # test sql server firewall-rule list self.cmd('sql server firewall-rule list -g {} --server {}'.format( rg, self.sql_server_name), checks=[JMESPathCheck('length(@)', 2)]) # # test sql server firewall-rule create azure ip rule # self.cmd('sql server firewall-rule allow-all-azure-ips -g {} --server {} ' # .format(rg, self.sql_server_name), checks=[ # JMESPathCheck('name', allow_all_azure_ips_rule), # JMESPathCheck('resourceGroup', rg), # JMESPathCheck('startIpAddress', allow_all_azure_ips_address), # JMESPathCheck('endIpAddress', allow_all_azure_ips_address)]) # # test sql server firewall-rule list # self.cmd('sql server firewall-rule list -g {} --server {}' # .format(rg, self.sql_server_name), checks=[JMESPathCheck('length(@)', 3)]) # # test sql server firewall-rule delete # self.cmd('sql server firewall-rule delete --name {} -g {} --server {}' # .format(allow_all_azure_ips_rule, rg, self.sql_server_name), checks=NoneCheck()) # self.cmd('sql server firewall-rule list -g {} --server {}' # .format(rg, self.sql_server_name), checks=[JMESPathCheck('length(@)', 2)]) self.cmd('sql server firewall-rule delete --name {} -g {} --server {}'. format(firewall_rule_1, rg, self.sql_server_name), checks=NoneCheck()) self.cmd('sql server firewall-rule list -g {} --server {}'.format( rg, self.sql_server_name), checks=[JMESPathCheck('length(@)', 1)]) self.cmd('sql server firewall-rule delete --name {} -g {} --server {}'. format(firewall_rule_2, rg, self.sql_server_name), checks=NoneCheck()) self.cmd('sql server firewall-rule list -g {} --server {}'.format( rg, self.sql_server_name), checks=[JMESPathCheck('length(@)', 0)]) # test delete sql server self.cmd('sql server delete -g {} --name {}'.format( rg, self.sql_server_name), checks=NoneCheck())
def body(self): rg = self.resource_group loc_short = self.location_short_name loc_long = self.location_long_name user = self.admin_login password = self.admin_password # create sql server with minimal required parameters self.cmd('sql server create -g {} --name {} -l "{}" ' '--admin-user {} --admin-password {}'.format( rg, self.sql_server_name, loc_short, user, password), checks=[ JMESPathCheck('name', self.sql_server_name), JMESPathCheck('resourceGroup', rg), JMESPathCheck('location', loc_long), JMESPathCheck('administratorLogin', user) ]) # test sql db commands self.cmd('sql db create -g {} --server {} --name {}'.format( rg, self.sql_server_name, self.database_name), checks=[ JMESPathCheck('resourceGroup', rg), JMESPathCheck('name', self.database_name), JMESPathCheck('location', loc_long), JMESPathCheck('elasticPoolName', None), JMESPathCheck('status', 'Online') ]) self.cmd('sql db list -g {} --server {}'.format( rg, self.sql_server_name), checks=[ JMESPathCheck('length(@)', 2), JMESPathCheck('[1].name', 'master'), JMESPathCheck('[1].resourceGroup', rg), JMESPathCheck('[0].name', self.database_name), JMESPathCheck('[0].resourceGroup', rg) ]) self.cmd('sql db show -g {} --server {} --name {}'.format( rg, self.sql_server_name, self.database_name), checks=[ JMESPathCheck('name', self.database_name), JMESPathCheck('resourceGroup', rg) ]) # # Usages will not be included in the first batch of GA commands # self.cmd('sql db show-usage -g {} --server {} --name {}' # .format(rg, self.sql_server_name, self.database_name), checks=[ # JMESPathCheck('[0].resourceName', self.database_name)]) self.cmd( 'sql db update -g {} -s {} -n {} --service-objective {} --max-size {}' ' --set tags.key1=value1'.format(rg, self.sql_server_name, self.database_name, self.update_service_objective, self.update_storage), checks=[ JMESPathCheck('resourceGroup', rg), JMESPathCheck('name', self.database_name), JMESPathCheck('requestedServiceObjectiveName', self.update_service_objective), JMESPathCheck('maxSizeBytes', self.update_storage_bytes), JMESPathCheck('tags.key1', 'value1') ]) self.cmd('sql db copy -g {} --server {} --name {} ' '--dest-name {}'.format(rg, self.sql_server_name, self.database_name, self.database_copy_name), checks=[ JMESPathCheck('resourceGroup', rg), JMESPathCheck('name', self.database_copy_name) ]) self.cmd('sql db delete -g {} --server {} --name {}'.format( rg, self.sql_server_name, self.database_name), checks=[NoneCheck()]) # delete sql server self.cmd('sql server delete -g {} --name {}'.format( rg, self.sql_server_name), checks=NoneCheck())
def body(self): rg = self.resource_group loc = self.location user = self.administrator_login password = self.administrator_login_password # create sql server with minimal required parameters self.cmd('sql server create -g {} --name {} -l {} ' '--administrator-login {} --administrator-login-password {}' .format(rg, self.sql_server_name, loc, user, password), checks=[ JMESPathCheck('name', self.sql_server_name), JMESPathCheck('resourceGroup', rg), JMESPathCheck('administratorLogin', user)]) # test sql elastic-pools commands self.cmd('sql elastic-pools create -g {} --server-name {} -l {} --name {}' .format(rg, self.sql_server_name, loc, self.pool_name), checks=[ JMESPathCheck('resourceGroup', rg), JMESPathCheck('name', self.pool_name), JMESPathCheck('state', 'Ready')]) self.cmd('sql elastic-pools show -g {} --server-name {} --name {}' .format(rg, self.sql_server_name, self.pool_name), checks=[ JMESPathCheck('resourceGroup', rg), JMESPathCheck('name', self.pool_name), JMESPathCheck('state', 'Ready')]) self.cmd('sql elastic-pools list -g {} --server-name {}' .format(rg, self.sql_server_name), checks=[ JMESPathCheck('[0].resourceGroup', rg), JMESPathCheck('[0].name', self.pool_name), JMESPathCheck('[0].state', 'Ready')]) self.cmd('sql elastic-pools update -g {} --server-name {} --name {} ' '--set tags.key1=value1' .format(rg, self.sql_server_name, self.pool_name), checks=[ JMESPathCheck('resourceGroup', rg), JMESPathCheck('name', self.pool_name), JMESPathCheck('state', 'Ready'), JMESPathCheck('tags.key1', 'value1')]) self.cmd('sql elastic-pools update -g {} --server-name {} --name {} ' '--remove tags.key1' .format(rg, self.sql_server_name, self.pool_name), checks=[ JMESPathCheck('resourceGroup', rg), JMESPathCheck('name', self.pool_name), JMESPathCheck('state', 'Ready'), JMESPathCheck('tags', {})]) # Create a database in an Azure sql elastic pool self.cmd('sql db create -g {} --server-name {} -l {} --name {} ' '--elastic-pool-name {}' .format(rg, self.sql_server_name, loc, self.database_name, self.pool_name), checks=[ JMESPathCheck('resourceGroup', rg), JMESPathCheck('name', self.database_name), JMESPathCheck('elasticPoolName', self.pool_name), JMESPathCheck('status', 'Online')]) # test sql elastic-pools db sub-group commands self.cmd('sql elastic-pools db list -g {} --server-name {} --elastic-pool-name {}' .format(rg, self.sql_server_name, self.pool_name), checks=[ JMESPathCheck('length(@)', 1), JMESPathCheck('[0].resourceGroup', rg), JMESPathCheck('[0].name', self.database_name), JMESPathCheck('[0].elasticPoolName', self.pool_name), JMESPathCheck('[0].status', 'Online')]) self.cmd('sql elastic-pools db show -g {} --server-name {} --elastic-pool-name {} ' '--name {}' .format(rg, self.sql_server_name, self.pool_name, self.database_name), checks=[ JMESPathCheck('resourceGroup', rg), JMESPathCheck('name', self.database_name), JMESPathCheck('elasticPoolName', self.pool_name), JMESPathCheck('status', 'Online')]) activities = self.cmd('sql elastic-pools db show-activity -g {} ' '--server-name {} --elastic-pool-name {}' .format(rg, self.sql_server_name, self.pool_name), checks=[JMESPathCheck('type(@)', 'array')]) self.verify_activities(activities) # delete sql server database self.cmd('sql db delete -g {} --server-name {} --name {}' .format(rg, self.sql_server_name, self.database_name), checks=[NoneCheck()]) # delete sql elastic pool self.cmd('sql elastic-pools delete -g {} --server-name {} --name {}' .format(rg, self.sql_server_name, self.pool_name), checks=[NoneCheck()]) # delete sql server self.cmd('sql server delete -g {} --name {}' .format(rg, self.sql_server_name), checks=NoneCheck())
def body(self): plan_result = self.cmd( 'appservice plan create -g {} -n {} --sku S1'.format( self.resource_group, self.plan)) self.cmd('appservice web create -g {} -n {} --plan {} -l {}'.format( self.resource_group, self.webapp, plan_result['id'], self.location)) # You can create and use any repros with the 3 files under "./sample_web" and with a 'staging 'branch slot = 'staging' slot2 = 'dev' test_git_repo = 'https://github.com/yugangw-msft/azure-site-test' # create a few app-settings to test they can be cloned self.cmd( 'appservice web config appsettings update -g {} -n {} --settings s1=v1 --slot-settings s2=v2' .format(self.resource_group, self.webapp)) # create an empty slot self.cmd('appservice web deployment slot create -g {} -n {} --slot {}'. format(self.resource_group, self.webapp, slot), checks=[JMESPathCheck('name', slot)]) self.cmd( 'appservice web source-control config -g {} -n {} --repo-url {} --branch {} -s {} --manual-integration' .format(self.resource_group, self.webapp, test_git_repo, slot, slot), checks=[ JMESPathCheck('repoUrl', test_git_repo), JMESPathCheck('branch', slot) ]) import time import requests ''' #verify the slot wires up the git repo/branch time.sleep(30) # 30 seconds should be enough for the deployment finished(Skipped under playback mode) r = requests.get('http://{}-{}.azurewebsites.net'.format(self.webapp, slot)) self.assertTrue('Staging' in str(r.content)) ''' # swap with prod and verify the git branch also switched self.cmd( 'appservice web deployment slot swap -g {} -n {} -s {}'.format( self.resource_group, self.webapp, slot)) time.sleep( 30 ) # 30 seconds should be enough for the slot swap finished(Skipped under playback mode) r = requests.get('http://{}.azurewebsites.net'.format(self.webapp)) self.assertTrue('Staging' in str(r.content)) result = self.cmd( 'appservice web config appsettings show -g {} -n {} -s {}'.format( self.resource_group, self.webapp, slot)) self.assertEqual(set([x['name'] for x in result]), set(['WEBSITE_NODE_DEFAULT_VERSION', 's1'])) # create a new slot by cloning from prod slot self.cmd( 'appservice web deployment slot create -g {} -n {} --slot {} --configuration-source {}' .format(self.resource_group, self.webapp, slot2, self.webapp)) self.cmd( 'appservice web config appsettings show -g {} -n {} --slot {}'. format(self.resource_group, self.webapp, slot2), checks=[ JMESPathCheck("length([])", 1), JMESPathCheck('[0].name', 'WEBSITE_NODE_DEFAULT_VERSION') ]) self.cmd( 'appservice web config appsettings update -g {} -n {} --slot {} --settings s3=v3 --slot-settings s4=v4' .format(self.resource_group, self.webapp, slot2)) # verify we can swap with non production slot self.cmd( 'appservice web deployment slot swap -g {} -n {} --slot {} --target-slot {}' .format(self.resource_group, self.webapp, slot, slot2), checks=NoneCheck()) result = self.cmd( 'appservice web config appsettings show -g {} -n {} --slot {}'. format(self.resource_group, self.webapp, slot2)) self.assertEqual(set([x['name'] for x in result]), set(['WEBSITE_NODE_DEFAULT_VERSION', 's1', 's4'])) result = self.cmd( 'appservice web config appsettings show -g {} -n {} --slot {}'. format(self.resource_group, self.webapp, slot)) self.assertEqual(set([x['name'] for x in result]), set(['WEBSITE_NODE_DEFAULT_VERSION', 's3'])) self.cmd('appservice web deployment slot list -g {} -n {}'.format( self.resource_group, self.webapp), checks=[ JMESPathCheck("length([])", 2), JMESPathCheck('[0].name', slot2), JMESPathCheck('[1].name', slot), ]) self.cmd('appservice web deployment slot delete -g {} -n {} --slot {}'. format(self.resource_group, self.webapp, slot), checks=NoneCheck())
def body(self): rg = self.resource_group linux_vm_name = 'ubuntuvm5367' linux_image = 'Ubuntu\ Server\ 16.04\ LTS' windows_vm_name = 'winvm5367' windows_image = 'Windows\ Server\ 2008\ R2\ SP1' image_type = 'gallery' size = 'Standard_DS1_v2' password = '******' self.cmd('group deployment create -g {} --template-file {}'.format( rg, TEMPLATE), checks=[ JMESPathCheck('properties.provisioningState', 'Succeeded') ]) # Create linux vm in the lab self.cmd( 'lab vm create -g {} --lab-name {} --name {} ' '--image {} --image-type {} --size {} --admin-password {}'.format( rg, LAB_NAME, linux_vm_name, linux_image, image_type, size, password), checks=[NoneCheck()]) self.cmd('lab vm show -g {} --lab-name {} --name {} '.format( rg, LAB_NAME, linux_vm_name), checks=[ JMESPathCheck('name', linux_vm_name), JMESPathCheck('provisioningState', 'Succeeded'), JMESPathCheck('osType', 'Linux'), JMESPathCheck('virtualMachineCreationSource', 'FromGalleryImage'), JMESPathCheck('size', size), JMESPathCheck('disallowPublicIpAddress', True), JMESPathCheck('artifactDeploymentStatus.totalArtifacts', 0), JMESPathCheck('galleryImageReference.publisher', 'Canonical') ]) # Create windows vm in the lab self.cmd( 'lab vm create -g {} --lab-name {} --name {} ' '--image {} --image-type {} --size {} --admin-password {}'.format( rg, LAB_NAME, windows_vm_name, windows_image, image_type, size, password), checks=[NoneCheck()]) self.cmd('lab vm show -g {} --lab-name {} --name {} '.format( rg, LAB_NAME, windows_vm_name), checks=[ JMESPathCheck('name', windows_vm_name), JMESPathCheck('provisioningState', 'Succeeded'), JMESPathCheck('osType', 'Windows'), JMESPathCheck('virtualMachineCreationSource', 'FromGalleryImage'), JMESPathCheck('size', size), JMESPathCheck('disallowPublicIpAddress', True), JMESPathCheck('artifactDeploymentStatus.totalArtifacts', 0), JMESPathCheck('galleryImageReference.publisher', 'MicrosoftWindowsServer') ]) # Delete all the vms self.cmd('lab vm delete -g {} --lab-name {} --name {}'.format( rg, LAB_NAME, linux_vm_name), checks=[NoneCheck()]) self.cmd('lab vm delete -g {} --lab-name {} --name {}'.format( rg, LAB_NAME, windows_vm_name), checks=[NoneCheck()]) # Delete the lab self.cmd('lab delete -g {} --name {}'.format(rg, LAB_NAME), checks=[NoneCheck()])
def body(self): plan = 'webapp-linux-plan' webapp = 'webapp-linux1' self.cmd('appservice plan create -g {} -n {} --sku S1 --is-linux' .format(self.resource_group, plan), checks=[ JMESPathCheck('reserved', True), # this weird field means it is a linux JMESPathCheck('sku.name', 'S1'), ]) self.cmd('appservice web create -g {} -n {} --plan {}'.format(self.resource_group, webapp, plan), checks=[ JMESPathCheck('name', webapp), ]) self.cmd('appservice web config update -g {} -n {} --startup-file {}'.format(self.resource_group, webapp, 'process.json'), checks=[ JMESPathCheck('appCommandLine', 'process.json') ]) self.cmd('appservice web config container update -g {} -n {} --docker-custom-image-name {} --docker-registry-server-password {} --docker-registry-server-user {} --docker-registry-server-url {}'.format( self.resource_group, webapp, 'foo-image', 'foo-password', 'foo-user', 'foo-url')) result = self.cmd('appservice web config container show -g {} -n {} '.format(self.resource_group, webapp)) self.assertEqual(set(x['name'] for x in result), set(['DOCKER_REGISTRY_SERVER_URL', 'DOCKER_REGISTRY_SERVER_USERNAME', 'DOCKER_CUSTOM_IMAGE_NAME', 'DOCKER_REGISTRY_SERVER_PASSWORD'])) sample = next((x for x in result if x['name'] == 'DOCKER_REGISTRY_SERVER_URL')) self.assertEqual(sample, {'name': 'DOCKER_REGISTRY_SERVER_URL', 'slotSetting': 'False', 'value': 'foo-url'}) self.cmd('appservice web config container delete -g {} -n {}'.format(self.resource_group, webapp)) result2 = self.cmd('appservice web config container show -g {} -n {} '.format(self.resource_group, webapp), checks=NoneCheck()) self.assertEqual(result2, [])
def body(self): rg = self.resource_group loc_short = self.location_short_name loc_long = self.location_long_name user = self.admin_login password = self.admin_password # create sql server with minimal required parameters self.cmd('sql server create -g {} --name {} -l {} ' '--admin-user {} --admin-password {}'.format( rg, self.sql_server_name, loc_short, user, password), checks=[ JMESPathCheck('name', self.sql_server_name), JMESPathCheck('resourceGroup', rg), JMESPathCheck('location', loc_long), JMESPathCheck('administratorLogin', user) ]) # test sql elastic-pool commands self.cmd('sql elastic-pool create -g {} --server {} --name {} ' '--dtu {} --edition {} --db-dtu-min {} --db-dtu-max {} ' '--storage {}'.format(rg, self.sql_server_name, self.pool_name, self.dtu, self.edition, self.db_dtu_min, self.db_dtu_max, self.storage), checks=[ JMESPathCheck('resourceGroup', rg), JMESPathCheck('name', self.pool_name), JMESPathCheck('location', loc_long), JMESPathCheck('state', 'Ready'), JMESPathCheck('dtu', self.dtu), JMESPathCheck('databaseDtuMin', self.db_dtu_min), JMESPathCheck('databaseDtuMax', self.db_dtu_max), JMESPathCheck('edition', self.edition), JMESPathCheck('storageMb', self.storage_mb) ]) self.cmd('sql elastic-pool show -g {} --server {} --name {}'.format( rg, self.sql_server_name, self.pool_name), checks=[ JMESPathCheck('resourceGroup', rg), JMESPathCheck('name', self.pool_name), JMESPathCheck('state', 'Ready'), JMESPathCheck('databaseDtuMin', self.db_dtu_min), JMESPathCheck('databaseDtuMax', self.db_dtu_max), JMESPathCheck('edition', self.edition), JMESPathCheck('storageMb', self.storage_mb) ]) self.cmd('sql elastic-pool list -g {} --server {}'.format( rg, self.sql_server_name), checks=[ JMESPathCheck('[0].resourceGroup', rg), JMESPathCheck('[0].name', self.pool_name), JMESPathCheck('[0].state', 'Ready'), JMESPathCheck('[0].databaseDtuMin', self.db_dtu_min), JMESPathCheck('[0].databaseDtuMax', self.db_dtu_max), JMESPathCheck('[0].edition', self.edition), JMESPathCheck('[0].storageMb', self.storage_mb) ]) self.cmd('sql elastic-pool update -g {} --server {} --name {} ' '--dtu {} --storage {} --set tags.key1=value1'.format( rg, self.sql_server_name, self.pool_name, self.updated_dtu, self.updated_storage), checks=[ JMESPathCheck('resourceGroup', rg), JMESPathCheck('name', self.pool_name), JMESPathCheck('state', 'Ready'), JMESPathCheck('dtu', self.updated_dtu), JMESPathCheck('edition', self.edition), JMESPathCheck('databaseDtuMin', self.db_dtu_min), JMESPathCheck('databaseDtuMax', self.db_dtu_max), JMESPathCheck('storageMb', self.updated_storage_mb), JMESPathCheck('tags.key1', 'value1') ]) self.cmd( 'sql elastic-pool update -g {} --server {} --name {} ' '--dtu {} --db-dtu-min {} --db-dtu-max {} --storage {}'.format( rg, self.sql_server_name, self.pool_name, self.dtu, self.updated_db_dtu_min, self.updated_db_dtu_max, self.storage), checks=[ JMESPathCheck('resourceGroup', rg), JMESPathCheck('name', self.pool_name), JMESPathCheck('state', 'Ready'), JMESPathCheck('dtu', self.dtu), JMESPathCheck('databaseDtuMin', self.updated_db_dtu_min), JMESPathCheck('databaseDtuMax', self.updated_db_dtu_max), JMESPathCheck('storageMb', self.storage_mb), JMESPathCheck('tags.key1', 'value1') ]) self.cmd('sql elastic-pool update -g {} --server {} --name {} ' '--remove tags.key1'.format(rg, self.sql_server_name, self.pool_name), checks=[ JMESPathCheck('resourceGroup', rg), JMESPathCheck('name', self.pool_name), JMESPathCheck('state', 'Ready'), JMESPathCheck('tags', {}) ]) # create a second pool with minimal params self.cmd('sql elastic-pool create -g {} --server {} --name {} '.format( rg, self.sql_server_name, self.pool_name2), checks=[ JMESPathCheck('resourceGroup', rg), JMESPathCheck('name', self.pool_name2), JMESPathCheck('location', loc_long), JMESPathCheck('state', 'Ready') ]) self.cmd('sql elastic-pool list -g {} -s {}'.format( rg, self.sql_server_name), checks=[JMESPathCheck('length(@)', 2)]) # Create a database directly in an Azure sql elastic pool self.cmd('sql db create -g {} --server {} --name {} ' '--elastic-pool {}'.format(rg, self.sql_server_name, self.database_name, self.pool_name), checks=[ JMESPathCheck('resourceGroup', rg), JMESPathCheck('name', self.database_name), JMESPathCheck('elasticPoolName', self.pool_name), JMESPathCheck('requestedServiceObjectiveName', 'ElasticPool'), JMESPathCheck('status', 'Online') ]) # Move database to second pool. Specify service objective just for fun self.cmd('sql db update -g {} -s {} -n {} --elastic-pool {}' ' --service-objective ElasticPool'.format( rg, self.sql_server_name, self.database_name, self.pool_name2), checks=[ JMESPathCheck('resourceGroup', rg), JMESPathCheck('name', self.database_name), JMESPathCheck('elasticPoolName', self.pool_name2), JMESPathCheck('requestedServiceObjectiveName', 'ElasticPool'), JMESPathCheck('status', 'Online') ]) # Remove database from pool self.cmd( 'sql db update -g {} -s {} -n {} --service-objective {}'.format( rg, self.sql_server_name, self.database_name, self.db_service_objective), checks=[ JMESPathCheck('resourceGroup', rg), JMESPathCheck('name', self.database_name), JMESPathCheck('elasticPoolName', None), JMESPathCheck('requestedServiceObjectiveName', self.db_service_objective), JMESPathCheck('status', 'Online') ]) # Move database back into pool self.cmd('sql db update -g {} -s {} -n {} --elastic-pool {}' ' --service-objective ElasticPool'.format( rg, self.sql_server_name, self.database_name, self.pool_name), checks=[ JMESPathCheck('resourceGroup', rg), JMESPathCheck('name', self.database_name), JMESPathCheck('elasticPoolName', self.pool_name), JMESPathCheck('requestedServiceObjectiveName', 'ElasticPool'), JMESPathCheck('status', 'Online') ]) # List databases in a pool self.cmd('sql elastic-pool list-dbs -g {} -s {} -n {}'.format( rg, self.sql_server_name, self.pool_name), checks=[ JMESPathCheck('length(@)', 1), JMESPathCheck('[0].resourceGroup', rg), JMESPathCheck('[0].name', self.database_name), JMESPathCheck('[0].elasticPoolName', self.pool_name) ]) # List databases in a pool - alternative command self.cmd('sql db list -g {} -s {} --elastic-pool {}'.format( rg, self.sql_server_name, self.pool_name), checks=[ JMESPathCheck('length(@)', 1), JMESPathCheck('[0].resourceGroup', rg), JMESPathCheck('[0].name', self.database_name), JMESPathCheck('[0].elasticPoolName', self.pool_name) ]) # self.cmd('sql elastic-pool db show-activity -g {} --server {} --elastic-pool {}' # .format(rg, self.sql_server_name, self.pool_name), # checks=[ # JMESPathCheck('length(@)', 1), # JMESPathCheck('[0].resourceGroup', rg), # JMESPathCheck('[0].serverName', self.sql_server_name), # JMESPathCheck('[0].currentElasticPoolName', self.pool_name)]) # activities = self.cmd('sql elastic-pools db show-activity -g {} ' # '--server-name {} --elastic-pool-name {}' # .format(rg, self.sql_server_name, self.pool_name), # checks=[JMESPathCheck('type(@)', 'array')]) # self.verify_activities(activities) # delete sql server database self.cmd('sql db delete -g {} --server {} --name {}'.format( rg, self.sql_server_name, self.database_name), checks=[NoneCheck()]) # delete sql elastic pool self.cmd('sql elastic-pool delete -g {} --server {} --name {}'.format( rg, self.sql_server_name, self.pool_name), checks=[NoneCheck()]) # delete sql server self.cmd('sql server delete -g {} --name {}'.format( rg, self.sql_server_name), checks=NoneCheck())
def body(self): rg = self.resource_group loc_short = self.location_short_name loc_long = self.location_long_name user = self.admin_login password = self.admin_password # create sql server with minimal required parameters self.cmd('sql server create -g {} --name {} -l "{}" ' '--admin-user {} --admin-password {}'.format( rg, self.sql_server_name, loc_short, user, password), checks=[ JMESPathCheck('name', self.sql_server_name), JMESPathCheck('resourceGroup', rg), JMESPathCheck('location', loc_long), JMESPathCheck('administratorLogin', user) ]) # test sql db commands self.cmd('sql dw create -g {} --server {} --name {}'.format( rg, self.sql_server_name, self.database_name), checks=[ JMESPathCheck('resourceGroup', rg), JMESPathCheck('name', self.database_name), JMESPathCheck('location', loc_long), JMESPathCheck('edition', 'DataWarehouse'), JMESPathCheck('maxSizeBytes', self.storage_bytes), JMESPathCheck('status', 'Online') ]) # DataWarehouse is a little quirky and is considered to be both a database and its # separate own type of thing. (Why? Because it has the same REST endpoint as regular # database, so it must be a database. However it has only a subset of supported operations, # so to clarify which operations are supported by dw we group them under `sql dw`.) So the # dw shows up under both `db list` and `dw list`. self.cmd( 'sql db list -g {} --server {}'.format(rg, self.sql_server_name), checks=[ JMESPathCheck('length(@)', 2), # includes dw and master JMESPathCheck('[1].name', 'master'), JMESPathCheck('[1].resourceGroup', rg), JMESPathCheck('[0].name', self.database_name), JMESPathCheck('[0].resourceGroup', rg) ]) self.cmd('sql dw list -g {} --server {}'.format( rg, self.sql_server_name), checks=[ JMESPathCheck('length(@)', 1), JMESPathCheck('[0].name', self.database_name), JMESPathCheck('[0].resourceGroup', rg) ]) self.cmd('sql db show -g {} --server {} --name {}'.format( rg, self.sql_server_name, self.database_name), checks=[ JMESPathCheck('name', self.database_name), JMESPathCheck('resourceGroup', rg) ]) self.cmd('sql dw show -g {} --server {} --name {}'.format( rg, self.sql_server_name, self.database_name), checks=[ JMESPathCheck('name', self.database_name), JMESPathCheck('resourceGroup', rg) ]) # pause/resume self.cmd('sql dw pause -g {} --server {} --name {}'.format( rg, self.sql_server_name, self.database_name), checks=[NoneCheck()]) self.cmd('sql dw show -g {} --server {} --name {}'.format( rg, self.sql_server_name, self.database_name), checks=[ JMESPathCheck('name', self.database_name), JMESPathCheck('resourceGroup', rg), JMESPathCheck('status', 'Paused') ]) self.cmd('sql dw resume -g {} --server {} --name {}'.format( rg, self.sql_server_name, self.database_name), checks=[NoneCheck()]) self.cmd('sql dw show -g {} --server {} --name {}'.format( rg, self.sql_server_name, self.database_name), checks=[ JMESPathCheck('name', self.database_name), JMESPathCheck('resourceGroup', rg), JMESPathCheck('status', 'Online') ]) # Update DW storage self.cmd('sql dw update -g {} -s {} -n {} --max-size {}' ' --set tags.key1=value1'.format(rg, self.sql_server_name, self.database_name, self.update_storage), checks=[ JMESPathCheck('resourceGroup', rg), JMESPathCheck('name', self.database_name), JMESPathCheck('maxSizeBytes', self.update_storage_bytes), JMESPathCheck('tags.key1', 'value1') ]) # Update DW service objective self.cmd( 'sql dw update -g {} -s {} -n {} --service-objective {}'.format( rg, self.sql_server_name, self.database_name, self.update_service_objective), checks=[ JMESPathCheck('resourceGroup', rg), JMESPathCheck('name', self.database_name), JMESPathCheck('requestedServiceObjectiveName', self.update_service_objective), JMESPathCheck('maxSizeBytes', self.update_storage_bytes), JMESPathCheck('tags.key1', 'value1') ]) # Delete DW self.cmd('sql dw delete -g {} --server {} --name {}'.format( rg, self.sql_server_name, self.database_name), checks=[NoneCheck()]) # delete sql server self.cmd('sql server delete -g {} --name {}'.format( rg, self.sql_server_name), checks=NoneCheck())
def body(self): from datetime import datetime from time import sleep rg = self.resource_group server_name = 'cliautomation44' location = 'westus' admin_login = '******' admin_password = '******' database_name = 'cliautomationdb01' # Standalone db restore_service_objective = 'S1' restore_edition = 'Standard' restore_standalone_database_name = 'cliautomationdb01restore1' restore_pool_database_name = 'cliautomationdb01restore2' elastic_pool = 'cliautomationpool1' # create server self.cmd('sql server create -g {} --name {} -l "{}" ' '--admin-user {} --admin-password {}'.format( rg, server_name, location, admin_login, admin_password), checks=[ JMESPathCheck('name', server_name), JMESPathCheck('resourceGroup', rg) ]) # create db db = self.cmd('sql db create -g {} --server {} --name {}'.format( rg, server_name, database_name), checks=[ JMESPathCheck('resourceGroup', rg), JMESPathCheck('name', database_name), JMESPathCheck('status', 'Online') ]) # create elastic pool self.cmd('sql elastic-pool create -g {} -s {} -n {}'.format( rg, server_name, elastic_pool)) # Wait until earliestRestoreDate is in the past. When run live, this will take at least # 10 minutes. Unforunately there's no way to speed this up. earliest_restore_date = datetime.strptime( db['earliestRestoreDate'], "%Y-%m-%dT%H:%M:%S.%f+00:00") while datetime.utcnow() <= earliest_restore_date: sleep(10) # seconds # Restore to standalone db db = self.cmd('sql db restore -g {} -s {} -n {} -t {} --dest-name {}' ' --service-objective {} --edition {}'.format( rg, server_name, database_name, datetime.utcnow().isoformat(), restore_standalone_database_name, restore_service_objective, restore_edition), checks=[ JMESPathCheck('resourceGroup', rg), JMESPathCheck('name', restore_standalone_database_name), JMESPathCheck('requestedServiceObjectiveName', restore_service_objective), JMESPathCheck('status', 'Online') ]) # Restore to db into pool db = self.cmd('sql db restore -g {} -s {} -n {} -t {} --dest-name {}' ' --elastic-pool {}'.format( rg, server_name, database_name, datetime.utcnow().isoformat(), restore_pool_database_name, elastic_pool), checks=[ JMESPathCheck('resourceGroup', rg), JMESPathCheck('name', restore_pool_database_name), JMESPathCheck('elasticPoolName', elastic_pool), JMESPathCheck('status', 'Online') ]) # delete sql server self.cmd('sql server delete -g {} --name {}'.format(rg, server_name), checks=NoneCheck())
def body(self): plan = 'webapp-linux-plan' webapp = 'webapp-linux' self.cmd('appservice plan create -g {} -n {} --sku S1 --is-linux' .format(self.resource_group, plan), checks=[ JMESPathCheck('reserved', True), #this weird field means it is a linux JMESPathCheck('sku.name', 'S1'), ]) self.cmd('appservice web create -g {} -n {} --plan {}'.format(self.resource_group, webapp, plan), checks=[ JMESPathCheck('name', webapp), ]) self.cmd('appservice web config update -g {} -n {} --startup-file {}'.format(self.resource_group, webapp, 'process.json'), checks=[ JMESPathCheck('appCommandLine', 'process.json') ]) self.cmd('appservice web config container update -g {} -n {} --docker-custom-image-name {} --docker-registry-server-password {} --docker-registry-server-user {} --docker-registry-server-url {}'.format( self.resource_group, webapp, 'foo-image', 'foo-password', 'foo-user', 'foo-url'), checks=[ JMESPathCheck('DOCKER_CUSTOM_IMAGE_NAME', 'foo-image'), JMESPathCheck('DOCKER_REGISTRY_SERVER_URL', 'foo-url'), JMESPathCheck('DOCKER_REGISTRY_SERVER_USERNAME', 'foo-user'), JMESPathCheck('DOCKER_REGISTRY_SERVER_PASSWORD', 'foo-password') ]) self.cmd('appservice web config container show -g {} -n {} '.format(self.resource_group, webapp), checks=[ JMESPathCheck('DOCKER_CUSTOM_IMAGE_NAME', 'foo-image'), JMESPathCheck('DOCKER_REGISTRY_SERVER_URL', 'foo-url'), JMESPathCheck('DOCKER_REGISTRY_SERVER_USERNAME', 'foo-user'), JMESPathCheck('DOCKER_REGISTRY_SERVER_PASSWORD', 'foo-password') ]) self.cmd('appservice web config container delete -g {} -n {}'.format(self.resource_group, webapp)) self.cmd('appservice web config container show -g {} -n {} '.format(self.resource_group, webapp), checks=NoneCheck())
def body(self): rg = self.resource_group loc = self.location user = self.administrator_login password = self.administrator_login_password firewall_rule_1 = 'rule1' start_ip_address_1 = '0.0.0.0' end_ip_address_1 = '255.255.255.255' firewall_rule_2 = 'rule2' start_ip_address_2 = '123.123.123.123' end_ip_address_2 = '123.123.123.124' # test create sql server with minimal required parameters self.cmd('sql server create -g {} --name {} -l {} ' '--administrator-login {} --administrator-login-password {}' .format(rg, self.sql_server_name, loc, user, password), checks=[ JMESPathCheck('name', self.sql_server_name), JMESPathCheck('resourceGroup', rg), JMESPathCheck('administratorLogin', user)]) # test sql server firewall create self.cmd('sql server firewall create --name {} -g {} --server-name {} ' '--start-ip-address {} --end-ip-address {}' .format(firewall_rule_1, rg, self.sql_server_name, start_ip_address_1, end_ip_address_1), checks=[ JMESPathCheck('name', firewall_rule_1), JMESPathCheck('resourceGroup', rg), JMESPathCheck('startIpAddress', start_ip_address_1), JMESPathCheck('endIpAddress', end_ip_address_1)]) # test sql server firewall show self.cmd('sql server firewall show --name {} -g {} --server-name {}' .format(firewall_rule_1, rg, self.sql_server_name), checks=[ JMESPathCheck('name', firewall_rule_1), JMESPathCheck('resourceGroup', rg), JMESPathCheck('startIpAddress', start_ip_address_1), JMESPathCheck('endIpAddress', end_ip_address_1)]) # test sql server firewall update self.cmd('sql server firewall update --name {} -g {} --server-name {} ' '--start-ip-address {} --end-ip-address {}' .format(firewall_rule_1, rg, self.sql_server_name, start_ip_address_2, end_ip_address_2), checks=[ JMESPathCheck('name', firewall_rule_1), JMESPathCheck('resourceGroup', rg), JMESPathCheck('startIpAddress', start_ip_address_2), JMESPathCheck('endIpAddress', end_ip_address_2)]) # test sql server firewall create another rule self.cmd('sql server firewall create --name {} -g {} --server-name {} ' '--start-ip-address {} --end-ip-address {}' .format(firewall_rule_2, rg, self.sql_server_name, start_ip_address_2, end_ip_address_2), checks=[ JMESPathCheck('name', firewall_rule_2), JMESPathCheck('resourceGroup', rg), JMESPathCheck('startIpAddress', start_ip_address_2), JMESPathCheck('endIpAddress', end_ip_address_2)]) # test sql server firewall list self.cmd('sql server firewall list -g {} --server-name {}' .format(rg, self.sql_server_name), checks=[JMESPathCheck('length(@)', 2)]) # test sql server firewall delete self.cmd('sql server firewall delete --name {} -g {} --server-name {}' .format(firewall_rule_1, rg, self.sql_server_name), checks=NoneCheck()) self.cmd('sql server firewall list -g {} --server-name {}' .format(rg, self.sql_server_name), checks=[JMESPathCheck('length(@)', 1)]) self.cmd('sql server firewall delete --name {} -g {} --server-name {}' .format(firewall_rule_2, rg, self.sql_server_name), checks=NoneCheck()) self.cmd('sql server firewall list -g {} --server-name {}' .format(rg, self.sql_server_name), checks=[JMESPathCheck('length(@)', 0)]) # test delete sql server self.cmd('sql server delete -g {} --name {}' .format(rg, self.sql_server_name), checks=NoneCheck())
def body(self): slot = 'staging' #You can create and use any repros with the 3 files under "./sample_web" and with a 'staging 'branch test_git_repo = 'https://github.com/yugangw-msft/azure-site-test' self.cmd('appservice web deployment slot create -g {} -n {} --slot {}'.format(self.resource_group, self.webapp, slot), checks=[ JMESPathCheck('name', self.webapp + '/' + slot), JMESPathCheck('siteName', '{}({})'.format(self.webapp, slot)) ]) self.cmd('appservice web source-control config -g {} -n {} --repo-url {} --branch {} --slot {}'.format(self.resource_group, self.webapp, test_git_repo, slot, slot), checks=[ JMESPathCheck('repoUrl', test_git_repo), JMESPathCheck('branch', slot) ]) import time time.sleep(30) # 30 seconds should be enough for the deployment finished(Skipped under playback mode) import requests r = requests.get('http://{}-{}.azurewebsites.net'.format(self.webapp, slot)) #verify the web page contains content from the staging branch self.assertTrue('Staging' in str(r.content)) self.cmd('appservice web deployment slot swap -g {} -n {} --slot {}'.format(self.resource_group, self.webapp, slot)) time.sleep(30) # 30 seconds should be enough for the slot swap finished(Skipped under playback mode) r = requests.get('http://{}.azurewebsites.net'.format(self.webapp)) #verify the web page contains content from the staging branch self.assertTrue('Staging' in str(r.content)) self.cmd('appservice web deployment slot list -g {} -n {}'.format(self.resource_group, self.webapp), checks=[ JMESPathCheck("length([])", 1), JMESPathCheck('[0].name', self.webapp + '/' + slot), ]) self.cmd('appservice web deployment slot delete -g {} -n {} --slot {}'.format(self.resource_group, self.webapp, slot), checks=NoneCheck())
def _test_keyvault_certificate_issuers(self): kv = self.keyvault_name self.cmd( 'keyvault certificate issuer create --vault-name {} --issuer-name issuer1 --provider Test' .format(kv), checks=[ JMESPathCheck('provider', 'Test'), JMESPathCheck('attributes.enabled', True) ]) with self.assertRaises(CLIError): self.cmd( 'keyvault certificate issuer create --vault-name {} --issuer-name issuer1 --provider-name Test' .format(kv)) self.cmd( 'keyvault certificate issuer show --vault-name {} --issuer-name issuer1' .format(kv), checks=[ JMESPathCheck('provider', 'Test'), JMESPathCheck('attributes.enabled', True) ]) self.cmd( 'keyvault certificate issuer update --vault-name {} --issuer-name issuer1 --organization-id TestOrg --account-id test_account' .format(kv), checks=[ JMESPathCheck('provider', 'Test'), JMESPathCheck('attributes.enabled', True), JMESPathCheck('organizationDetails.id', 'TestOrg'), JMESPathCheck('credentials.accountId', 'test_account') ]) with self.assertRaises(CLIError): self.cmd( 'keyvault certificate issuer update --vault-name {} --issuer-name notexist --organization-id TestOrg --account-id test_account' .format(kv)) self.cmd( 'keyvault certificate issuer update --vault-name {} --issuer-name issuer1 --account-id ""' .format(kv), checks=[ JMESPathCheck('provider', 'Test'), JMESPathCheck('attributes.enabled', True), JMESPathCheck('organizationDetails.id', 'TestOrg'), JMESPathCheck('credentials.accountId', None) ]) self.cmd('keyvault certificate issuer list --vault-name {}'.format(kv), checks=JMESPathCheck('length(@)', 1)) # test admin commands self.cmd( 'keyvault certificate issuer admin add --vault-name {} --issuer-name issuer1 --email [email protected] --first-name Test --last-name Admin --phone 123-456-7890' .format(kv), checks=[ JMESPathCheck('emailAddress', '*****@*****.**'), JMESPathCheck('firstName', 'Test'), JMESPathCheck('lastName', 'Admin'), JMESPathCheck('phone', '123-456-7890'), ]) with self.assertRaises(CLIError): self.cmd( 'keyvault certificate issuer admin add --vault-name {} --issuer-name issuer1 --email [email protected]' .format(kv)) self.cmd( 'keyvault certificate issuer admin add --vault-name {} --issuer-name issuer1 --email [email protected]' .format(kv), checks=[ JMESPathCheck('emailAddress', '*****@*****.**'), JMESPathCheck('firstName', None), JMESPathCheck('lastName', None), JMESPathCheck('phone', None), ]) self.cmd( 'keyvault certificate issuer admin list --vault-name {} --issuer-name issuer1' .format(kv), checks=JMESPathCheck('length(@)', 2)) self.cmd( 'keyvault certificate issuer admin delete --vault-name {} --issuer-name issuer1 --email [email protected]' .format(kv)) self.cmd( 'keyvault certificate issuer admin list --vault-name {} --issuer-name issuer1' .format(kv), checks=JMESPathCheck('length(@)', 1)) self.cmd( 'keyvault certificate issuer delete --vault-name {} --issuer-name issuer1' .format(kv)) self.cmd('keyvault certificate issuer list --vault-name {}'.format(kv), checks=NoneCheck())
def body(self): sas_url = 'https://azureclistore.blob.core.windows.net/sitebackups?sv=2015-04-05&sr=c&sig=%2FjH1lEtbm3uFqtMI%2BfFYwgrntOs1qhGnpGv9uRibJ7A%3D&se=2017-02-14T04%3A53%3A28Z&sp=rwdl' frequency = '1d' db_conn_str = 'Server=tcp:cli-backup.database.windows.net,1433;Initial Catalog=cli-db;Persist Security Info=False;User ID=cliuser;Password=cli!password1;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;' retention_period = 5 # set without databases self.cmd( 'appservice web config backup update -g {} --webapp-name {} --frequency {} --container-url {} --retain-one true --retention {}' .format(self.resource_group, self.webapp_name, frequency, sas_url, retention_period), checks=NoneCheck()) checks = [ JMESPathCheck('backupSchedule.frequencyInterval', 1), JMESPathCheck('backupSchedule.frequencyUnit', 'Day'), JMESPathCheck('backupSchedule.keepAtLeastOneBackup', True), JMESPathCheck('backupSchedule.retentionPeriodInDays', retention_period) ] self.cmd( 'appservice web config backup show -g {} --webapp-name {}'.format( self.resource_group, self.webapp_name), checks=checks) # update with databases database_name = 'cli-db' database_type = 'SqlAzure' self.cmd( 'appservice web config backup update -g {} --webapp-name {} --db-connection-string "{}" --db-name {} --db-type {} --retain-one true' .format(self.resource_group, self.webapp_name, db_conn_str, database_name, database_type), checks=NoneCheck()) checks = [ JMESPathCheck('backupSchedule.frequencyInterval', 1), JMESPathCheck('backupSchedule.frequencyUnit', 'Day'), JMESPathCheck('backupSchedule.keepAtLeastOneBackup', True), JMESPathCheck('backupSchedule.retentionPeriodInDays', retention_period), JMESPathCheck('databases[0].connectionString', db_conn_str), JMESPathCheck('databases[0].databaseType', database_type), JMESPathCheck('databases[0].name', database_name) ] self.cmd( 'appservice web config backup show -g {} --webapp-name {}'.format( self.resource_group, self.webapp_name), checks=checks) # update frequency and retention only frequency = '18h' retention_period = 7 self.cmd( 'appservice web config backup update -g {} --webapp-name {} --frequency {} --retain-one false --retention {}' .format(self.resource_group, self.webapp_name, frequency, retention_period), checks=NoneCheck()) checks = [ JMESPathCheck('backupSchedule.frequencyInterval', 18), JMESPathCheck('backupSchedule.frequencyUnit', 'Hour'), JMESPathCheck('backupSchedule.keepAtLeastOneBackup', False), JMESPathCheck('backupSchedule.retentionPeriodInDays', retention_period), JMESPathCheck('databases[0].connectionString', db_conn_str), JMESPathCheck('databases[0].databaseType', database_type), JMESPathCheck('databases[0].name', database_name) ] self.cmd( 'appservice web config backup show -g {} --webapp-name {}'.format( self.resource_group, self.webapp_name), checks=checks)
def body(self): rg = self.resource_group kv = self.keyvault_names[0] loc = self.location # test create keyvault with default access policy set keyvault = self.cmd( 'keyvault create -g {} -n {} -l {}'.format(rg, kv, loc), checks=[ JMESPathCheck('name', kv), JMESPathCheck('location', loc), JMESPathCheck('resourceGroup', rg), JMESPathCheck('type(properties.accessPolicies)', 'array'), JMESPathCheck('length(properties.accessPolicies)', 1), JMESPathCheck('properties.sku.name', 'standard') ]) policy_id = keyvault['properties']['accessPolicies'][0]['objectId'] self.cmd('keyvault show -n {}'.format(kv), checks=[ JMESPathCheck('name', kv), JMESPathCheck('location', loc), JMESPathCheck('resourceGroup', rg), JMESPathCheck('type(properties.accessPolicies)', 'array'), JMESPathCheck('length(properties.accessPolicies)', 1), ]) self.cmd('keyvault list -g {}'.format(rg), checks=[ JMESPathCheck('type(@)', 'array'), JMESPathCheck('length(@)', 1), JMESPathCheck('[0].name', kv), JMESPathCheck('[0].location', loc), JMESPathCheck('[0].resourceGroup', rg), ]) # test updating keyvault sku name self.cmd( 'keyvault update -g {} -n {} --set properties.sku.name=premium'. format(rg, kv), checks=[ JMESPathCheck('name', kv), JMESPathCheck('properties.sku.name', 'premium'), ]) # test policy set/delete self.cmd( 'keyvault set-policy -g {} -n {} --object-id {} --certificate-permissions get list' .format(rg, kv, policy_id), checks=JMESPathCheck( 'length(properties.accessPolicies[0].permissions.certificates)', 2)) self.cmd('keyvault delete-policy -g {} -n {} --object-id {}'.format( rg, kv, policy_id), checks=[ JMESPathCheck('type(properties.accessPolicies)', 'array'), JMESPathCheck('length(properties.accessPolicies)', 0) ]) # test keyvault delete self.cmd('keyvault delete -n {}'.format(kv)) self.cmd('keyvault list -g {}'.format(rg), checks=NoneCheck()) # test create keyvault further self.cmd('keyvault create -g {} -n {} -l {} --no-self-perms'.format( rg, self.keyvault_names[1], loc), checks=[ JMESPathCheck('type(properties.accessPolicies)', 'array'), JMESPathCheck('length(properties.accessPolicies)', 0) ]) self.cmd('keyvault create -g {} -n {} -l {} --enabled-for-deployment true '\ '--enabled-for-disk-encryption true --enabled-for-template-deployment true'.format(rg, self.keyvault_names[2], loc), checks=[ JMESPathCheck('properties.enabledForDeployment', True), JMESPathCheck('properties.enabledForDiskEncryption', True), JMESPathCheck('properties.enabledForTemplateDeployment', True) ]) self.cmd('keyvault create -g {} -n {} -l {} --sku premium'.format( rg, self.keyvault_names[3], loc), checks=[JMESPathCheck('properties.sku.name', 'premium')])
def body(self): kv = self.keyvault_name # create a key key = self.cmd( 'keyvault key create --vault-name {} -n key1 -p software'.format( kv), checks=JMESPathCheck('attributes.enabled', True)) first_kid = key['key']['kid'] first_version = first_kid.rsplit('/', 1)[1] # list keys self.cmd('keyvault key list --vault-name {}'.format(kv), checks=JMESPathCheck('length(@)', 1)) # create a new key version key = self.cmd( 'keyvault key create --vault-name {} -n key1 -p software --disabled --ops encrypt decrypt --tags test=foo' .format(kv), checks=[ JMESPathCheck('attributes.enabled', False), JMESPathCheck('length(key.keyOps)', 2), JMESPathCheck('tags', {'test': 'foo'}) ]) second_kid = key['key']['kid'] # list key versions self.cmd( 'keyvault key list-versions --vault-name {} -n key1'.format(kv), checks=JMESPathCheck('length(@)', 2)) # show key (latest) self.cmd('keyvault key show --vault-name {} -n key1'.format(kv), checks=JMESPathCheck('key.kid', second_kid)) # show key (specific version) self.cmd('keyvault key show --vault-name {} -n key1 -v {}'.format( kv, first_version), checks=JMESPathCheck('key.kid', first_kid)) # set key attributes self.cmd( 'keyvault key set-attributes --vault-name {} -n key1 --enabled true' .format(kv), checks=[ JMESPathCheck('key.kid', second_kid), JMESPathCheck('attributes.enabled', True) ]) # backup and then delete key key_file = 'backup.key' self.cmd( 'keyvault key backup --vault-name {} -n key1 --file {}'.format( kv, key_file)) self.cmd('keyvault key delete --vault-name {} -n key1'.format(kv)) self.cmd('keyvault key list --vault-name {}'.format(kv), checks=NoneCheck()) # restore key from backup self.cmd('keyvault key restore --vault-name {} --file {}'.format( kv, key_file)) self.cmd( 'keyvault key list-versions --vault-name {} -n key1'.format(kv), checks=JMESPathCheck('length(@)', 2)) if os.path.isfile(key_file): os.remove(key_file) # import PEM and BYOK keys key_enc_file = os.path.join(TEST_DIR, 'mydomain.test.encrypted.pem') key_enc_password = '******' key_plain_file = os.path.join(TEST_DIR, 'mydomain.test.pem') self.cmd( 'keyvault key import --vault-name {} -n import-key-plain --pem-file "{}" -p software' .format(kv, key_plain_file)) self.cmd( 'keyvault key import --vault-name {} -n import-key-encrypted --pem-file "{}" --pem-password {} -p hsm' .format(kv, key_enc_file, key_enc_password)) byok_key_file = os.path.join(TEST_DIR, 'TestBYOK-NA.byok') self.cmd( 'keyvault key import --vault-name {} -n import-key-byok --byok-file "{}"' .format(kv, byok_key_file))
def body(self): rg = self.resource_group loc = self.location user = self.admin_login password = self.admin_passwords[0] password_updated = self.admin_passwords[1] # test create sql server with minimal required parameters self.cmd('sql server create -g {} --name {} -l {} ' '--admin-user {} --admin-password {}'.format( rg, self.sql_server_names[0], loc, user, password), checks=[ JMESPathCheck('name', self.sql_server_names[0]), JMESPathCheck('resourceGroup', rg), JMESPathCheck('administratorLogin', user), JMESPathCheck('administratorLoginPassword', password) ]) # test list sql server should be 1 self.cmd('sql server list -g {}'.format(rg), checks=[JMESPathCheck('length(@)', 1)]) # test update sql server self.cmd( 'sql server update -g {} --name {} --admin-password {}'.format( rg, self.sql_server_names[0], password_updated), checks=[ JMESPathCheck('name', self.sql_server_names[0]), JMESPathCheck('resourceGroup', rg), JMESPathCheck('administratorLogin', user), JMESPathCheck('administratorLoginPassword', password_updated) ]) # test create another sql server self.cmd('sql server create -g {} --name {} -l {} ' '--admin-user {} --admin-password {}'.format( rg, self.sql_server_names[1], loc, user, password), checks=[ JMESPathCheck('name', self.sql_server_names[1]), JMESPathCheck('resourceGroup', rg), JMESPathCheck('administratorLogin', user), JMESPathCheck('administratorLoginPassword', password) ]) # test list sql server should be 2 self.cmd('sql server list -g {}'.format(rg), checks=[JMESPathCheck('length(@)', 2)]) # test show sql server self.cmd('sql server show -g {} --name {}'.format( rg, self.sql_server_names[0]), checks=[ JMESPathCheck('name', self.sql_server_names[0]), JMESPathCheck('resourceGroup', rg), JMESPathCheck('administratorLogin', user) ]) # test delete sql server self.cmd('sql server delete -g {} --name {}'.format( rg, self.sql_server_names[0]), checks=NoneCheck()) self.cmd('sql server delete -g {} --name {}'.format( rg, self.sql_server_names[1]), checks=NoneCheck()) # test list sql server should be 0 self.cmd('sql server list -g {}'.format(rg), checks=[JMESPathCheck('length(@)', 0)])
def body(self): kv = self.keyvault_name self._test_certificate_download() policy_path = os.path.join(TEST_DIR, 'policy.json') policy2_path = os.path.join(TEST_DIR, 'policy2.json') # create a certificate self.cmd( 'keyvault certificate create --vault-name {} -n cert1 -p @"{}"'. format(kv, policy_path), checks=JMESPathCheck('status', 'completed')) # list certificates self.cmd('keyvault certificate list --vault-name {}'.format(kv), checks=JMESPathCheck('length(@)', 1)) # create a new certificate version self.cmd( 'keyvault certificate create --vault-name {} -n cert1 -p @"{}"'. format(kv, policy2_path), checks=[ JMESPathCheck('status', 'completed'), ]) # list certificate versions ver_list = self.cmd( 'keyvault certificate list-versions --vault-name {} -n cert1'. format(kv), checks=JMESPathCheck('length(@)', 2)) ver_list = sorted(ver_list, key=lambda x: x['attributes']['created']) versions = [x['id'] for x in ver_list] # show certificate (latest) self.cmd( 'keyvault certificate show --vault-name {} -n cert1'.format(kv), checks=[ JMESPathCheck('id', versions[1]), JMESPathCheck( 'policy.x509CertificateProperties.validityInMonths', 50) ]) # show certificate (specific version) cert_version = versions[0].rsplit('/', 1)[1] self.cmd( 'keyvault certificate show --vault-name {} -n cert1 -v {}'.format( kv, cert_version), checks=JMESPathCheck('id', versions[0])) # update certificate attributes self.cmd( 'keyvault certificate set-attributes --vault-name {} -n cert1 --enabled false -p @"{}"' .format(kv, policy_path), checks=[ JMESPathCheck('id', versions[1]), JMESPathCheck('attributes.enabled', False), JMESPathCheck( 'policy.x509CertificateProperties.validityInMonths', 60) ]) self._test_keyvault_certificate_contacts() self._test_keyvault_certificate_issuers() self._test_keyvault_pending_certificate() # delete certificate self.cmd( 'keyvault certificate delete --vault-name {} -n cert1'.format(kv)) self.cmd('keyvault certificate list --vault-name {}'.format(kv), checks=NoneCheck()) # test certificate import pem_encrypted_file = os.path.join(TEST_DIR, 'import_pem_encrypted_pwd_1234.pem') pem_encrypted_password = '******' pem_plain_file = os.path.join(TEST_DIR, 'import_pem_plain.pem') pem_policy_path = os.path.join(TEST_DIR, 'policy_import_pem.json') self.cmd( 'keyvault certificate import --vault-name {} -n pem-cert1 --file "{}" -p @"{}"' .format(kv, pem_plain_file, pem_policy_path)) self.cmd( 'keyvault certificate import --vault-name {} -n pem-cert2 --file "{}" --password {} -p @"{}"' .format(kv, pem_encrypted_file, pem_encrypted_password, pem_policy_path)) pfx_plain_file = os.path.join(TEST_DIR, 'import_pfx.pfx') pfx_policy_path = os.path.join(TEST_DIR, 'policy_import_pfx.json') self.cmd( 'keyvault certificate import --vault-name {} -n pfx-cert --file "{}" -p @"{}"' .format(kv, pfx_plain_file, pfx_policy_path))
def body(self): plan_result = self.cmd( 'appservice plan create -g {} -n {} --sku S1'.format( self.resource_group, self.plan)) self.cmd('webapp create -g {} -n {} --plan {}'.format( self.resource_group, self.webapp, plan_result['id'])) # You can create and use any repros with the 3 files under "./sample_web" and with a 'staging 'branch slot = 'staging' slot2 = 'dev' test_git_repo = 'https://github.com/yugangw-msft/azure-site-test' test_node_version = '6.6.0' # create a few app-settings to test they can be cloned self.cmd( 'webapp config appsettings set -g {} -n {} --settings s1=v1 --slot-settings s2=v2' .format(self.resource_group, self.webapp)) # create an empty slot self.cmd('webapp deployment slot create -g {} -n {} --slot {}'.format( self.resource_group, self.webapp, slot), checks=[JMESPathCheck('name', slot)]) self.cmd( 'webapp deployment source config -g {} -n {} --repo-url {} --branch {} -s {} --manual-integration' .format(self.resource_group, self.webapp, test_git_repo, slot, slot), checks=[ JMESPathCheck('repoUrl', test_git_repo), JMESPathCheck('branch', slot) ]) import time import requests # comment out the git sync testing as it requires to pre-load a git token # the rest test steps should be sufficient to verify the slot functionalities. # verify the slot wires up the git repo/branch # time.sleep(30) # 30 seconds should be enough for the deployment finished(Skipped under playback mode) # r = requests.get('http://{}-{}.azurewebsites.net'.format(self.webapp, slot)) # self.assertTrue('Staging' in str(r.content)) # swap with prod and verify the git branch also switched self.cmd('webapp deployment slot swap -g {} -n {} -s {}'.format( self.resource_group, self.webapp, slot)) # time.sleep(30) # 30 seconds should be enough for the slot swap finished(Skipped under playback mode) # r = requests.get('http://{}.azurewebsites.net'.format(self.webapp)) # self.assertTrue('Staging' in str(r.content)) result = self.cmd( 'webapp config appsettings list -g {} -n {} -s {}'.format( self.resource_group, self.webapp, slot)) self.assertEqual(set([x['name'] for x in result]), set(['WEBSITE_NODE_DEFAULT_VERSION', 's1'])) # create a new slot by cloning from prod slot self.cmd('webapp config set -g {} -n {} --node-version {}'.format( self.resource_group, self.webapp, test_node_version)) self.cmd( 'webapp deployment slot create -g {} -n {} --slot {} --configuration-source {}' .format(self.resource_group, self.webapp, slot2, self.webapp)) self.cmd('webapp config appsettings list -g {} -n {} --slot {}'.format( self.resource_group, self.webapp, slot2), checks=[ JMESPathCheck("length([])", 1), JMESPathCheck('[0].name', 'WEBSITE_NODE_DEFAULT_VERSION') ]) self.cmd('webapp config show -g {} -n {} --slot {}'.format( self.resource_group, self.webapp, slot2), checks=[ JMESPathCheck("nodeVersion", test_node_version), ]) self.cmd( 'webapp config appsettings set -g {} -n {} --slot {} --settings s3=v3 --slot-settings s4=v4' .format(self.resource_group, self.webapp, slot2)) self.cmd( 'webapp config connection-string set -g {} -n {} -t mysql --slot {} --settings c1=connection1 --slot-settings c2=connection2' .format(self.resource_group, self.webapp, slot2)) # verify we can swap with non production slot self.cmd( 'webapp deployment slot swap -g {} -n {} --slot {} --target-slot {}' .format(self.resource_group, self.webapp, slot, slot2), checks=NoneCheck()) result = self.cmd( 'webapp config appsettings list -g {} -n {} --slot {}'.format( self.resource_group, self.webapp, slot2)) self.assertEqual(set([x['name'] for x in result]), set(['WEBSITE_NODE_DEFAULT_VERSION', 's1', 's4'])) result = self.cmd( 'webapp config connection-string list -g {} -n {} --slot {}'. format(self.resource_group, self.webapp, slot2)) self.assertEqual(set([x['name'] for x in result]), set(['c2'])) result = self.cmd( 'webapp config appsettings list -g {} -n {} --slot {}'.format( self.resource_group, self.webapp, slot)) self.assertEqual(set([x['name'] for x in result]), set(['WEBSITE_NODE_DEFAULT_VERSION', 's3'])) result = self.cmd( 'webapp config connection-string list -g {} -n {} --slot {}'. format(self.resource_group, self.webapp, slot)) self.assertEqual(set([x['name'] for x in result]), set(['c1'])) self.cmd('webapp deployment slot list -g {} -n {}'.format( self.resource_group, self.webapp), checks=[ JMESPathCheck("length([])", 2), JMESPathCheck("length([?name=='{}'])".format(slot2), 1), JMESPathCheck("length([?name=='{}'])".format(slot), 1), ]) self.cmd('webapp deployment slot delete -g {} -n {} --slot {}'.format( self.resource_group, self.webapp, slot), checks=NoneCheck())
def body(self): s = self container = s.container proposed_lease_id = s.proposed_lease_id new_lease_id = s.new_lease_id date = s.date _get_connection_string(self) s.cmd('storage container create --name {} --fail-on-exist'.format( container), checks=JMESPathCheck('created', True)) s.cmd('storage container exists -n {}'.format(container), checks=JMESPathCheck('exists', True)) s.cmd('storage container set-permission -n {} --public-access blob'. format(container)) s.cmd('storage container show-permission -n {}'.format(container), checks=JMESPathCheck('publicAccess', 'blob')) s.cmd('storage container set-permission -n {} --public-access off'. format(container)) s.cmd('storage container show-permission -n {}'.format(container), checks=JMESPathCheck('publicAccess', 'off')) s.cmd('storage container show -n {}'.format(container), checks=JMESPathCheck('name', container)) res = s.cmd('storage container list') assert container in [x['name'] for x in res] s.cmd( 'storage container metadata update -n {} --metadata foo=bar moo=bak' .format(container)) s.cmd( 'storage container metadata show -n {}'.format(container), checks=[JMESPathCheck('foo', 'bar'), JMESPathCheck('moo', 'bak')]) s.cmd('storage container metadata update -n {}'.format( container)) # reset metadata s.cmd('storage container metadata show -n {}'.format(container), checks=NoneCheck()) s._storage_blob_scenario() # test lease operations s.cmd( 'storage container lease acquire --lease-duration 60 -c {} --if-modified-since {} --proposed-lease-id {}' .format(container, date, proposed_lease_id)) s.cmd('storage container show --name {}'.format(container), checks=[ JMESPathCheck('properties.lease.duration', 'fixed'), JMESPathCheck('properties.lease.state', 'leased'), JMESPathCheck('properties.lease.status', 'locked') ]) s.cmd( 'storage container lease change -c {} --lease-id {} --proposed-lease-id {}' .format(container, proposed_lease_id, new_lease_id)) s.cmd('storage container lease renew -c {} --lease-id {}'.format( container, new_lease_id)) s.cmd('storage container show -n {}'.format(container), checks=[ JMESPathCheck('properties.lease.duration', 'fixed'), JMESPathCheck('properties.lease.state', 'leased'), JMESPathCheck('properties.lease.status', 'locked') ]) s.cmd('storage container lease break -c {} --lease-break-period 30'. format(container)) s.cmd('storage container show --name {}'.format(container), checks=[ JMESPathCheck('properties.lease.duration', None), JMESPathCheck('properties.lease.state', 'breaking'), JMESPathCheck('properties.lease.status', 'locked') ]) s.cmd('storage container lease release -c {} --lease-id {}'.format( container, new_lease_id)) s.cmd('storage container show --name {}'.format(container), checks=[ JMESPathCheck('properties.lease.duration', None), JMESPathCheck('properties.lease.state', 'available'), JMESPathCheck('properties.lease.status', 'unlocked') ]) sas = s.cmd('storage container generate-sas -n {}'.format(container)) sas_keys = dict(pair.split('=') for pair in sas.split('&')) assert u'sig' in sas_keys # verify delete operation s.cmd('storage container delete --name {} --fail-not-exist'.format( container), checks=JMESPathCheck('deleted', True)) s.cmd('storage container exists -n {}'.format(container), checks=JMESPathCheck('exists', False))
def body(self): kv = self.keyvault_name policy_path = os.path.join(TEST_DIR, 'policy.json') policy2_path = os.path.join(TEST_DIR, 'policy2.json') # create a certificate self.cmd( 'keyvault certificate create --vault-name {} -n cert1 -p @"{}"'. format(kv, policy_path), checks=JMESPathCheck('status', 'completed')) # list certificates self.cmd('keyvault certificate list --vault-name {}'.format(kv), checks=JMESPathCheck('length(@)', 1)) # create a new certificate version self.cmd( 'keyvault certificate create --vault-name {} -n cert1 -p @"{}"'. format(kv, policy2_path), checks=[ JMESPathCheck('status', 'completed'), ]) # list certificate versions ver_list = self.cmd( 'keyvault certificate list-versions --vault-name {} -n cert1'. format(kv), checks=JMESPathCheck('length(@)', 2)) ver_list = sorted(ver_list, key=lambda x: x['attributes']['created']) versions = [x['id'] for x in ver_list] # show certificate (latest) self.cmd( 'keyvault certificate show --vault-name {} -n cert1'.format(kv), checks=[ JMESPathCheck('id', versions[1]), JMESPathCheck( 'policy.x509CertificateProperties.validityInMonths', 50) ]) # show certificate (specific version) cert_version = versions[0].rsplit('/', 1)[1] self.cmd( 'keyvault certificate show --vault-name {} -n cert1 -v {}'.format( kv, cert_version), checks=JMESPathCheck('id', versions[0])) # update certificate attributes self.cmd( 'keyvault certificate set-attributes --vault-name {} -n cert1 --enabled false -p @"{}"' .format(kv, policy_path), checks=[ JMESPathCheck('id', versions[1]), JMESPathCheck('attributes.enabled', False), JMESPathCheck( 'policy.x509CertificateProperties.validityInMonths', 60) ]) self._test_keyvault_certificate_contacts() self._test_keyvault_certificate_issuers() # PHASE 3 COMMANDS # TODO: download certificiate # TODO: import certificate # TODO: merge certificate # delete certificate self.cmd( 'keyvault certificate delete --vault-name {} -n cert1'.format(kv)) self.cmd('keyvault certificate list --vault-name {}'.format(kv), checks=NoneCheck())
def _storage_blob_scenario(self): s = self container = s.container account = s.account block_blob = 'testblockblob' page_blob = 'testpageblob' append_blob = 'testappendblob' blob = block_blob dest_file = os.path.join(TEST_DIR, 'download-blob.rst') proposed_lease_id = s.proposed_lease_id new_lease_id = s.new_lease_id date = s.date # test block blob upload s.cmd( 'storage blob upload -n {} -c {} --type block --file "{}"'.format( block_blob, container, os.path.join(TEST_DIR, 'testfile.rst'))) s.cmd('storage blob exists -n {} -c {}'.format(block_blob, container), checks=JMESPathCheck('exists', True)) # test page blob upload s.cmd('storage blob upload -n {} -c {} --type page --file "{}"'.format( page_blob, container, os.path.join(TEST_DIR, 'testpage.rst'))) s.cmd('storage blob exists -n {} -c {}'.format(page_blob, container), checks=JMESPathCheck('exists', True)) # test append blob upload s.cmd( 'storage blob upload -n {} -c {} --type append --file "{}"'.format( append_blob, container, os.path.join(TEST_DIR, 'testfile.rst'))) s.cmd( 'storage blob upload -n {} -c {} --type append --file "{}"'.format( append_blob, container, os.path.join(TEST_DIR, 'testfile.rst'))) s.cmd('storage blob exists -n {} -c {}'.format(append_blob, container), checks=JMESPathCheck('exists', True)) # test generate a sas sas = s.cmd( 'storage blob generate-sas -n {} -c {} --expiry 2046-12-31T08:23Z --permissions r --https-only' ) sas_keys = dict(pair.split('=') for pair in sas.split('&')) assert u'se' in sas_keys blob_url = 'https://{}.blob.core.windows.net/{}/{}'.format( account, container, blob) s.cmd('storage blob url -n {} -c {}'.format(blob, container), checks=StringCheck(blob_url)) s.cmd('storage blob metadata update -n {} -c {} --metadata a=b c=d'. format(blob, container)) s.cmd('storage blob metadata show -n {} -c {}'.format(blob, container), checks=[JMESPathCheck('a', 'b'), JMESPathCheck('c', 'd')]) s.cmd('storage blob metadata update -n {} -c {}'.format( blob, container)) s.cmd('storage blob metadata show -n {} -c {}'.format(blob, container), checks=NoneCheck()) res = s.cmd('storage blob list --container-name {}'.format(container)) blob_list = [block_blob, append_blob, page_blob] for item in res: assert item['name'] in blob_list s.cmd('storage blob show --container-name {} --name {}'.format( container, block_blob), checks=[ JMESPathCheck('name', block_blob), JMESPathCheck('properties.blobType', 'BlockBlob') ]) s.cmd('storage blob update -c {} -n {} --content-type "test/type"'. format(container, block_blob)) s.cmd('storage blob show -c {} -n {}'.format(container, block_blob), checks=JMESPathCheck('properties.contentSettings.contentType', 'test/type')) s.cmd('storage blob service-properties show', checks=JMESPathCheck('hourMetrics.enabled', True)) s.cmd('storage blob download -n {} -c {} --file "{}"'.format( blob, container, dest_file)) if os.path.isfile(dest_file): os.remove(dest_file) else: raise CLIError('Download failed. Test failed!') # test lease operations s.cmd( 'storage blob lease acquire --lease-duration 60 -b {} -c {} --if-modified-since {} --proposed-lease-id {}' .format(blob, container, date, proposed_lease_id)) s.cmd('storage blob show -n {} -c {}'.format(blob, container), checks=[ JMESPathCheck('properties.lease.duration', 'fixed'), JMESPathCheck('properties.lease.state', 'leased'), JMESPathCheck('properties.lease.status', 'locked') ]) s.cmd( 'storage blob lease change -b {} -c {} --lease-id {} --proposed-lease-id {}' .format(blob, container, proposed_lease_id, new_lease_id)) s.cmd('storage blob lease renew -b {} -c {} --lease-id {}'.format( blob, container, new_lease_id)) s.cmd('storage blob show -n {} -c {}'.format(blob, container), checks=[ JMESPathCheck('properties.lease.duration', 'fixed'), JMESPathCheck('properties.lease.state', 'leased'), JMESPathCheck('properties.lease.status', 'locked') ]) s.cmd('storage blob lease break -b {} -c {} --lease-break-period 30'. format(blob, container)) s.cmd('storage blob show -n {} -c {}'.format(blob, container), checks=[ JMESPathCheck('properties.lease.duration', None), JMESPathCheck('properties.lease.state', 'breaking'), JMESPathCheck('properties.lease.status', 'locked') ]) s.cmd('storage blob lease release -b {} -c {} --lease-id {}'.format( blob, container, new_lease_id)) s.cmd('storage blob show -n {} -c {}'.format(blob, container), checks=[ JMESPathCheck('properties.lease.duration', None), JMESPathCheck('properties.lease.state', 'available'), JMESPathCheck('properties.lease.status', 'unlocked') ]) json_result = s.cmd('storage blob snapshot -c {} -n {}'.format( container, append_blob)) snapshot_dt = json_result['snapshot'] s.cmd('storage blob exists -n {} -c {} --snapshot {}'.format( append_blob, container, snapshot_dt), checks=JMESPathCheck('exists', True)) s.cmd('storage blob delete --container-name {} --name {}'.format( container, blob)) s.cmd('storage blob exists -n {} -c {}'.format(blob, container), checks=JMESPathCheck('exists', False))
def body(self): rg = self.resource_group location = self.location hub = self.hub_name # Test 'az iot hub create' self.cmd('iot hub create -n {0} -g {1} --sku S1'.format(hub, rg), checks=[ JMESPathCheck('resourceGroup', rg), JMESPathCheck('location', location), JMESPathCheck('name', hub), JMESPathCheck('sku.name', 'S1') ]) # Test 'az iot hub show-connection-string' conn_str_pattern = r'^HostName={0}\.azure-devices\.net;SharedAccessKeyName=iothubowner;SharedAccessKey='.format( hub) self.cmd('iot hub show-connection-string -n {0}'.format(hub), checks=[ JMESPathPatternCheck('connectionString', conn_str_pattern) ]) self.cmd('iot hub show-connection-string -g {0}'.format(rg), checks=[ JMESPathCheck('length([*])', 1), JMESPathCheck('[0].name', hub), JMESPathPatternCheck('[0].connectionString', conn_str_pattern) ]) # Test 'az iot hub show' self.cmd('iot hub show -n {0}'.format(hub), checks=[ JMESPathCheck('resourceGroup', rg), JMESPathCheck('location', location), JMESPathCheck('name', hub), JMESPathCheck('sku.name', 'S1') ]) # Test 'az iot hub list' self.cmd('iot hub list -g {0}'.format(rg), checks=[ JMESPathCheck('length([*])', 1), JMESPathCheck('[0].resourceGroup', rg), JMESPathCheck('[0].location', location), JMESPathCheck('[0].name', hub), JMESPathCheck('[0].sku.name', 'S1') ]) # Test 'az iot hub sku list' self.cmd('iot hub list-skus -n {0}'.format(hub), checks=[ JMESPathCheck('length([*])', 3), JMESPathCheck('[0].sku.name', 'S1'), JMESPathCheck('[1].sku.name', 'S2'), JMESPathCheck('[2].sku.name', 'S3') ]) # Test 'az iot hub policy list' self.cmd('iot hub policy list --hub-name {0}'.format(hub), checks=[JMESPathCheck('length([*])', 5)]) # Test 'az iot hub policy show' policy_name = 'service' self.cmd('iot hub policy show --hub-name {0} -n {1}'.format( hub, policy_name), checks=[ JMESPathCheck('keyName', policy_name), JMESPathCheck('rights', 'ServiceConnect') ]) # Test 'az iot hub consumer-group create' consumer_group_name = 'cg1' self.cmd('iot hub consumer-group create --hub-name {0} -n {1}'.format( hub, consumer_group_name), checks=[JMESPathCheck('name', consumer_group_name)]) # Test 'az iot hub consumer-group show' self.cmd('iot hub consumer-group show --hub-name {0} -n {1}'.format( hub, consumer_group_name), checks=[JMESPathCheck('name', consumer_group_name)]) # Test 'az iot hub consumer-group list' self.cmd('iot hub consumer-group list --hub-name {0}'.format(hub), checks=[ JMESPathCheck('length([*])', 2), JMESPathCheck('[0]', '$Default'), JMESPathCheck('[1]', consumer_group_name) ]) # Test 'az iot hub consumer-group delete' self.cmd('iot hub consumer-group delete --hub-name {0} -n {1}'.format( hub, consumer_group_name), checks=NoneCheck()) self.cmd('iot hub consumer-group list --hub-name {0}'.format(hub), checks=[ JMESPathCheck('length([*])', 1), JMESPathCheck('[0]', '$Default') ]) # Test 'az iot hub job list' self.cmd('iot hub job list --hub-name {0}'.format(hub), checks=NoneCheck()) # Test 'az iot hub job show' job_id = 'fake-job' expected_exception = 'Job not found with ID' self.cmd('iot hub job show --hub-name {0} --job-id {1}'.format( hub, job_id), allowed_exceptions=expected_exception) # Test 'az iot hub job cancel' expected_exception = 'JobNotFound' self.cmd('iot hub job cancel --hub-name {0} --job-id {1}'.format( hub, job_id), allowed_exceptions=expected_exception) # Test 'az iot device create' device_1 = self.device_id_1 self.cmd('iot device create --hub-name {0} -d {1}'.format( hub, device_1), checks=[ JMESPathCheck('deviceId', device_1), JMESPathCheck('status', 'enabled'), JMESPathCheck('statusReason', None), JMESPathCheck('connectionState', 'Disconnected') ]) device_2 = self.device_id_2 primary_thumbprint = 'A361EA6A7119A8B0B7BBFFA2EAFDAD1F9D5BED8C' secondary_thumbprint = '14963E8F3BA5B3984110B3C1CA8E8B8988599087' self.cmd( 'iot device create --hub-name {0} -d {1} --x509 --primary-thumbprint {2} --secondary-thumbprint {3}' .format(hub, device_2, primary_thumbprint, secondary_thumbprint), checks=[ JMESPathCheck('deviceId', device_2), JMESPathCheck('status', 'enabled'), JMESPathCheck('statusReason', None), JMESPathCheck('connectionState', 'Disconnected'), JMESPathCheck('authentication.symmetricKey.primaryKey', None), JMESPathCheck('authentication.symmetricKey.secondaryKey', None), JMESPathCheck( 'authentication.x509Thumbprint.primaryThumbprint', primary_thumbprint), JMESPathCheck( 'authentication.x509Thumbprint.secondaryThumbprint', secondary_thumbprint), ]) # Test 'az iot device show-connection-string' conn_str_pattern = r'^HostName={0}\.azure-devices\.net;DeviceId={1};SharedAccessKey='.format( hub, device_1) self.cmd( 'iot device show-connection-string --hub-name {0} -d {1}'.format( hub, device_1), checks=[ JMESPathPatternCheck('connectionString', conn_str_pattern) ]) connection_string = 'HostName={0}.azure-devices.net;DeviceId={1};x509=true'.format( hub, device_2) self.cmd( 'iot device show-connection-string --hub-name {0} -d {1}'.format( hub, device_2), checks=[JMESPathCheck('connectionString', connection_string)]) device_id_pattern = r'^test\-device\-\d$' self.cmd( 'iot device show-connection-string --hub-name {0}'.format(hub), checks=[ JMESPathCheck('length([*])', 2), JMESPathPatternCheck('[0].deviceId', device_id_pattern), JMESPathPatternCheck('[1].deviceId', device_id_pattern) ]) # Test 'az iot device show' self.cmd('iot device show --hub-name {0} -d {1}'.format(hub, device_1), checks=[ JMESPathCheck('deviceId', device_1), JMESPathCheck('status', 'enabled'), JMESPathCheck('statusReason', None), JMESPathCheck('connectionState', 'Disconnected') ]) # Test 'az iot device update' status_reason = 'TestReason' self.cmd( 'iot device update --hub-name {0} -d {1} --set statusReason={2}'. format(hub, device_2, status_reason), checks=[ JMESPathCheck('deviceId', device_2), JMESPathCheck('status', 'enabled'), JMESPathCheck('statusReason', status_reason), JMESPathCheck('connectionState', 'Disconnected'), JMESPathCheck('authentication.symmetricKey.primaryKey', None), JMESPathCheck('authentication.symmetricKey.secondaryKey', None), JMESPathCheck( 'authentication.x509Thumbprint.primaryThumbprint', primary_thumbprint), JMESPathCheck( 'authentication.x509Thumbprint.secondaryThumbprint', secondary_thumbprint), ]) # Test 'az iot device list' self.cmd('iot device list --hub-name {0}'.format(hub), checks=[ JMESPathCheck('length([*])', 2), JMESPathPatternCheck('[0].deviceId', device_id_pattern), JMESPathPatternCheck('[1].deviceId', device_id_pattern) ]) # Test 'az iot device message send' self.cmd('iot device message send --hub-name {0} -d {1}'.format( hub, device_1), checks=NoneCheck()) # Test 'az iot device message receive' self.cmd('iot device message receive --hub-name {0} -d {1}'.format( hub, device_1), checks=NoneCheck()) # Test 'az iot device message complete' lock_token = '00000000-0000-0000-0000-000000000000' expected_exception = 'PreconditionFailed' self.cmd( 'iot device message complete --hub-name {0} -d {1} --lock-token {2}' .format(hub, device_1, lock_token), allowed_exceptions=expected_exception) # Test 'az iot device message reject' self.cmd( 'iot device message reject --hub-name {0} -d {1} --lock-token {2}'. format(hub, device_1, lock_token), allowed_exceptions=expected_exception) # Test 'az iot device message abandon' self.cmd( 'iot device message abandon --hub-name {0} -d {1} --lock-token {2}' .format(hub, device_1, lock_token), allowed_exceptions=expected_exception) # Test 'az iot hub show-quota-metrics' self.cmd('iot hub show-quota-metrics -n {0}'.format(hub), checks=[ JMESPathCheck('length([*])', 2), JMESPathCheck('[0].name', 'TotalMessages'), JMESPathCheck('[0].maxValue', 400000), JMESPathCheck('[1].name', 'TotalDeviceCount'), JMESPathCheck('[1].maxValue', 500000) ]) # Test 'az iot hub show-stats' device_count_pattern = r'^\d$' self.cmd('iot hub show-stats -n {0}'.format(hub), checks=[ JMESPathPatternCheck('disabledDeviceCount', device_count_pattern), JMESPathPatternCheck('enabledDeviceCount', device_count_pattern), JMESPathPatternCheck('totalDeviceCount', device_count_pattern) ]) # Test 'az iot device delete' self.cmd('iot device delete --hub-name {0} -d {1}'.format( hub, device_1), checks=NoneCheck()) self.cmd('iot device delete --hub-name {0} -d {1}'.format( hub, device_2), checks=NoneCheck())