diff --git a/azure-mgmt-resourcegraph/tests/recordings/test_mgmt_resourcegraph.test_resources_basic_query.yaml b/azure-mgmt-resourcegraph/tests/recordings/test_mgmt_resourcegraph.test_resources_basic_query.yaml new file mode 100644 index 000000000000..cad4b4aa7722 --- /dev/null +++ b/azure-mgmt-resourcegraph/tests/recordings/test_mgmt_resourcegraph.test_resources_basic_query.yaml @@ -0,0 +1,32 @@ +interactions: +- request: + body: 'b''b\''b\\\''b\\\\\\\''{"subscriptions": ["00000000-0000-0000-0000-000000000000"], + "query": "project id, tags, properties | limit 2"}\\\\\\\''\\\''\''''' + headers: + Accept: [application/json] + Accept-Encoding: ['gzip, deflate'] + Connection: [keep-alive] + Content-Length: ['110'] + Content-Type: [application/json; charset=utf-8] + User-Agent: [python/3.6.3 (Windows-10-10.0.17134-SP0) requests/2.19.1 msrest/0.5.4 + msrest_azure/0.4.34 azure-mgmt-resourcegraph/0.6.0 Azure-SDK-For-Python] + accept-language: [en-US] + method: POST + uri: https://management.azure.com/providers/Microsoft.ResourceGraph/resources?api-version=2018-09-01-preview + response: + body: {string: '{"totalRecords":2,"count":2,"data":{"columns":[{"name":"id","type":"string"},{"name":"tags","type":"object"},{"name":"properties","type":"object"}],"rows":[["/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/zarttest1faaede5-14b9-43b9-8836-3b8df81aa6f2/providers/Microsoft.StreamAnalytics/streamingjobs/zarttest28000000",{},{"provisioningState":"Succeeded","sku":{"name":"Standard"},"eventsLateArrivalMaxDelayInSeconds":5,"createdDate":"2018-07-26T01:17:29.3470000Z","compatibilityLevel":"1.0","outputErrorPolicy":"Stop","dataLocale":"en-US","jobState":"Created","package":null,"jobType":"Cloud","jobId":"00000000-0000-0000-0000-000000000000"}],["/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/newzarttestefd4b1a7-6480-40bb-bac5-f23376ebb04d/providers/Microsoft.Storage/storageAccounts/zarttest9b000000",{},{"provisioningState":"Succeeded","creationTime":"2018-08-04T19:23:48.4690000Z","supportsHttpsTrafficOnly":true,"trustedDirectories":["72f988bf-86f1-41af-91ab-2d7cd011db47"],"primaryEndpoints":{"blob":"https://zarttest9b000000.blob.core.windows.net/","file":"https://zarttest9b000000.file.core.windows.net/","table":"https://zarttest9b000000.table.core.windows.net/","queue":"https://zarttest9b000000.queue.core.windows.net/"},"statusOfPrimary":"available","primaryLocation":"eastus","networkAcls":{"virtualNetworkRules":[],"defaultAction":"Allow","ipRules":[],"bypass":"AzureServices"},"encryption":{"services":{"blob":{"lastEnabledTime":"2018-08-04T19:23:48.5940000Z","enabled":true},"file":{"lastEnabledTime":"2018-08-04T19:23:48.5940000Z","enabled":true}},"keySource":"Microsoft.Storage"}}]]},"facets":[],"resultTruncated":"false"}'} + headers: + cache-control: [no-cache] + content-length: ['1679'] + content-type: [application/json; charset=utf-8] + date: ['Wed, 29 Aug 2018 02:06:58 GMT'] + expires: ['-1'] + pragma: [no-cache] + server: [Microsoft-HTTPAPI/2.0] + strict-transport-security: [max-age=31536000; includeSubDomains] + transfer-encoding: [chunked] + vary: [Accept-Encoding] + x-content-type-options: [nosniff] + x-ms-ratelimit-remaining-tenant-writes: ['1198'] + status: {code: 200, message: OK} +version: 1 diff --git a/azure-mgmt-resourcegraph/tests/recordings/test_mgmt_resourcegraph.test_resources_facet_query.yaml b/azure-mgmt-resourcegraph/tests/recordings/test_mgmt_resourcegraph.test_resources_facet_query.yaml new file mode 100644 index 000000000000..fe886a974d58 --- /dev/null +++ b/azure-mgmt-resourcegraph/tests/recordings/test_mgmt_resourcegraph.test_resources_facet_query.yaml @@ -0,0 +1,36 @@ +interactions: +- request: + body: 'b''b\''b\\\''b\\\\\\\''{"subscriptions": ["00000000-0000-0000-0000-000000000000"], + "query": "project id, location | limit 10", "facets": [{"expression": "location", + "options": {"sortOrder": "desc", "$top": 4}}, {"expression": "nonExistingColumn", + "options": {"sortOrder": "desc", "$top": 4}}]}\\\\\\\''\\\''\''''' + headers: + Accept: [application/json] + Accept-Encoding: ['gzip, deflate'] + Connection: [keep-alive] + Content-Length: ['270'] + Content-Type: [application/json; charset=utf-8] + User-Agent: [python/3.6.3 (Windows-10-10.0.17134-SP0) requests/2.19.1 msrest/0.5.4 + msrest_azure/0.4.34 azure-mgmt-resourcegraph/0.6.0 Azure-SDK-For-Python] + accept-language: [en-US] + method: POST + uri: https://management.azure.com/providers/Microsoft.ResourceGraph/resources?api-version=2018-09-01-preview + response: + body: {string: '{"totalRecords":10,"count":10,"data":{"columns":[{"name":"id","type":"string"},{"name":"location","type":"string"}],"rows":[["/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/zarttest1f000000-14b9-43b9-8836-3b8df81aa6f2/providers/Microsoft.StreamAnalytics/streamingjobs/zarttest28000000","southcentralus"],["/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test/providers/Microsoft.Storage/storageAccounts/testsouthcentralus","southcentralus"],["/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/newzarttest30000000-5d0c-432c-8652-102e3aa336b6/providers/Microsoft.Storage/storageAccounts/zarttest93000000","eastus"],["/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/backup/providers/Microsoft.ClassicCompute/domainNames/rp-a","westcentralus"],["/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test/providers/Microsoft.Storage/storageAccounts/test1","southcentralus"],["/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/k8stest_centralus/providers/Microsoft.Compute/virtualMachines/aks-default-34000000-0/extensions/cse-agent-0","centralus"],["/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/pere/providers/Microsoft.Network/networkSecurityGroups/shouldFail-nsg","eastus"],["/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/newzarttestdd000000-bfc5-44f1-b6a9-aabdc7a1e614/providers/Microsoft.Storage/storageAccounts/zarttest43000000","eastus"],["/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/newzarttest60000000-3713-4c51-9e6b-c96a30f0fbb7/providers/Microsoft.Storage/storageAccounts/zarttestd2000000","eastus"],["/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/ManageRG/providers/Microsoft.EventHub/namespaces/resourceuse","eastus"]]},"facets":[{"expression":"location","totalRecords":4,"count":4,"data":{"columns":[{"name":"location","type":"string"},{"name":"count","type":"integer"}],"rows":[["eastus",5],["southcentralus",3],["centralus",1],["westcentralus",1]]},"resultType":"FacetResult"},{"expression":"nonExistingColumn","errors":[{"code":"NoValidColumns","message":"No + valid columns in facet expression."},{"code":"InvalidColumnNames","message":"Invalid + column names: [nonExistingColumn]."}],"resultType":"FacetError"}],"resultTruncated":"false"}'} + headers: + cache-control: [no-cache] + content-length: ['2472'] + content-type: [application/json; charset=utf-8] + date: ['Wed, 29 Aug 2018 02:06:59 GMT'] + expires: ['-1'] + pragma: [no-cache] + server: [Microsoft-HTTPAPI/2.0] + strict-transport-security: [max-age=31536000; includeSubDomains] + transfer-encoding: [chunked] + vary: [Accept-Encoding] + x-content-type-options: [nosniff] + x-ms-ratelimit-remaining-tenant-writes: ['1197'] + status: {code: 200, message: OK} +version: 1 diff --git a/azure-mgmt-resourcegraph/tests/recordings/test_mgmt_resourcegraph.test_resources_malformed_query.yaml b/azure-mgmt-resourcegraph/tests/recordings/test_mgmt_resourcegraph.test_resources_malformed_query.yaml new file mode 100644 index 000000000000..2518c93555f1 --- /dev/null +++ b/azure-mgmt-resourcegraph/tests/recordings/test_mgmt_resourcegraph.test_resources_malformed_query.yaml @@ -0,0 +1,31 @@ +interactions: +- request: + body: 'b''b\''b\\\''b\\\\\\\''{"subscriptions": ["00000000-0000-0000-0000-000000000000"], + "query": "project id, location | where where"}\\\\\\\''\\\''\''''' + headers: + Accept: [application/json] + Accept-Encoding: ['gzip, deflate'] + Connection: [keep-alive] + Content-Length: ['106'] + Content-Type: [application/json; charset=utf-8] + User-Agent: [python/3.6.3 (Windows-10-10.0.17134-SP0) requests/2.19.1 msrest/0.5.4 + msrest_azure/0.4.34 azure-mgmt-resourcegraph/0.6.0 Azure-SDK-For-Python] + accept-language: [en-US] + method: POST + uri: https://management.azure.com/providers/Microsoft.ResourceGraph/resources?api-version=2018-09-01-preview + response: + body: {string: "{\"error\":{\"code\":\"InvalidQuery\",\"message\":\"Query validation + error\",\"details\":[{\"code\":\"ParserFailure\",\"message\":\"Parser failure\",\"additionalProperties\":{\"line\":1,\"characterPositionInLine\":34,\"token\":\"\",\"expectedToken\":\"\u0178\"}}]}}"} + headers: + cache-control: [no-cache] + content-length: ['232'] + content-type: [application/json; charset=utf-8] + date: ['Wed, 29 Aug 2018 02:47:47 GMT'] + expires: ['-1'] + pragma: [no-cache] + server: [Microsoft-HTTPAPI/2.0] + strict-transport-security: [max-age=31536000; includeSubDomains] + x-content-type-options: [nosniff] + x-ms-ratelimit-remaining-tenant-writes: ['1197'] + status: {code: 400, message: Bad Request} +version: 1 diff --git a/azure-mgmt-resourcegraph/tests/recordings/test_mgmt_resourcegraph.test_resources_query_options.yaml b/azure-mgmt-resourcegraph/tests/recordings/test_mgmt_resourcegraph.test_resources_query_options.yaml new file mode 100644 index 000000000000..96d998889cc4 --- /dev/null +++ b/azure-mgmt-resourcegraph/tests/recordings/test_mgmt_resourcegraph.test_resources_query_options.yaml @@ -0,0 +1,33 @@ +interactions: +- request: + body: 'b''b\''b\\\''b\\\\\\\''{"subscriptions": ["00000000-0000-0000-0000-000000000000"], + "query": "project id", "options": {"$skipToken": "82aw3vQlArEastJ24LABY8oPgQLesIyAyzYs2g6/aOOOmJHSYFj39fODurJV5e2tTFFebWcfxn7n5edicA8u6HgSJe1GCEk5HjxwLkeJiye2LVZDC7TaValkJbsk9JqY4yv5c7iRiLqgO34RbHEeVfLJpa56u4RZu0K+GpQvnBRPyAhy3KbwhZWpU5Nnqnud2whGb5WKdlL8xF7wnQaUnUN2lns8WwqwM4rc0VK4BbQt/WfWWcYJivSAyB3m4Z5g73df1KiU4C+K8auvUMpLPYVxxnKC/YZz42YslVAWXXUmuGOaM2SfLHRO6o4O9DgXlUgYjeFWqIbAkmMiVEqU", + "$top": 4, "$skip": 8}}\\\\\\\''\\\''\''''' + headers: + Accept: [application/json] + Accept-Encoding: ['gzip, deflate'] + Connection: [keep-alive] + Content-Length: ['416'] + Content-Type: [application/json; charset=utf-8] + User-Agent: [python/3.6.3 (Windows-10-10.0.17134-SP0) requests/2.19.1 msrest/0.5.4 + msrest_azure/0.4.34 azure-mgmt-resourcegraph/0.6.0 Azure-SDK-For-Python] + accept-language: [en-US] + method: POST + uri: https://management.azure.com/providers/Microsoft.ResourceGraph/resources?api-version=2018-09-01-preview + response: + body: {string: '{"totalRecords":743,"count":4,"data":{"columns":[{"name":"id","type":"string"}],"rows":[["/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/backup/providers/Microsoft.ClassicCompute/domainNames/admin-a"],["/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/backup/providers/Microsoft.ClassicCompute/domainNames/admin-b"],["/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/backup/providers/Microsoft.Network/trafficmanagerprofiles/admin"],["/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/RP/providers/Microsoft.ClassicCompute/domainNames/rp-a"]]},"facets":[],"resultTruncated":"false","$skipToken":"ceXHDV/5yajn1stYtSCyQ32ULLF0jGv9oazG14qvdgwdAQNDUPHjt6MIlJZ2Y/K8z7fb+qo9wguegf8QYW0c7rqwtXUghJvKkPBENcn1O17nQxtjXeq6s8sD64D8t5P9NIHntl70D95yuVUjHF6/dsvVK33wKyvORwPTCbZrSj+pfz2yd5spa93izzOu06PcyFvcvCJAzZ5scImnVDqS700hR63izVwyETJtQluoqSPYkhxAOVk/+ThWlN0DKy9OfUE34M9PZSQz2QTWXKpUK1+okRfH/B2RVdXro60ZnNMrdPtglA5w7oEs5Ivq20IE4RtPfg97UEbkfyMP9huC="}'} + headers: + cache-control: [no-cache] + content-length: ['1098'] + content-type: [application/json; charset=utf-8] + date: ['Wed, 29 Aug 2018 02:07:01 GMT'] + expires: ['-1'] + pragma: [no-cache] + server: [Microsoft-HTTPAPI/2.0] + strict-transport-security: [max-age=31536000; includeSubDomains] + transfer-encoding: [chunked] + vary: [Accept-Encoding] + x-content-type-options: [nosniff] + x-ms-ratelimit-remaining-tenant-writes: ['1199'] + status: {code: 200, message: OK} +version: 1 diff --git a/azure-mgmt-resourcegraph/tests/test_mgmt_resourcegraph.py b/azure-mgmt-resourcegraph/tests/test_mgmt_resourcegraph.py new file mode 100644 index 000000000000..5d6c58c96487 --- /dev/null +++ b/azure-mgmt-resourcegraph/tests/test_mgmt_resourcegraph.py @@ -0,0 +1,180 @@ +# coding: utf-8 + +#------------------------------------------------------------------------- +# 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.mgmt.resourcegraph import ResourceGraphClient +from azure.mgmt.resourcegraph.models import * +from devtools_testutils import AzureMgmtTestCase +import six + + +class MgmtResourceGraphTest(AzureMgmtTestCase): + + def setUp(self): + super(MgmtResourceGraphTest, self).setUp() + self.resourcegraph_client = self.create_basic_client( + ResourceGraphClient + ) + + def test_resources_basic_query(self): + query = QueryRequest( + query='project id, tags, properties | limit 2', + subscriptions=[self.settings.SUBSCRIPTION_ID] + ) + + query_response = self.resourcegraph_client.resources(query) + + # Top-level response fields + self.assertEqual(query_response.count, 2) + self.assertEqual(query_response.total_records, 2) + self.assertIsNone(query_response.skip_token) + self.assertEqual(query_response.result_truncated, ResultTruncated.false) + self.assertIsNotNone(query_response.data) + self.assertIsNotNone(query_response.facets) + self.assertEqual(len(query_response.facets), 0) + + # Data columns + self.assertIsNotNone(query_response.data.columns) + self.assertEqual(len(query_response.data.columns), 3) + self.assertIsNotNone(query_response.data.columns[0].name) + self.assertIsNotNone(query_response.data.columns[1].name) + self.assertIsNotNone(query_response.data.columns[2].name) + self.assertEqual(query_response.data.columns[0].type, ColumnDataType.string) + self.assertEqual(query_response.data.columns[1].type, ColumnDataType.object_enum) + self.assertEqual(query_response.data.columns[2].type, ColumnDataType.object_enum) + + # Data rows + self.assertIsNotNone(query_response.data.rows) + self.assertEqual(len(query_response.data.rows), 2) + self.assertEqual(len(query_response.data.rows[0]), 3) + self.assertIsInstance(query_response.data.rows[0][0], six.string_types) + self.assertIsInstance(query_response.data.rows[0][1], dict) + self.assertIsInstance(query_response.data.rows[0][2], dict) + + def test_resources_query_options(self): + query = QueryRequest( + query='project id', + subscriptions=[self.settings.SUBSCRIPTION_ID], + options=QueryRequestOptions( + skip_token='82aw3vQlArEastJ24LABY8oPgQLesIyAyzYs2g6/aOOOmJHSYFj39fODurJV5e2tTFFebWcfxn7n5edicA8u6HgSJe1GCEk5HjxwLkeJiye2LVZDC7TaValkJbsk9JqY4yv5c7iRiLqgO34RbHEeVfLJpa56u4RZu0K+GpQvnBRPyAhy3KbwhZWpU5Nnqnud2whGb5WKdlL8xF7wnQaUnUN2lns8WwqwM4rc0VK4BbQt/WfWWcYJivSAyB3m4Z5g73df1KiU4C+K8auvUMpLPYVxxnKC/YZz42YslVAWXXUmuGOaM2SfLHRO6o4O9DgXlUgYjeFWqIbAkmMiVEqU', + top=4, + skip=8 + ) + ) + + query_response = self.resourcegraph_client.resources(query) + + # Top-level response fields + self.assertEqual(query_response.count, 4) + self.assertEqual(query_response.total_records, 743) + self.assertIsNotNone(query_response.skip_token) + self.assertEqual(query_response.result_truncated, ResultTruncated.false) + self.assertIsNotNone(query_response.data) + self.assertIsNotNone(query_response.facets) + self.assertEqual(len(query_response.facets), 0) + + # Data columns + self.assertIsNotNone(query_response.data.columns) + self.assertEqual(len(query_response.data.columns), 1) + self.assertIsNotNone(query_response.data.columns[0].name) + self.assertEqual(query_response.data.columns[0].type, ColumnDataType.string) + + # Data rows + self.assertIsNotNone(query_response.data.rows) + self.assertEqual(len(query_response.data.rows), 4) + self.assertEqual(len(query_response.data.rows[0]), 1) + self.assertIsInstance(query_response.data.rows[0][0], six.string_types) + + def test_resources_facet_query(self): + facet_expression0 = 'location' + facet_expression1 = 'nonExistingColumn' + + query = QueryRequest( + query='project id, location | limit 10', + subscriptions=[self.settings.SUBSCRIPTION_ID], + facets=[ + FacetRequest( + expression=facet_expression0, + options=FacetRequestOptions( + sort_order='desc', + top=4 + ) + ), + FacetRequest( + expression=facet_expression1, + options=FacetRequestOptions( + sort_order='desc', + top=4 + ) + ) + ] + ) + + query_response = self.resourcegraph_client.resources(query) + + # Top-level response fields + self.assertEqual(query_response.count, 10) + self.assertEqual(query_response.total_records, 10) + self.assertIsNone(query_response.skip_token) + self.assertEqual(query_response.result_truncated, ResultTruncated.false) + self.assertIsNotNone(query_response.data) + self.assertIsNotNone(query_response.facets) + self.assertEqual(len(query_response.facets), 2) + + # Successful facet fields + self.assertIsInstance(query_response.facets[0], FacetResult) + self.assertEqual(query_response.facets[0].expression, facet_expression0) + self.assertEqual(query_response.facets[0].total_records, 4) + self.assertEqual(query_response.facets[0].count, 4) + + # Successful facet columns + self.assertIsNotNone(query_response.facets[0].data.columns) + self.assertEqual(len(query_response.facets[0].data.columns), 2) + self.assertIsNotNone(query_response.facets[0].data.columns[0].name) + self.assertIsNotNone(query_response.facets[0].data.columns[1].name) + self.assertEqual(query_response.facets[0].data.columns[0].type, ColumnDataType.string) + self.assertEqual(query_response.facets[0].data.columns[1].type, ColumnDataType.integer) + + # Successful facet rows + self.assertIsNotNone(query_response.facets[0].data.rows) + self.assertEqual(len(query_response.facets[0].data.rows), 4) + self.assertEqual(len(query_response.facets[0].data.rows[0]), 2) + self.assertIsInstance(query_response.facets[0].data.rows[0][0], six.string_types) + self.assertIsInstance(query_response.facets[0].data.rows[0][1], six.integer_types) + + # Failed facet + self.assertIsInstance(query_response.facets[1], FacetError) + self.assertEqual(query_response.facets[1].expression, facet_expression1) + self.assertIsNotNone(query_response.facets[1].errors) + self.assertGreater(len(query_response.facets[1].errors), 0) + self.assertIsNotNone(query_response.facets[1].errors[0].code) + self.assertIsNotNone(query_response.facets[1].errors[0].message) + + def test_resources_malformed_query(self): + query = QueryRequest( + query='project id, location | where where', + subscriptions=[self.settings.SUBSCRIPTION_ID] + ) + + with self.assertRaises(ErrorResponseException) as cm: + self.resourcegraph_client.resources(query) + + error = cm.exception.error.error + self.assertIsNotNone(error.code) + self.assertIsNotNone(error.message) + self.assertIsNotNone(error.details) + self.assertGreater(len(error.details), 0) + self.assertIsNotNone(error.details[0].code) + self.assertIsNotNone(error.details[0].message) + self.assertIsNotNone(error.details[0].additional_properties) + self.assertGreater(len(error.details[0].additional_properties), 0) + + +#------------------------------------------------------------------------------ +if __name__ == '__main__': + unittest.main()