brendandburns: @tjprescott fixed (test fixed too)
tjprescott: ```
/home/travis/build/Azure/azure-cli/src/command_modules/azure-cli-resource/tests/test_resource_validators.py:20:1: E302 expected 2 blank lines, found 1
2     E302 expected 2 blank lines, found 1
```

Have I mentioned I hate PEP8?
yugangw-msft: @brendandburns, please add a functional test, say a VCR scenario test, to verify simple "az lock create/read/delete" command work.
brendandburns: VCR test added, please take another look...
codecov-io: # [Codecov](https://codecov.io/gh/Azure/azure-cli/pull/3409?src=pr&el=h1) Report
> Merging [#3409](https://codecov.io/gh/Azure/azure-cli/pull/3409?src=pr&el=desc) into [master](https://codecov.io/gh/Azure/azure-cli/commit/7c10cae4442c3d64d5570fe4dcdf96c47dd1531a?src=pr&el=desc) will **increase** coverage by `0.18%`.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/Azure/azure-cli/pull/3409/graphs/tree.svg?width=650&src=pr&token=2pog0TKvF8&height=150)](https://codecov.io/gh/Azure/azure-cli/pull/3409?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master    #3409      +/-   ##
==========================================
+ Coverage   70.73%   70.92%   +0.18%     
==========================================
  Files         394      394              
  Lines       25534    25534              
  Branches     3889     3889              
==========================================
+ Hits        18062    18110      +48     
+ Misses       6337     6279      -58     
- Partials     1135     1145      +10
```


| [Impacted Files](https://codecov.io/gh/Azure/azure-cli/pull/3409?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [.../azure/cli/command\_modules/resource/\_validators.py](https://codecov.io/gh/Azure/azure-cli/pull/3409?src=pr&el=tree#diff-c3JjL2NvbW1hbmRfbW9kdWxlcy9henVyZS1jbGktcmVzb3VyY2UvYXp1cmUvY2xpL2NvbW1hbmRfbW9kdWxlcy9yZXNvdXJjZS9fdmFsaWRhdG9ycy5weQ==) | `69.56% <100%> (ø)` | :arrow_up: |
| [...nent/azure/cli/command\_modules/component/custom.py](https://codecov.io/gh/Azure/azure-cli/pull/3409?src=pr&el=tree#diff-c3JjL2NvbW1hbmRfbW9kdWxlcy9henVyZS1jbGktY29tcG9uZW50L2F6dXJlL2NsaS9jb21tYW5kX21vZHVsZXMvY29tcG9uZW50L2N1c3RvbS5weQ==) | `16.23% <0%> (ø)` | :arrow_up: |
| [...dback/azure/cli/command\_modules/feedback/custom.py](https://codecov.io/gh/Azure/azure-cli/pull/3409?src=pr&el=tree#diff-c3JjL2NvbW1hbmRfbW9kdWxlcy9henVyZS1jbGktZmVlZGJhY2svYXp1cmUvY2xpL2NvbW1hbmRfbW9kdWxlcy9mZWVkYmFjay9jdXN0b20ucHk=) | `34.69% <0%> (ø)` | :arrow_up: |
| [src/azure-cli-core/azure/cli/core/util.py](https://codecov.io/gh/Azure/azure-cli/pull/3409?src=pr&el=tree#diff-c3JjL2F6dXJlLWNsaS1jb3JlL2F6dXJlL2NsaS9jb3JlL3V0aWwucHk=) | `68.61% <0%> (ø)` | :arrow_up: |
| [...re/cli/command\_modules/resource/\_client\_factory.py](https://codecov.io/gh/Azure/azure-cli/pull/3409?src=pr&el=tree#diff-c3JjL2NvbW1hbmRfbW9kdWxlcy9henVyZS1jbGktcmVzb3VyY2UvYXp1cmUvY2xpL2NvbW1hbmRfbW9kdWxlcy9yZXNvdXJjZS9fY2xpZW50X2ZhY3RvcnkucHk=) | `88.46% <0%> (+5.76%)` | :arrow_up: |
| [...ource/azure/cli/command\_modules/resource/custom.py](https://codecov.io/gh/Azure/azure-cli/pull/3409?src=pr&el=tree#diff-c3JjL2NvbW1hbmRfbW9kdWxlcy9henVyZS1jbGktcmVzb3VyY2UvYXp1cmUvY2xpL2NvbW1hbmRfbW9kdWxlcy9yZXNvdXJjZS9jdXN0b20ucHk=) | `61.64% <0%> (+7.53%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/Azure/azure-cli/pull/3409?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/Azure/azure-cli/pull/3409?src=pr&el=footer). Last update [7c10cae...abc205c](https://codecov.io/gh/Azure/azure-cli/pull/3409?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

brendandburns: Comments (mostly) addressed, please take another look.
diff --git a/src/azure-cli/setup.py b/src/azure-cli/setup.py
index 331db8c41..6a59bb8be 100644
--- a/src/azure-cli/setup.py
+++ b/src/azure-cli/setup.py
@@ -54,11 +54,13 @@ DEPENDENCIES = [
     'azure-cli-acs',
     'azure-cli-appservice',
     'azure-cli-batch',
+    'azure-cli-billing',
     'azure-cli-cdn',
     'azure-cli-cloud',
     'azure-cli-cognitiveservices',
     'azure-cli-component',
     'azure-cli-configure',
+    'azure-cli-consumption',
     'azure-cli-core',
     'azure-cli-dla',
     'azure-cli-dls',
diff --git a/src/command_modules/azure-cli-resource/azure/cli/command_modules/resource/_validators.py b/src/command_modules/azure-cli-resource/azure/cli/command_modules/resource/_validators.py
index f2436813e..4348e2b7b 100644
--- a/src/command_modules/azure-cli-resource/azure/cli/command_modules/resource/_validators.py
+++ b/src/command_modules/azure-cli-resource/azure/cli/command_modules/resource/_validators.py
@@ -64,8 +64,8 @@ def internal_validate_lock_parameters(resource_group_name, resource_provider_nam
 
 
 def validate_lock_parameters(namespace):
-    internal_validate_lock_parameters(namespace.get('resource_group_name', None),
-                                      namespace.get('resource_provider_namespace', None),
-                                      namespace.get('parent_resource_path', None),
-                                      namespace.get('resource_type', None),
-                                      namespace.get('resource_name', None))
+    internal_validate_lock_parameters(getattr(namespace, 'resource_group_name', None),
+                                      getattr(namespace, 'resource_provider_namespace', None),
+                                      getattr(namespace, 'parent_resource_path', None),
+                                      getattr(namespace, 'resource_type', None),
+                                      getattr(namespace, 'resource_name', None))
diff --git a/src/command_modules/azure-cli-vm/azure/cli/command_modules/vm/custom.py b/src/command_modules/azure-cli-vm/azure/cli/command_modules/vm/custom.py
index f92f94630..39896c05e 100644
--- a/src/command_modules/azure-cli-vm/azure/cli/command_modules/vm/custom.py
+++ b/src/command_modules/azure-cli-vm/azure/cli/command_modules/vm/custom.py
@@ -292,7 +292,9 @@ def create_managed_disk(resource_group_name, disk_name, location=None,
                         # below are generated internally from 'source'
                         source_blob_uri=None, source_disk=None, source_snapshot=None,
                         source_storage_account_id=None, no_wait=False, tags=None):
-    from azure.mgmt.compute.models import Disk, CreationData, DiskCreateOption
+    Disk, CreationData, DiskCreateOption = get_sdk(ResourceType.MGMT_COMPUTE, 'Disk', 'CreationData',
+                                                   'DiskCreateOption', mod='models')
+
     location = location or get_resource_group_location(resource_group_name)
     if source_blob_uri:
         option = DiskCreateOption.import_enum
@@ -402,7 +404,8 @@ def create_snapshot(resource_group_name, snapshot_name, location=None, size_gb=N
                     # below are generated internally from 'source'
                     source_blob_uri=None, source_disk=None, source_snapshot=None, source_storage_account_id=None,
                     tags=None):
-    from azure.mgmt.compute.models import Snapshot, CreationData, DiskCreateOption
+    Snapshot, CreationData, DiskCreateOption = get_sdk(ResourceType.MGMT_COMPUTE, 'Snapshot', 'CreationData',
+                                                       'DiskCreateOption', mod='models')
 
     location = location or get_resource_group_location(resource_group_name)
     if source_blob_uri:
@@ -474,8 +477,10 @@ def create_image(resource_group_name, name, os_type=None, location=None,  # pyli
                  os_blob_uri=None, data_blob_uris=None,
                  os_snapshot=None, data_snapshots=None,
                  os_disk=None, data_disks=None, tags=None):
-    from azure.mgmt.compute.models import (ImageOSDisk, ImageDataDisk, ImageStorageProfile, Image, SubResource,
-                                           OperatingSystemStateTypes)
+    ImageOSDisk, ImageDataDisk, ImageStorageProfile, Image, SubResource, OperatingSystemStateTypes = get_sdk(
+        ResourceType.MGMT_COMPUTE, 'ImageOSDisk', 'ImageDataDisk', 'ImageStorageProfile', 'Image', 'SubResource',
+        'OperatingSystemStateTypes', mod='models')
+
     # pylint: disable=line-too-long
     if source_virtual_machine:
         location = location or get_resource_group_location(resource_group_name)

[Lock] az create lock Fails
### Description
Creating locks fails with:
```
az lock create: error: 'Namespace' object has no attribute 'get'
```

---

### Environment summary

**Install Method:** How did you install the CLI? (e.g. pip, interactive script, apt-get, Docker, MSI, nightly)  
Answer here: `pip3`

**CLI Version:** What version of the CLI and modules are installed? (Use `az --version`)  
Answer here:
```
azure-cli (2.0.6)

acr (2.0.4)
acs (2.0.6)
appservice (0.1.6)
batch (2.0.4)
cdn (0.0.2)
cloud (2.0.2)
cognitiveservices (0.1.2)
command-modules-nspkg (2.0.0)
component (2.0.4)
configure (2.0.6)
core (2.0.6)
cosmosdb (0.1.6)
dla (0.0.6)
dls (0.0.6)
feedback (2.0.2)
find (0.2.2)
interactive (0.3.1)
iot (0.1.5)
keyvault (2.0.4)
lab (0.0.4)
monitor (0.0.4)
network (2.0.6)
nspkg (3.0.0)
profile (2.0.4)
rdbms (0.0.1)
redis (0.2.3)
resource (2.0.6)
role (2.0.4)
sf (1.0.1)
sql (2.0.3)
storage (2.0.6)
vm (2.0.6)

Python (Linux) 3.6.1 (default, Mar 27 2017, 00:27:06)
[GCC 6.3.1 20170306] 
```

**OS Version:** What OS and version are you using?  
Answer here: Arch Linux, kernel 4.10.8. But was tested in Ubuntu 17.04 container and it also fails.

**Shell Type:** What shell are you using? (e.g. bash, cmd.exe, Bash on Windows)  
Answer here: `bash` and `nash`. Both fails.


diff --git a/src/command_modules/azure-cli-resource/tests/recordings/test_list_locks.yaml b/src/command_modules/azure-cli-resource/tests/recordings/test_list_locks.yaml
new file mode 100644
index 000000000..b43592289
--- /dev/null
+++ b/src/command_modules/azure-cli-resource/tests/recordings/test_list_locks.yaml
@@ -0,0 +1,28 @@
+interactions:
+- request:
+    body: null
+    headers:
+      Accept: [application/json]
+      Accept-Encoding: ['gzip, deflate']
+      CommandName: [lock list]
+      Connection: [keep-alive]
+      Content-Type: [application/json; charset=utf-8]
+      User-Agent: [python/3.5.3 (Windows-10-10.0.15063-SP0) requests/2.9.1 msrest/0.4.7
+          msrest_azure/0.4.7 managementlockclient/1.1.0rc1 Azure-SDK-For-Python AZURECLI/2.0.6+dev]
+      accept-language: [en-US]
+    method: GET
+    uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/locks?api-version=2016-09-01
+  response:
+    body: {string: '{"value":[]}'}
+    headers:
+      cache-control: [no-cache]
+      content-length: ['12']
+      content-type: [application/json; charset=utf-8]
+      date: ['Fri, 19 May 2017 23:27:30 GMT']
+      expires: ['-1']
+      pragma: [no-cache]
+      strict-transport-security: [max-age=31536000; includeSubDomains]
+      transfer-encoding: [chunked]
+      vary: ['Accept-Encoding,Accept-Encoding']
+    status: {code: 200, message: OK}
+version: 1
diff --git a/src/command_modules/azure-cli-resource/tests/recordings/test_lock_create_list_delete.yaml b/src/command_modules/azure-cli-resource/tests/recordings/test_lock_create_list_delete.yaml
new file mode 100644
index 000000000..60cb34dd2
--- /dev/null
+++ b/src/command_modules/azure-cli-resource/tests/recordings/test_lock_create_list_delete.yaml
@@ -0,0 +1,260 @@
+interactions:
+- request:
+    body: '{"name": "foo", "properties": {"level": "ReadOnly"}}'
+    headers:
+      Accept: [application/json]
+      Accept-Encoding: ['gzip, deflate']
+      CommandName: [lock create]
+      Connection: [keep-alive]
+      Content-Length: ['52']
+      Content-Type: [application/json; charset=utf-8]
+      User-Agent: [python/3.5.3 (Windows-10-10.0.15063-SP0) requests/2.9.1 msrest/0.4.7
+          msrest_azure/0.4.7 managementlockclient/1.1.0rc1 Azure-SDK-For-Python AZURECLI/2.0.6+dev]
+      accept-language: [en-US]
+    method: PUT
+    uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/locks/foo?api-version=2016-09-01
+  response:
+    body: {string: '{"properties":{"level":"ReadOnly"},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/locks/foo","type":"Microsoft.Authorization/locks","name":"foo"}'}
+    headers:
+      cache-control: [no-cache]
+      content-length: ['190']
+      content-type: [application/json; charset=utf-8]
+      date: ['Fri, 19 May 2017 23:38:22 GMT']
+      expires: ['-1']
+      pragma: [no-cache]
+      strict-transport-security: [max-age=31536000; includeSubDomains]
+      x-ms-ratelimit-remaining-subscription-writes: ['1198']
+    status: {code: 201, message: Created}
+- request:
+    body: null
+    headers:
+      Accept: [application/json]
+      Accept-Encoding: ['gzip, deflate']
+      CommandName: [lock list]
+      Connection: [keep-alive]
+      Content-Type: [application/json; charset=utf-8]
+      User-Agent: [python/3.5.3 (Windows-10-10.0.15063-SP0) requests/2.9.1 msrest/0.4.7
+          msrest_azure/0.4.7 managementlockclient/1.1.0rc1 Azure-SDK-For-Python AZURECLI/2.0.6+dev]
+      accept-language: [en-US]
+    method: GET
+    uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/locks?api-version=2016-09-01
+  response:
+    body: {string: '{"value":[{"properties":{"level":"ReadOnly"},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/locks/foo","type":"Microsoft.Authorization/locks","name":"foo"}]}'}
+    headers:
+      cache-control: [no-cache]
+      content-length: ['202']
+      content-type: [application/json; charset=utf-8]
+      date: ['Fri, 19 May 2017 23:38:23 GMT']
+      expires: ['-1']
+      pragma: [no-cache]
+      strict-transport-security: [max-age=31536000; includeSubDomains]
+      transfer-encoding: [chunked]
+      vary: ['Accept-Encoding,Accept-Encoding']
+    status: {code: 200, message: OK}
+- request:
+    body: null
+    headers:
+      Accept: [application/json]
+      Accept-Encoding: ['gzip, deflate']
+      CommandName: [lock show]
+      Connection: [keep-alive]
+      Content-Type: [application/json; charset=utf-8]
+      User-Agent: [python/3.5.3 (Windows-10-10.0.15063-SP0) requests/2.9.1 msrest/0.4.7
+          msrest_azure/0.4.7 managementlockclient/1.1.0rc1 Azure-SDK-For-Python AZURECLI/2.0.6+dev]
+      accept-language: [en-US]
+    method: GET
+    uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/locks/foo?api-version=2016-09-01
+  response:
+    body: {string: '{"properties":{"level":"ReadOnly"},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/locks/foo","type":"Microsoft.Authorization/locks","name":"foo"}'}
+    headers:
+      cache-control: [no-cache]
+      content-length: ['190']
+      content-type: [application/json; charset=utf-8]
+      date: ['Fri, 19 May 2017 23:38:23 GMT']
+      expires: ['-1']
+      pragma: [no-cache]
+      strict-transport-security: [max-age=31536000; includeSubDomains]
+      transfer-encoding: [chunked]
+      vary: ['Accept-Encoding,Accept-Encoding']
+    status: {code: 200, message: OK}
+- request:
+    body: null
+    headers:
+      Accept: [application/json]
+      Accept-Encoding: ['gzip, deflate']
+      CommandName: [lock delete]
+      Connection: [keep-alive]
+      Content-Type: [application/json; charset=utf-8]
+      User-Agent: [python/3.5.3 (Windows-10-10.0.15063-SP0) requests/2.9.1 msrest/0.4.7
+          msrest_azure/0.4.7 managementlockclient/1.1.0rc1 Azure-SDK-For-Python AZURECLI/2.0.6+dev]
+      accept-language: [en-US]
+    method: GET
+    uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/locks?api-version=2016-09-01
+  response:
+    body: {string: '{"value":[{"properties":{"level":"ReadOnly"},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/locks/foo","type":"Microsoft.Authorization/locks","name":"foo"}]}'}
+    headers:
+      cache-control: [no-cache]
+      content-length: ['202']
+      content-type: [application/json; charset=utf-8]
+      date: ['Fri, 19 May 2017 23:38:24 GMT']
+      expires: ['-1']
+      pragma: [no-cache]
+      strict-transport-security: [max-age=31536000; includeSubDomains]
+      transfer-encoding: [chunked]
+      vary: ['Accept-Encoding,Accept-Encoding']
+    status: {code: 200, message: OK}
+- request:
+    body: null
+    headers:
+      Accept: [application/json]
+      Accept-Encoding: ['gzip, deflate']
+      CommandName: [lock delete]
+      Connection: [keep-alive]
+      Content-Length: ['0']
+      Content-Type: [application/json; charset=utf-8]
+      User-Agent: [python/3.5.3 (Windows-10-10.0.15063-SP0) requests/2.9.1 msrest/0.4.7
+          msrest_azure/0.4.7 managementlockclient/1.1.0rc1 Azure-SDK-For-Python AZURECLI/2.0.6+dev]
+      accept-language: [en-US]
+    method: DELETE
+    uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/locks/foo?api-version=2016-09-01
+  response:
+    body: {string: ''}
+    headers:
+      cache-control: [no-cache]
+      content-length: ['0']
+      date: ['Fri, 19 May 2017 23:38:25 GMT']
+      expires: ['-1']
+      pragma: [no-cache]
+      strict-transport-security: [max-age=31536000; includeSubDomains]
+      x-ms-ratelimit-remaining-subscription-writes: ['1198']
+    status: {code: 200, message: OK}
+- request:
+    body: '{"name": "foo", "properties": {"level": "CanNotDelete"}}'
+    headers:
+      Accept: [application/json]
+      Accept-Encoding: ['gzip, deflate']
+      CommandName: [lock create]
+      Connection: [keep-alive]
+      Content-Length: ['56']
+      Content-Type: [application/json; charset=utf-8]
+      User-Agent: [python/3.5.3 (Windows-10-10.0.15063-SP0) requests/2.9.1 msrest/0.4.7
+          msrest_azure/0.4.7 managementlockclient/1.1.0rc1 Azure-SDK-For-Python AZURECLI/2.0.6+dev]
+      accept-language: [en-US]
+    method: PUT
+    uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/locks/foo?api-version=2016-09-01
+  response:
+    body: {string: '{"properties":{"level":"CanNotDelete"},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/locks/foo","type":"Microsoft.Authorization/locks","name":"foo"}'}
+    headers:
+      cache-control: [no-cache]
+      content-length: ['194']
+      content-type: [application/json; charset=utf-8]
+      date: ['Fri, 19 May 2017 23:38:26 GMT']
+      expires: ['-1']
+      pragma: [no-cache]
+      strict-transport-security: [max-age=31536000; includeSubDomains]
+      x-ms-ratelimit-remaining-subscription-writes: ['1198']
+    status: {code: 201, message: Created}
+- request:
+    body: null
+    headers:
+      Accept: [application/json]
+      Accept-Encoding: ['gzip, deflate']
+      CommandName: [lock list]
+      Connection: [keep-alive]
+      Content-Type: [application/json; charset=utf-8]
+      User-Agent: [python/3.5.3 (Windows-10-10.0.15063-SP0) requests/2.9.1 msrest/0.4.7
+          msrest_azure/0.4.7 managementlockclient/1.1.0rc1 Azure-SDK-For-Python AZURECLI/2.0.6+dev]
+      accept-language: [en-US]
+    method: GET
+    uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/locks?api-version=2016-09-01
+  response:
+    body: {string: '{"value":[{"properties":{"level":"CanNotDelete"},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/locks/foo","type":"Microsoft.Authorization/locks","name":"foo"}]}'}
+    headers:
+      cache-control: [no-cache]
+      content-length: ['206']
+      content-type: [application/json; charset=utf-8]
+      date: ['Fri, 19 May 2017 23:38:27 GMT']
+      expires: ['-1']
+      pragma: [no-cache]
+      strict-transport-security: [max-age=31536000; includeSubDomains]
+      transfer-encoding: [chunked]
+      vary: ['Accept-Encoding,Accept-Encoding']
+    status: {code: 200, message: OK}
+- request:
+    body: null
+    headers:
+      Accept: [application/json]
+      Accept-Encoding: ['gzip, deflate']
+      CommandName: [lock show]
+      Connection: [keep-alive]
+      Content-Type: [application/json; charset=utf-8]
+      User-Agent: [python/3.5.3 (Windows-10-10.0.15063-SP0) requests/2.9.1 msrest/0.4.7
+          msrest_azure/0.4.7 managementlockclient/1.1.0rc1 Azure-SDK-For-Python AZURECLI/2.0.6+dev]
+      accept-language: [en-US]
+    method: GET
+    uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/locks/foo?api-version=2016-09-01
+  response:
+    body: {string: '{"properties":{"level":"CanNotDelete"},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/locks/foo","type":"Microsoft.Authorization/locks","name":"foo"}'}
+    headers:
+      cache-control: [no-cache]
+      content-length: ['194']
+      content-type: [application/json; charset=utf-8]
+      date: ['Fri, 19 May 2017 23:38:28 GMT']
+      expires: ['-1']
+      pragma: [no-cache]
+      strict-transport-security: [max-age=31536000; includeSubDomains]
+      transfer-encoding: [chunked]
+      vary: ['Accept-Encoding,Accept-Encoding']
+    status: {code: 200, message: OK}
+- request:
+    body: null
+    headers:
+      Accept: [application/json]
+      Accept-Encoding: ['gzip, deflate']
+      CommandName: [lock delete]
+      Connection: [keep-alive]
+      Content-Type: [application/json; charset=utf-8]
+      User-Agent: [python/3.5.3 (Windows-10-10.0.15063-SP0) requests/2.9.1 msrest/0.4.7
+          msrest_azure/0.4.7 managementlockclient/1.1.0rc1 Azure-SDK-For-Python AZURECLI/2.0.6+dev]
+      accept-language: [en-US]
+    method: GET
+    uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/locks?api-version=2016-09-01
+  response:
+    body: {string: '{"value":[{"properties":{"level":"CanNotDelete"},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/locks/foo","type":"Microsoft.Authorization/locks","name":"foo"}]}'}
+    headers:
+      cache-control: [no-cache]
+      content-length: ['206']
+      content-type: [application/json; charset=utf-8]
+      date: ['Fri, 19 May 2017 23:38:30 GMT']
+      expires: ['-1']
+      pragma: [no-cache]
+      strict-transport-security: [max-age=31536000; includeSubDomains]
+      transfer-encoding: [chunked]
+      vary: ['Accept-Encoding,Accept-Encoding']
+    status: {code: 200, message: OK}
+- request:
+    body: null
+    headers:
+      Accept: [application/json]
+      Accept-Encoding: ['gzip, deflate']
+      CommandName: [lock delete]
+      Connection: [keep-alive]
+      Content-Length: ['0']
+      Content-Type: [application/json; charset=utf-8]
+      User-Agent: [python/3.5.3 (Windows-10-10.0.15063-SP0) requests/2.9.1 msrest/0.4.7
+          msrest_azure/0.4.7 managementlockclient/1.1.0rc1 Azure-SDK-For-Python AZURECLI/2.0.6+dev]
+      accept-language: [en-US]
+    method: DELETE
+    uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/locks/foo?api-version=2016-09-01
+  response:
+    body: {string: ''}
+    headers:
+      cache-control: [no-cache]
+      content-length: ['0']
+      date: ['Fri, 19 May 2017 23:38:30 GMT']
+      expires: ['-1']
+      pragma: [no-cache]
+      strict-transport-security: [max-age=31536000; includeSubDomains]
+      x-ms-ratelimit-remaining-subscription-writes: ['1196']
+    status: {code: 200, message: OK}
+version: 1
diff --git a/src/command_modules/azure-cli-resource/tests/recordings/test_lock_create_list_delete_resource_group.yaml b/src/command_modules/azure-cli-resource/tests/recordings/test_lock_create_list_delete_resource_group.yaml
new file mode 100644
index 000000000..d3cd445b4
--- /dev/null
+++ b/src/command_modules/azure-cli-resource/tests/recordings/test_lock_create_list_delete_resource_group.yaml
@@ -0,0 +1,315 @@
+interactions:
+- request:
+    body: '{"tags": {"use": "az-test"}, "location": "westus"}'
+    headers:
+      Accept: [application/json]
+      Accept-Encoding: ['gzip, deflate']
+      CommandName: [group create]
+      Connection: [keep-alive]
+      Content-Length: ['50']
+      Content-Type: [application/json; charset=utf-8]
+      User-Agent: [python/3.5.3 (Windows-10-10.0.15063-SP0) requests/2.9.1 msrest/0.4.7
+          msrest_azure/0.4.7 resourcemanagementclient/1.1.0rc1 Azure-SDK-For-Python
+          AZURECLI/2.0.6+dev]
+      accept-language: [en-US]
+    method: PUT
+    uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001?api-version=2017-05-10
+  response:
+    body: {string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001","name":"clitest.rg000001","location":"westus","tags":{"use":"az-test"},"properties":{"provisioningState":"Succeeded"}}'}
+    headers:
+      cache-control: [no-cache]
+      content-length: ['328']
+      content-type: [application/json; charset=utf-8]
+      date: ['Fri, 19 May 2017 23:42:41 GMT']
+      expires: ['-1']
+      pragma: [no-cache]
+      strict-transport-security: [max-age=31536000; includeSubDomains]
+      x-ms-ratelimit-remaining-subscription-writes: ['1187']
+    status: {code: 201, message: Created}
+- request:
+    body: '{"properties": {"level": "ReadOnly"}, "name": "foo"}'
+    headers:
+      Accept: [application/json]
+      Accept-Encoding: ['gzip, deflate']
+      CommandName: [lock create]
+      Connection: [keep-alive]
+      Content-Length: ['52']
+      Content-Type: [application/json; charset=utf-8]
+      User-Agent: [python/3.5.3 (Windows-10-10.0.15063-SP0) requests/2.9.1 msrest/0.4.7
+          msrest_azure/0.4.7 managementlockclient/1.1.0rc1 Azure-SDK-For-Python AZURECLI/2.0.6+dev]
+      accept-language: [en-US]
+    method: PUT
+    uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.Authorization/locks/foo?api-version=2016-09-01
+  response:
+    body: {string: '{"properties":{"level":"ReadOnly"},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.Authorization/locks/foo","type":"Microsoft.Authorization/locks","name":"foo"}'}
+    headers:
+      cache-control: [no-cache]
+      content-length: ['281']
+      content-type: [application/json; charset=utf-8]
+      date: ['Fri, 19 May 2017 23:42:43 GMT']
+      expires: ['-1']
+      pragma: [no-cache]
+      strict-transport-security: [max-age=31536000; includeSubDomains]
+      x-ms-ratelimit-remaining-subscription-writes: ['1189']
+    status: {code: 201, message: Created}
+- request:
+    body: null
+    headers:
+      Accept: [application/json]
+      Accept-Encoding: ['gzip, deflate']
+      CommandName: [lock list]
+      Connection: [keep-alive]
+      Content-Type: [application/json; charset=utf-8]
+      User-Agent: [python/3.5.3 (Windows-10-10.0.15063-SP0) requests/2.9.1 msrest/0.4.7
+          msrest_azure/0.4.7 managementlockclient/1.1.0rc1 Azure-SDK-For-Python AZURECLI/2.0.6+dev]
+      accept-language: [en-US]
+    method: GET
+    uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/locks?api-version=2016-09-01
+  response:
+    body: {string: '{"value":[{"properties":{"level":"ReadOnly"},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg6hms5bk4lei5ddclway74mxxuyl46kfsfuygwco5al3eh7ousyhogw676rbllwli3/providers/Microsoft.Authorization/locks/foo","type":"Microsoft.Authorization/locks","name":"foo"},{"properties":{"level":"ReadOnly"},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.Authorization/locks/foo","type":"Microsoft.Authorization/locks","name":"foo"}]}'}
+    headers:
+      cache-control: [no-cache]
+      content-length: ['575']
+      content-type: [application/json; charset=utf-8]
+      date: ['Fri, 19 May 2017 23:42:46 GMT']
+      expires: ['-1']
+      pragma: [no-cache]
+      strict-transport-security: [max-age=31536000; includeSubDomains]
+      transfer-encoding: [chunked]
+      vary: ['Accept-Encoding,Accept-Encoding']
+    status: {code: 200, message: OK}
+- request:
+    body: null
+    headers:
+      Accept: [application/json]
+      Accept-Encoding: ['gzip, deflate']
+      CommandName: [lock show]
+      Connection: [keep-alive]
+      Content-Type: [application/json; charset=utf-8]
+      User-Agent: [python/3.5.3 (Windows-10-10.0.15063-SP0) requests/2.9.1 msrest/0.4.7
+          msrest_azure/0.4.7 managementlockclient/1.1.0rc1 Azure-SDK-For-Python AZURECLI/2.0.6+dev]
+      accept-language: [en-US]
+    method: GET
+    uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.Authorization/locks/foo?api-version=2016-09-01
+  response:
+    body: {string: '{"properties":{"level":"ReadOnly"},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.Authorization/locks/foo","type":"Microsoft.Authorization/locks","name":"foo"}'}
+    headers:
+      cache-control: [no-cache]
+      content-length: ['281']
+      content-type: [application/json; charset=utf-8]
+      date: ['Fri, 19 May 2017 23:42:53 GMT']
+      expires: ['-1']
+      pragma: [no-cache]
+      strict-transport-security: [max-age=31536000; includeSubDomains]
+      transfer-encoding: [chunked]
+      vary: ['Accept-Encoding,Accept-Encoding']
+    status: {code: 200, message: OK}
+- request:
+    body: null
+    headers:
+      Accept: [application/json]
+      Accept-Encoding: ['gzip, deflate']
+      CommandName: [lock delete]
+      Connection: [keep-alive]
+      Content-Type: [application/json; charset=utf-8]
+      User-Agent: [python/3.5.3 (Windows-10-10.0.15063-SP0) requests/2.9.1 msrest/0.4.7
+          msrest_azure/0.4.7 managementlockclient/1.1.0rc1 Azure-SDK-For-Python AZURECLI/2.0.6+dev]
+      accept-language: [en-US]
+    method: GET
+    uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/locks?api-version=2016-09-01
+  response:
+    body: {string: '{"value":[{"properties":{"level":"ReadOnly"},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg6hms5bk4lei5ddclway74mxxuyl46kfsfuygwco5al3eh7ousyhogw676rbllwli3/providers/Microsoft.Authorization/locks/foo","type":"Microsoft.Authorization/locks","name":"foo"},{"properties":{"level":"ReadOnly"},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.Authorization/locks/foo","type":"Microsoft.Authorization/locks","name":"foo"}]}'}
+    headers:
+      cache-control: [no-cache]
+      content-length: ['575']
+      content-type: [application/json; charset=utf-8]
+      date: ['Fri, 19 May 2017 23:43:05 GMT']
+      expires: ['-1']
+      pragma: [no-cache]
+      strict-transport-security: [max-age=31536000; includeSubDomains]
+      transfer-encoding: [chunked]
+      vary: ['Accept-Encoding,Accept-Encoding']
+    status: {code: 200, message: OK}
+- request:
+    body: null
+    headers:
+      Accept: [application/json]
+      Accept-Encoding: ['gzip, deflate']
+      CommandName: [lock delete]
+      Connection: [keep-alive]
+      Content-Length: ['0']
+      Content-Type: [application/json; charset=utf-8]
+      User-Agent: [python/3.5.3 (Windows-10-10.0.15063-SP0) requests/2.9.1 msrest/0.4.7
+          msrest_azure/0.4.7 managementlockclient/1.1.0rc1 Azure-SDK-For-Python AZURECLI/2.0.6+dev]
+      accept-language: [en-US]
+    method: DELETE
+    uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.Authorization/locks/foo?api-version=2016-09-01
+  response:
+    body: {string: ''}
+    headers:
+      cache-control: [no-cache]
+      content-length: ['0']
+      date: ['Fri, 19 May 2017 23:43:07 GMT']
+      expires: ['-1']
+      pragma: [no-cache]
+      strict-transport-security: [max-age=31536000; includeSubDomains]
+      x-ms-ratelimit-remaining-subscription-writes: ['1198']
+    status: {code: 200, message: OK}
+- request:
+    body: '{"properties": {"level": "CanNotDelete"}, "name": "foo"}'
+    headers:
+      Accept: [application/json]
+      Accept-Encoding: ['gzip, deflate']
+      CommandName: [lock create]
+      Connection: [keep-alive]
+      Content-Length: ['56']
+      Content-Type: [application/json; charset=utf-8]
+      User-Agent: [python/3.5.3 (Windows-10-10.0.15063-SP0) requests/2.9.1 msrest/0.4.7
+          msrest_azure/0.4.7 managementlockclient/1.1.0rc1 Azure-SDK-For-Python AZURECLI/2.0.6+dev]
+      accept-language: [en-US]
+    method: PUT
+    uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.Authorization/locks/foo?api-version=2016-09-01
+  response:
+    body: {string: '{"properties":{"level":"CanNotDelete"},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.Authorization/locks/foo","type":"Microsoft.Authorization/locks","name":"foo"}'}
+    headers:
+      cache-control: [no-cache]
+      content-length: ['285']
+      content-type: [application/json; charset=utf-8]
+      date: ['Fri, 19 May 2017 23:43:08 GMT']
+      expires: ['-1']
+      pragma: [no-cache]
+      strict-transport-security: [max-age=31536000; includeSubDomains]
+      x-ms-ratelimit-remaining-subscription-writes: ['1198']
+    status: {code: 201, message: Created}
+- request:
+    body: null
+    headers:
+      Accept: [application/json]
+      Accept-Encoding: ['gzip, deflate']
+      CommandName: [lock list]
+      Connection: [keep-alive]
+      Content-Type: [application/json; charset=utf-8]
+      User-Agent: [python/3.5.3 (Windows-10-10.0.15063-SP0) requests/2.9.1 msrest/0.4.7
+          msrest_azure/0.4.7 managementlockclient/1.1.0rc1 Azure-SDK-For-Python AZURECLI/2.0.6+dev]
+      accept-language: [en-US]
+    method: GET
+    uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/locks?api-version=2016-09-01
+  response:
+    body: {string: '{"value":[{"properties":{"level":"ReadOnly"},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg6hms5bk4lei5ddclway74mxxuyl46kfsfuygwco5al3eh7ousyhogw676rbllwli3/providers/Microsoft.Authorization/locks/foo","type":"Microsoft.Authorization/locks","name":"foo"},{"properties":{"level":"CanNotDelete"},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.Authorization/locks/foo","type":"Microsoft.Authorization/locks","name":"foo"}]}'}
+    headers:
+      cache-control: [no-cache]
+      content-length: ['579']
+      content-type: [application/json; charset=utf-8]
+      date: ['Fri, 19 May 2017 23:43:09 GMT']
+      expires: ['-1']
+      pragma: [no-cache]
+      strict-transport-security: [max-age=31536000; includeSubDomains]
+      transfer-encoding: [chunked]
+      vary: ['Accept-Encoding,Accept-Encoding']
+    status: {code: 200, message: OK}
+- request:
+    body: null
+    headers:
+      Accept: [application/json]
+      Accept-Encoding: ['gzip, deflate']
+      CommandName: [lock show]
+      Connection: [keep-alive]
+      Content-Type: [application/json; charset=utf-8]
+      User-Agent: [python/3.5.3 (Windows-10-10.0.15063-SP0) requests/2.9.1 msrest/0.4.7
+          msrest_azure/0.4.7 managementlockclient/1.1.0rc1 Azure-SDK-For-Python AZURECLI/2.0.6+dev]
+      accept-language: [en-US]
+    method: GET
+    uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.Authorization/locks/foo?api-version=2016-09-01
+  response:
+    body: {string: '{"properties":{"level":"CanNotDelete"},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.Authorization/locks/foo","type":"Microsoft.Authorization/locks","name":"foo"}'}
+    headers:
+      cache-control: [no-cache]
+      content-length: ['285']
+      content-type: [application/json; charset=utf-8]
+      date: ['Fri, 19 May 2017 23:43:11 GMT']
+      expires: ['-1']
+      pragma: [no-cache]
+      strict-transport-security: [max-age=31536000; includeSubDomains]
+      transfer-encoding: [chunked]
+      vary: ['Accept-Encoding,Accept-Encoding']
+    status: {code: 200, message: OK}
+- request:
+    body: null
+    headers:
+      Accept: [application/json]
+      Accept-Encoding: ['gzip, deflate']
+      CommandName: [lock delete]
+      Connection: [keep-alive]
+      Content-Type: [application/json; charset=utf-8]
+      User-Agent: [python/3.5.3 (Windows-10-10.0.15063-SP0) requests/2.9.1 msrest/0.4.7
+          msrest_azure/0.4.7 managementlockclient/1.1.0rc1 Azure-SDK-For-Python AZURECLI/2.0.6+dev]
+      accept-language: [en-US]
+    method: GET
+    uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/locks?api-version=2016-09-01
+  response:
+    body: {string: '{"value":[{"properties":{"level":"ReadOnly"},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg6hms5bk4lei5ddclway74mxxuyl46kfsfuygwco5al3eh7ousyhogw676rbllwli3/providers/Microsoft.Authorization/locks/foo","type":"Microsoft.Authorization/locks","name":"foo"},{"properties":{"level":"CanNotDelete"},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.Authorization/locks/foo","type":"Microsoft.Authorization/locks","name":"foo"}]}'}
+    headers:
+      cache-control: [no-cache]
+      content-length: ['579']
+      content-type: [application/json; charset=utf-8]
+      date: ['Fri, 19 May 2017 23:43:12 GMT']
+      expires: ['-1']
+      pragma: [no-cache]
+      strict-transport-security: [max-age=31536000; includeSubDomains]
+      transfer-encoding: [chunked]
+      vary: ['Accept-Encoding,Accept-Encoding']
+    status: {code: 200, message: OK}
+- request:
+    body: null
+    headers:
+      Accept: [application/json]
+      Accept-Encoding: ['gzip, deflate']
+      CommandName: [lock delete]
+      Connection: [keep-alive]
+      Content-Length: ['0']
+      Content-Type: [application/json; charset=utf-8]
+      User-Agent: [python/3.5.3 (Windows-10-10.0.15063-SP0) requests/2.9.1 msrest/0.4.7
+          msrest_azure/0.4.7 managementlockclient/1.1.0rc1 Azure-SDK-For-Python AZURECLI/2.0.6+dev]
+      accept-language: [en-US]
+    method: DELETE
+    uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.Authorization/locks/foo?api-version=2016-09-01
+  response:
+    body: {string: ''}
+    headers:
+      cache-control: [no-cache]
+      content-length: ['0']
+      date: ['Fri, 19 May 2017 23:43:13 GMT']
+      expires: ['-1']
+      pragma: [no-cache]
+      strict-transport-security: [max-age=31536000; includeSubDomains]
+      x-ms-ratelimit-remaining-subscription-writes: ['1188']
+    status: {code: 200, message: OK}
+- request:
+    body: null
+    headers:
+      Accept: [application/json]
+      Accept-Encoding: ['gzip, deflate']
+      CommandName: [group delete]
+      Connection: [keep-alive]
+      Content-Length: ['0']
+      Content-Type: [application/json; charset=utf-8]
+      User-Agent: [python/3.5.3 (Windows-10-10.0.15063-SP0) requests/2.9.1 msrest/0.4.7
+          msrest_azure/0.4.7 resourcemanagementclient/1.1.0rc1 Azure-SDK-For-Python
+          AZURECLI/2.0.6+dev]
+      accept-language: [en-US]
+    method: DELETE
+    uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001?api-version=2017-05-10
+  response:
+    body: {string: ''}
+    headers:
+      cache-control: [no-cache]
+      content-length: ['0']
+      date: ['Fri, 19 May 2017 23:43:15 GMT']
+      expires: ['-1']
+      location: ['https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1DTElURVNUOjJFUkdORlVXV05FUE4zVlQzRkJDSlc1UUwzQUVMTFE3Mk1TQ1JXQnwxMEFGMEY1QzVBMjE5M0FCLVdFU1RVUyIsImpvYkxvY2F0aW9uIjoid2VzdHVzIn0?api-version=2017-05-10']
+      pragma: [no-cache]
+      retry-after: ['15']
+      strict-transport-security: [max-age=31536000; includeSubDomains]
+      x-ms-ratelimit-remaining-subscription-writes: ['1196']
+    status: {code: 202, message: Accepted}
+version: 1
diff --git a/src/command_modules/azure-cli-resource/tests/test_locks.py b/src/command_modules/azure-cli-resource/tests/test_locks.py
new file mode 100644
index 000000000..fdee87239
--- /dev/null
+++ b/src/command_modules/azure-cli-resource/tests/test_locks.py
@@ -0,0 +1,45 @@
+# --------------------------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# --------------------------------------------------------------------------------------------
+
+import unittest
+
+from azure.cli.testsdk import ScenarioTest, ResourceGroupPreparer
+
+
+class ResourceLockTests(ScenarioTest):
+    def test_list_locks(self):
+        # just make sure this doesn't throw
+        self.cmd('az lock list').get_output_in_json()
+
+    # Test for subscription level locks
+    def test_lock_create_list_delete(self):
+        for lock_type in ['ReadOnly', 'CanNotDelete']:
+            self.cmd('az lock create -n foo --lock-type {}'.format(lock_type))
+            locks_list = self.cmd('az lock list').get_output_in_json()
+            assert len(locks_list) > 0
+            assert 'foo' in [l['name'] for l in locks_list]
+            lock = self.cmd('az lock show -n foo').get_output_in_json()
+            self.assertEqual(lock.get('name', None), 'foo')
+            self.assertEqual(lock.get('level', None), lock_type)
+            self.cmd('az lock delete -n foo')
+
+    # Test for resource group level locks
+    @ResourceGroupPreparer()
+    def test_lock_create_list_delete_resource_group(self, resource_group):
+        for lock_type in ['ReadOnly', 'CanNotDelete']:
+            self.cmd('az lock create -n foo -g {} --lock-type {}'.format(resource_group, lock_type))
+            locks_list = self.cmd('az lock list').get_output_in_json()
+            assert 'foo' in [l['name'] for l in locks_list]
+            assert len(locks_list) > 0
+            lock = self.cmd('az lock show -g {} -n foo'.format(resource_group)).get_output_in_json()
+            self.assertEqual(lock.get('name', None), 'foo')
+            self.assertEqual(lock.get('level', None), lock_type)
+            self.cmd('az lock delete -g {} -n foo'.format(resource_group))
+
+    # TODO: test for resource group level locks
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/src/command_modules/azure-cli-resource/tests/test_resource_validators.py b/src/command_modules/azure-cli-resource/tests/test_resource_validators.py
index ca533fd35..eea7b941b 100644
--- a/src/command_modules/azure-cli-resource/tests/test_resource_validators.py
+++ b/src/command_modules/azure-cli-resource/tests/test_resource_validators.py
@@ -4,8 +4,8 @@
 # --------------------------------------------------------------------------------------------
 
 import unittest
-import mock
 import os.path
+import mock
 from six import StringIO
 
 from azure.cli.core.util import CLIError
@@ -15,6 +15,10 @@ from azure.cli.command_modules.resource._validators import (
 )
 
 
+class NamespaceObject:
+    pass
+
+
 class Test_resource_validators(unittest.TestCase):
     def setUp(self):
         self.io = StringIO()
@@ -59,9 +63,12 @@ class Test_resource_validators(unittest.TestCase):
             }
         ]
         for valid_namespace in valid:
+            namespace_obj = NamespaceObject()
+            for key in valid_namespace:
+                setattr(namespace_obj, key, valid_namespace[key])
             try:
                 # If unexpected invalid, this throws, so no need for asserts
-                validate_lock_parameters(valid_namespace)
+                validate_lock_parameters(namespace_obj)
             except CLIError as ex:
                 self.fail('Test {} failed. {}'.format(valid_namespace['test'], ex))
 
@@ -102,7 +109,10 @@ class Test_resource_validators(unittest.TestCase):
         ]
         for invalid_namespace in invalid:
             with self.assertRaises(CLIError):
-                validate_lock_parameters(invalid_namespace)
+                namespace_obj = NamespaceObject()
+                for key in invalid_namespace:
+                    setattr(namespace_obj, key, invalid_namespace[key])
+                validate_lock_parameters(namespace_obj)
 
     def test_generate_deployment_name_from_file(self):
         # verify auto-gen from uri

python scripts/dev_setup.py
parse_log_pytest
requirements.txt
pytest
apt-get update apt-get install -y gcc
3.5
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
adal==0.4.3
applicationinsights==0.10.0
argcomplete==1.8.0
astroid==2.11.7
attrs==22.2.0
autopep8==1.2.4
azure-batch==3.0.0
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli&subdirectory=src/azure-cli
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_acr&subdirectory=src/command_modules/azure-cli-acr
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_acs&subdirectory=src/command_modules/azure-cli-acs
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_appservice&subdirectory=src/command_modules/azure-cli-appservice
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_batch&subdirectory=src/command_modules/azure-cli-batch
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_billing&subdirectory=src/command_modules/azure-cli-billing
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_cdn&subdirectory=src/command_modules/azure-cli-cdn
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_cloud&subdirectory=src/command_modules/azure-cli-cloud
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_cognitiveservices&subdirectory=src/command_modules/azure-cli-cognitiveservices
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_component&subdirectory=src/command_modules/azure-cli-component
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_configure&subdirectory=src/command_modules/azure-cli-configure
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_consumption&subdirectory=src/command_modules/azure-cli-consumption
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_core&subdirectory=src/azure-cli-core
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_cosmosdb&subdirectory=src/command_modules/azure-cli-cosmosdb
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_dla&subdirectory=src/command_modules/azure-cli-dla
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_dls&subdirectory=src/command_modules/azure-cli-dls
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_feedback&subdirectory=src/command_modules/azure-cli-feedback
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_find&subdirectory=src/command_modules/azure-cli-find
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_interactive&subdirectory=src/command_modules/azure-cli-interactive
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_iot&subdirectory=src/command_modules/azure-cli-iot
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_keyvault&subdirectory=src/command_modules/azure-cli-keyvault
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_lab&subdirectory=src/command_modules/azure-cli-lab
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_monitor&subdirectory=src/command_modules/azure-cli-monitor
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_network&subdirectory=src/command_modules/azure-cli-network
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_nspkg&subdirectory=src/azure-cli-nspkg
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_profile&subdirectory=src/command_modules/azure-cli-profile
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_rdbms&subdirectory=src/command_modules/azure-cli-rdbms
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_redis&subdirectory=src/command_modules/azure-cli-redis
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_resource&subdirectory=src/command_modules/azure-cli-resource
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_role&subdirectory=src/command_modules/azure-cli-role
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_sf&subdirectory=src/command_modules/azure-cli-sf
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_sql&subdirectory=src/command_modules/azure-cli-sql
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_storage&subdirectory=src/command_modules/azure-cli-storage
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_taskhelp&subdirectory=src/command_modules/azure-cli-taskhelp
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_testsdk&subdirectory=src/azure-cli-testsdk
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_utility_automation&subdirectory=scripts
-e git+https://github.com/Azure/azure-cli.git@40c111b3daa79c4cc326f09d47e60be5826ecccc#egg=azure_cli_vm&subdirectory=src/command_modules/azure-cli-vm
azure-common==1.1.28
azure-core==1.24.2
azure-datalake-store==0.0.9
azure-graphrbac==0.30.0rc6
azure-keyvault==0.3.0
azure-mgmt-authorization==0.30.0rc6
azure-mgmt-batch==4.0.0
azure-mgmt-billing==0.1.0
azure-mgmt-cdn==0.30.2
azure-mgmt-cognitiveservices==1.0.0
azure-mgmt-compute==1.0.0rc1
azure-mgmt-consumption==0.1.0
azure-mgmt-containerregistry==0.2.1
azure-mgmt-datalake-analytics==0.1.4
azure-mgmt-datalake-nspkg==3.0.1
azure-mgmt-datalake-store==0.1.4
azure-mgmt-devtestlabs==2.0.0
azure-mgmt-dns==1.0.1
azure-mgmt-documentdb==0.1.3
azure-mgmt-iothub==0.2.2
azure-mgmt-keyvault==0.31.0
azure-mgmt-monitor==0.2.1
azure-mgmt-network==1.0.0rc3
azure-mgmt-nspkg==1.0.0
azure-mgmt-rdbms==0.1.0
azure-mgmt-redis==1.0.0
azure-mgmt-resource==1.1.0rc1
azure-mgmt-sql==0.4.0
azure-mgmt-storage==1.0.0rc1
azure-mgmt-trafficmanager==0.30.0
azure-mgmt-web==0.32.0
azure-monitor==0.3.0
azure-multiapi-storage==0.1.0
azure-nspkg==1.0.0
azure-servicefabric==5.6.130
certifi==2021.5.30
cffi==1.15.1
colorama==0.3.7
coverage==4.2
cryptography==40.0.2
flake8==3.2.1
futures==3.1.1
humanfriendly==2.4
importlib-metadata==4.8.3
iniconfig==1.1.1
isodate==0.7.0
isort==5.10.1
jeepney==0.7.1
jmespath==0.10.0
keyring==23.4.1
lazy-object-proxy==1.7.1
mccabe==0.5.3
mock==1.3.0
msrest==0.4.29
msrestazure==0.4.34
nose==1.3.7
oauthlib==3.2.2
packaging==21.3
paramiko==2.0.2
pbr==6.1.1
pep8==1.7.1
pluggy==1.0.0
prompt-toolkit==3.0.36
py==1.11.0
pyasn1==0.5.1
pycodestyle==2.2.0
pycparser==2.21
pydocumentdb==2.3.5
pyflakes==1.3.0
Pygments==2.1.3
PyJWT==2.4.0
pylint==1.7.1
pyOpenSSL==16.2.0
pyparsing==3.1.4
pytest==7.0.1
python-dateutil==2.9.0.post0
pytz==2025.2
PyYAML==3.11
requests==2.9.1
requests-oauthlib==2.0.0
scp==0.15.0
SecretStorage==3.3.3
six==1.10.0
sshtunnel==0.4.0
tabulate==0.7.7
tomli==1.2.3
typed-ast==1.5.5
typing-extensions==4.1.1
urllib3==1.16
vcrpy==1.10.3
vsts-cd-manager==1.0.2
wcwidth==0.2.13
Whoosh==2.7.4
wrapt==1.16.0
xmltodict==0.14.2
zipp==3.6.0

name: azure-cli
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - adal==0.4.3
      - applicationinsights==0.10.0
      - argcomplete==1.8.0
      - astroid==2.11.7
      - attrs==22.2.0
      - autopep8==1.2.4
      - azure-batch==3.0.0
      - azure-common==1.1.28
      - azure-core==1.24.2
      - azure-datalake-store==0.0.9
      - azure-graphrbac==0.30.0rc6
      - azure-keyvault==0.3.0
      - azure-mgmt-authorization==0.30.0rc6
      - azure-mgmt-batch==4.0.0
      - azure-mgmt-billing==0.1.0
      - azure-mgmt-cdn==0.30.2
      - azure-mgmt-cognitiveservices==1.0.0
      - azure-mgmt-compute==1.0.0rc1
      - azure-mgmt-consumption==0.1.0
      - azure-mgmt-containerregistry==0.2.1
      - azure-mgmt-datalake-analytics==0.1.4
      - azure-mgmt-datalake-nspkg==3.0.1
      - azure-mgmt-datalake-store==0.1.4
      - azure-mgmt-devtestlabs==2.0.0
      - azure-mgmt-dns==1.0.1
      - azure-mgmt-documentdb==0.1.3
      - azure-mgmt-iothub==0.2.2
      - azure-mgmt-keyvault==0.31.0
      - azure-mgmt-monitor==0.2.1
      - azure-mgmt-network==1.0.0rc3
      - azure-mgmt-nspkg==1.0.0
      - azure-mgmt-rdbms==0.1.0
      - azure-mgmt-redis==1.0.0
      - azure-mgmt-resource==1.1.0rc1
      - azure-mgmt-sql==0.4.0
      - azure-mgmt-storage==1.0.0rc1
      - azure-mgmt-trafficmanager==0.30.0
      - azure-mgmt-web==0.32.0
      - azure-monitor==0.3.0
      - azure-multiapi-storage==0.1.0
      - azure-nspkg==1.0.0
      - azure-servicefabric==5.6.130
      - cffi==1.15.1
      - colorama==0.3.7
      - coverage==4.2
      - cryptography==40.0.2
      - flake8==3.2.1
      - futures==3.1.1
      - humanfriendly==2.4
      - importlib-metadata==4.8.3
      - iniconfig==1.1.1
      - isodate==0.7.0
      - isort==5.10.1
      - jeepney==0.7.1
      - jmespath==0.10.0
      - keyring==23.4.1
      - lazy-object-proxy==1.7.1
      - mccabe==0.5.3
      - mock==1.3.0
      - msrest==0.4.29
      - msrestazure==0.4.34
      - nose==1.3.7
      - oauthlib==3.2.2
      - packaging==21.3
      - paramiko==2.0.2
      - pbr==6.1.1
      - pep8==1.7.1
      - pip==9.0.1
      - pluggy==1.0.0
      - prompt-toolkit==3.0.36
      - py==1.11.0
      - pyasn1==0.5.1
      - pycodestyle==2.2.0
      - pycparser==2.21
      - pydocumentdb==2.3.5
      - pyflakes==1.3.0
      - pygments==2.1.3
      - pyjwt==2.4.0
      - pylint==1.7.1
      - pyopenssl==16.2.0
      - pyparsing==3.1.4
      - pytest==7.0.1
      - python-dateutil==2.9.0.post0
      - pytz==2025.2
      - pyyaml==3.11
      - requests==2.9.1
      - requests-oauthlib==2.0.0
      - scp==0.15.0
      - secretstorage==3.3.3
      - setuptools==30.4.0
      - six==1.10.0
      - sshtunnel==0.4.0
      - tabulate==0.7.7
      - tomli==1.2.3
      - typed-ast==1.5.5
      - typing-extensions==4.1.1
      - urllib3==1.16
      - vcrpy==1.10.3
      - vsts-cd-manager==1.0.2
      - wcwidth==0.2.13
      - whoosh==2.7.4
      - wrapt==1.16.0
      - xmltodict==0.14.2
      - zipp==3.6.0
prefix: /opt/conda/envs/azure-cli

src/command_modules/azure-cli-resource/tests/test_locks.py::ResourceLockTests::test_lock_create_list_delete src/command_modules/azure-cli-resource/tests/test_locks.py::ResourceLockTests::test_lock_create_list_delete_resource_group src/command_modules/azure-cli-resource/tests/test_resource_validators.py::Test_resource_validators::test_validate_lock_params src/command_modules/azure-cli-resource/tests/test_resource_validators.py::Test_resource_validators::test_validate_lock_params_invalid
src/command_modules/azure-cli-resource/tests/test_locks.py::ResourceLockTests::test_list_locks src/command_modules/azure-cli-resource/tests/test_resource_validators.py::Test_resource_validators::test_generate_deployment_name_from_file
src/command_modules/azure-cli-resource/azure/cli/command_modules/resource/_validators.py src/azure-cli/setup.py src/command_modules/azure-cli-vm/azure/cli/command_modules/vm/custom.py
src/command_modules/azure-cli-resource/azure/cli/command_modules/resource/_validators.py src/azure-cli/setup.py src/command_modules/azure-cli-vm/azure/cli/command_modules/vm/custom.py