def testGetModelDataWithModelUIdAndAnomalyScore(self): """ test GET /metricId/data?anomaly=testanomalyScore """ getMetricDataWithAnomalyQueryResponse = self.app.get( "/%s/data?anomaly=%s" % (self.uid, self.testAnomalyScore), headers=self.headers) getMetricDataWithAnomalyQueryResult = utils.jsonDecode( getMetricDataWithAnomalyQueryResponse.body) assertions.assertSuccess(self, getMetricDataWithAnomalyQueryResponse) self.assertIsInstance(getMetricDataWithAnomalyQueryResult, dict) self.assertItemsEqual(getMetricDataWithAnomalyQueryResult.keys(), ["data", "names"]) self.assertGreater(len(getMetricDataWithAnomalyQueryResult["data"]), 0) # we are parsing amomaly scores from reponse and chekcing if each of it # is satisfying value condition set with GET request. # If for some reason this parameter is not applied on DB query, we get # full response for this request # We are making sure each value for anomaly_score in result matches with # condition set in GET request, hence the assertion anomalyScores = \ [row[2] for row in getMetricDataWithAnomalyQueryResult["data"]] failedScores = [a for a in anomalyScores if a < self.testAnomalyScore] self.assertEqual(failedScores, [])
def testCombinationQuota1(self): result = self.cloudwatchApp.get("/us-west-2/AWS/EC2", headers=self.headers) instances = json.loads(result.body) for i in range(0, 10, 5): instance = instances[i] instanceId = "us-west-2/AWS/EC2/%s" % ( instance["dimensions"]["InstanceId"]) postResponse = self.instancesApp.post("/%s" % instanceId, headers=self.headers) assertions.assertSuccess(self, postResponse) self.addCleanup(self.instancesApp.delete, "/", headers=self.headers, params=json.dumps([instanceId])) sock = socket.socket() sock.connect(("localhost", self.plaintextPort)) sock.sendall("CustomMetric1 5.0 1386201600\n") self.gracefullyCloseSocket(sock) self.addCleanup(self.customApp.delete, "/CustomMetric1", headers=self.headers) uid = self.checkMetricCreated("CustomMetric1") with self.assertRaises(AppError) as e: payload = {"uid": uid, "datasource": "custom", "min": 0.0, "max": 100.0} self.modelApp.post("/", json.dumps(payload), headers=self.headers) self.assertIn("Server limit exceeded", e.exception.message)
def _deleteOneMetric(self): """ Delete one metric from test EC2 instance """ app = TestApp(models_api.app.wsgifunc()) response = app.get("/", headers=self.headers) assertions.assertSuccess(self, response) result = app_utils.jsonDecode(response.body) self.assertIsInstance(result, list) app.delete("/" + result[0]['uid'], headers=self.headers)
def testGETDatasources(self): """ Test for GET for '/_metrics/datasources' response is validated for appropriate headers and body """ response = self.app.get('/datasources', headers=self.headers) assertions.assertSuccess(self, response) self.assertIsInstance(utils.jsonDecode(response.body), list) self.assertSetEqual(set(utils.jsonDecode(response.body)), set(["autostack", "custom", "cloudwatch"]))
def testGetListRegionsEmptyResponse(self, adapterMock): """ Test for Get '/_metrics/cloudwatch/regions' response is validated for appropriate headers, body and status """ adapterMock.return_value.describeRegions.return_value = [] response = self.app.get("/regions", headers=self.headers) assertions.assertSuccess(self, response) result = app_utils.jsonDecode(response.body) self.assertEqual(result, {})
def testDefaultGetSpecificSection(self): response = self.app.get("/aws", headers=self.headers) assertions.assertSuccess(self, response) result = app_utils.jsonDecode(response.body) self.assertIsInstance(result, dict) for key in set(self.configurable_options["aws"]): if key in settings_api.HIDDEN_SETTINGS["aws"]: self.assertNotIn(key, result) else: self.assertIn(key, result)
def _deleteInstance(self): """ Delete test EC2 instance created by :py:meth:`_createEC2Instance` """ app = TestApp(instances_api.app.wsgifunc()) response = app.delete("/", params=json.dumps([self.instanceId]), headers=self.headers) assertions.assertSuccess(self, response) result = app_utils.jsonDecode(response.body) self.assertIsInstance(result, dict) self.assertEqual(result, {"result": "success"})
def testGetModelDataWithModelUId(self): """ test GET /metricId/data """ getMetricDataResponse = self.app.get("/%s/data" % self.uid, headers=self.headers) assertions.assertSuccess(self, getMetricDataResponse) getMetricDataResult = utils.jsonDecode(getMetricDataResponse.body) self.assertIsInstance(getMetricDataResult, dict) self.assertItemsEqual(getMetricDataResult.keys(), ["data", "names"]) self.assertGreater(len(getMetricDataResult["data"]), 0)
def testGetListNamespaceNoRegions(self, adapterMock): """ Test for Get '/_metrics/cloudwatch/namespaces' response is validated for appropriate headers, body and status """ adapterMock.return_value.describeRegions.return_value = [] response = self.app.get("/namespaces", headers=self.headers) assertions.assertSuccess(self, response) result = app_utils.jsonDecode(response.body) # Added Autostacks namespaces to this list for now, to maintain API # backwards-compatibility during adapter refactor self.assertEqual(result, {'Autostacks': {'metrics': ['InstanceCount']}})
def testDefaultGetList(self): response = self.app.get("", headers=self.headers) assertions.assertSuccess(self, response) result = app_utils.jsonDecode(response.body) self.assertIsInstance(result, dict) for config in self.configurable_options: self.assertTrue(result.has_key(config)) for key in self.configurable_options[config]: if key in settings_api.HIDDEN_SETTINGS[config]: self.assertNotIn(key, result[config]) else: self.assertIn(key, result[config])
def _createEC2Instance(self): """ Created EC2 instance to be used by the tests :return: Instance ID :rtype: str """ app = TestApp(instances_api.app.wsgifunc()) response = app.post("/" + self.instanceId, headers=self.headers) assertions.assertSuccess(self, response) result = app_utils.jsonDecode(response.body) self.assertIsInstance(result, dict) self.assertEqual(result, {"result": "success"})
def testGetMetricValidInputEmptyResponse(self, adapterMock): """ Test for Get '/_metrics/cloudwatch/<region-name>/AWS/<namespace>/metricName' response is validated for appropriate headers, body and status """ adapterMock.return_value.describeRegions.return_value = self.regions adapterMock.return_value.describeSupportedMetrics.return_value = ( self.resources) adapterMock.return_value.describeResources.return_value = [] response = self.app.get("/us-east-1/AWS/EC2/CPUUtilization", headers=self.headers) assertions.assertSuccess(self, response) result = app_utils.jsonDecode(response.body) self.assertEqual(result, [])
def testPostMultipleWithInvalidInstanceId(self): """ Test for post '/_instances' response is validated for appropriate headers, body and status Invoke post with invalid instanceId Expect a 200 OK even when attempting to POST to an invalid instance, this saves the overhead of asking AWS if we're dealing with a valid instance every POST. We expect the CLI user to know what instance ID he/she is looking for. """ params = ["abcd1234"] response = self.app.post("/us-west-2/AWS/EC2", params=app_utils.jsonEncode(params), headers=self.headers, status="*") assertions.assertSuccess(self, response)
def testPostMultipleWithInstanceToIncorrectNamespace(self): """ Test for post'/_instances' response is validated for appropriate headers, body and status Invoke post with valid instance id to incorrect namespace Expect a 200 OK even when attempting to POST an instance to the wrong namespace, this saves the overhead of asking AWS if we're dealing with a valid instance in the given namespace with every POST request. We expect the CLI user to know what instance ID he/she is looking for. """ params = ["htm-it-docs-elb"] response = self.app.post("/us-west-2/AWS/EC2", params=app_utils.jsonEncode(params), headers=self.headers, status="*") assertions.assertSuccess(self, response)
def testGetMetricDimensionWithResponse(self, adapterMock): """ Test for Get '/_metrics/cloudwatch/<region-name>/AWS/<namespace>/metricName' response is validated for appropriate headers, body and status and response is validated with pre-defined responses """ adapterMock.return_value.describeRegions.return_value = self.regions adapterMock.return_value.describeSupportedMetrics.return_value = ( self.resources) adapterMock.return_value.describeResources.return_value = [ {'grn': u'aws://us-west-2/Instance/i-d48ccaba', 'name': u'Foo', 'resID': u'i-d48ccaba'}, {'grn': u'aws://us-west-2/Instance/i-548acc3a', 'name': u'Bar', 'resID': u'i-548acc3a'}] response = self.app.get("/us-east-1/AWS/EC2/CPUUtilization", headers=self.headers) assertions.assertSuccess(self, response) result = app_utils.jsonDecode(response.body) self.assertItemsEqual(result, [ {'datasource': 'cloudwatch', 'dimensions': {'InstanceId': 'i-d48ccaba'}, 'metric': 'CPUUtilization', 'namespace': 'AWS/EC2', 'region': 'us-east-1'}, {'datasource': 'cloudwatch', 'dimensions': {'InstanceId': 'i-548acc3a'}, 'metric': 'CPUUtilization', 'namespace': 'AWS/EC2', 'region': 'us-east-1'}, {'datasource': 'cloudwatch', 'dimensions': {'AutoScalingGroupName': 'i-d48ccaba'}, 'metric': 'CPUUtilization', 'namespace': 'AWS/EC2', 'region': 'us-east-1'}, {'datasource': 'cloudwatch', 'dimensions': {'AutoScalingGroupName': 'i-548acc3a'}, 'metric': 'CPUUtilization', 'namespace': 'AWS/EC2', 'region': 'us-east-1'} ])
def testPostWithInvalidInstanceId(self): """ Test for post '/_instances/region/namespace/instanceId' response is validated for appropriate headers, body and status Invoke Api call with instanceId that does not exists Expect a 200 OK even when attempting to POST to an invalid instance, this saves the overhead of asking AWS if we're dealing with a valid instance every POST. We expect the CLI user to know what instance ID he/she is looking for. """ region = "us-west-2" namespace = "EC2" instanceId = "abcd1234" response = self.app.post("/%s/AWS/%s/%s" % (region, namespace, instanceId), headers=self.headers, status="*") assertions.assertSuccess(self, response)
def testPostInstanceIdToIncorrectNamespace(self): """ Test for post '/_instances/region/namespace/instanceId' response is validated for appropriate headers, body and status Invoke Api call with instance to incorrect namespace. e.g post htm-it-docs-elb to AWS/EC2 Expect a 200 OK even when attempting to POST an instance to the wrong namespace, this saves the overhead of asking AWS if we're dealing with a valid instance in the given namespace with every POST request. We expect the CLI user to know what instance ID he/she is looking for. """ region = "us-west-2" namespace = "EC2" instanceId = "htm-it-docs-elb" response = self.app.post("/%s/AWS/%s/%s" % (region, namespace, instanceId), headers=self.headers, status="*") assertions.assertSuccess(self, response)
def testGetAllModelData(self): """ test GET /data """ getAllMetricDataResponse = self.app.get("/%s/data" % self.uid, headers=self.headers) assertions.assertSuccess(self, getAllMetricDataResponse) getAllMetricDataResult = utils.jsonDecode(getAllMetricDataResponse.body) assertions.assertSuccess(self, getAllMetricDataResponse) self.assertIsInstance(getAllMetricDataResult, dict) self.assertItemsEqual(getAllMetricDataResult.keys(), ["data", "names"]) # Compare http and https response https_response = requests.get("https://localhost/_models/%s/data" % self.uid, headers=self.headers, verify=False) httpsData = json.loads(https_response.text) self.assertIsInstance(httpsData, dict) self.assertItemsEqual(httpsData.keys(), ["data", "names"]) self.assertItemsEqual(httpsData["names"], ["timestamp", "value", "anomaly_score", "rowid"]) self.assertIsInstance(httpsData["data"], list) self.assertTrue(all(isinstance(row, list) and len(row) == 4 for row in httpsData["data"])) http_response = requests.get("http://localhost/_models/%s/data" % self.uid, headers=self.headers) httpData = json.loads(http_response.text) self.assertIsInstance(httpData, dict) self.assertItemsEqual(httpData.keys(), ["data", "names"]) self.assertItemsEqual(httpData["names"], ["timestamp", "value", "anomaly_score", "rowid"]) self.assertIsInstance(httpData["data"], list) self.assertTrue(all(isinstance(row, list) and len(row) == 4 for row in httpData["data"]))
def testGetModelDataWithModelUIdAndFromTimeStamp(self): """ test GET /metricId/data?from=timeStamp """ getMetricDataWithFromTimeStampResponse = self.app.get( "/%s/data?from=%s" % (self.uid, self.testTimeStamp), headers=self.headers) getMetricDataWithFromTimeStampResult = utils.jsonDecode( getMetricDataWithFromTimeStampResponse.body) assertions.assertSuccess(self, getMetricDataWithFromTimeStampResponse) self.assertGreater(len(getMetricDataWithFromTimeStampResult["data"]), 0) # We wait for minimum rows to be available for givem metric # We are using lower value for rowId to get Non NULL value anomaly_score # We get all available metric data rows, if condition is # not applied on DB query and hence the GET call will return all data rows # Asserting following will make sure that we have received result with # applied condition. # ( In this case len(metricData) would be greater than result length) self.assertGreater(len(self.metricData), len(getMetricDataWithFromTimeStampResult["data"]))
def testGetNamespaceAWSType(self, adapterMock): """ Test for Get '/_metrics/cloudwatch/AWS/<namespace>' response is validated for appropriate headers, body and status """ adapterMock.return_value.describeRegions.return_value = self.regions adapterMock.return_value.describeSupportedMetrics.return_value = ( self.resources) response = self.app.get("/AWS/EC2", headers=self.headers) #self.assertTrue(getMetrics.called) assertions.assertSuccess(self, response) result = app_utils.jsonDecode(response.body) self.assertEqual(result, {'AWS/EC2': {'dimensions': ['InstanceId', 'AutoScalingGroupName'], 'metrics': ['CPUUtilization', 'NetworkIn', 'DiskWriteBytes', 'NetworkOut', 'DiskReadBytes']}})
def testCloudwatchQuota(self): result = self.cloudwatchApp.get("/us-west-2/AWS/EC2", headers=self.headers) instances = json.loads(result.body) for i in range(0, 10, 5): instance = instances[i] instanceId = "us-west-2/AWS/EC2/%s" % ( instance["dimensions"]["InstanceId"]) postResponse = self.instancesApp.post("/%s" % instanceId, headers=self.headers) assertions.assertSuccess(self, postResponse) self.addCleanup(self.instancesApp.delete, "/", headers=self.headers, params=json.dumps([instanceId])) with self.assertRaises(AppError) as e: instanceId = ("us-west-2/AWS/EC2/%s" % (instances[10]["dimensions"]["InstanceId"])) postResponse = self.instancesApp.post("/%s" % instanceId, headers=self.headers) self.assertIn("Server limit exceeded", e.exception.message)
def testLifecycleForSingleInstance(self): """ Test for Get '/_instances' response is validated for appropriate headers, body and status Make sure app returns empty list at initial step Test for post '/_instances/region/namespace/instanceId' response is validated for appropriate headers, body and status Invoke post with valid instanceId Test for get '/_instances/{instanceId}' response is validated for appropriate headers, body and status Check if you can invoke get on previously post'ed instance Instance Test for delete '/_instances/region/namespace/instanceId' response is validated for appropriate headers, body and status This invokes delete call on previously monitored instance Test for get '/_instances/{instanceId}' response is validated for appropriate headers, body and status This invokes get call with instanceId which is deleted from monitored list """ # check initial empty response with get request initialGetResponse = self.app.get("", headers=self.headers) assertions.assertSuccess(self, initialGetResponse) initialGetResult = app_utils.jsonDecode(initialGetResponse.body) self.assertItemsEqual(initialGetResult, []) # Post single instance details to add under monitor region = VALID_EC2_INSTANCES["jenkins-master"]["region"] namespace = "EC2" instanceId = "%s/AWS/%s/%s" % ( region, namespace, VALID_EC2_INSTANCES["jenkins-master"]["instanceId"]) postResponse = self.app.post("/" + instanceId, headers=self.headers) assertions.assertSuccess(self, postResponse) postResult = app_utils.jsonDecode(postResponse.body) self.assertIsInstance(postResult, dict) self.assertEqual(postResult, {"result": "success"}) # Verify that instance is successfully added under monitor getPostCheckResponse = self.app.get("", headers=self.headers) assertions.assertSuccess(self, getPostCheckResponse) getPostCheckResult = app_utils.jsonDecode(getPostCheckResponse.body) self.assertEqual(len(getPostCheckResult), 1) instanceResult = getPostCheckResult[0] self.assertEqual(region, instanceResult["location"]) self.assertTrue(instanceId, instanceResult["server"]) # Delete instance from monitor deleteResponse = self.app.delete("/", headers=self.headers, params=json.dumps([instanceId])) assertions.assertDeleteSuccessResponse(self, deleteResponse) # Check get reponse to confirm that instance has been deleted successfully getPostDeleteResponse = self.app.get("", headers=self.headers) postResult = app_utils.jsonDecode(getPostDeleteResponse.body) self.assertEqual(postResult, [])
def testGetInstanceWithDimension(self,adapterMock): """ Test for Get '/_metrics/cloudwatch/<region-name>/AWS/<namespace>/\ instances/<InstancdId>' with valid InstancceId response is validated for appropriate headers, body and status """ adapterMock.return_value.describeRegions.return_value = self.regions adapterMock.return_value.describeSupportedMetrics.return_value = ( self.resources) adapterMock.return_value.describeResources.return_value = [ {'grn': u'aws://us-west-2/Instance/i-548acc3a', 'name': u'Bar', 'resID': u'i-548acc3a'}] response = self.app.get("/us-east-1/AWS/EC2/instances/i-548acc3a", headers=self.headers) assertions.assertSuccess(self, response) result = app_utils.jsonDecode(response.body) self.assertTrue(all(metric["metric"] in self.resources['AWS::EC2::Instance'] for metric in result))
def testGetInstanceWithDimensionNotFoundEmpty(self, adapterMock): """ Test for Get '/_metrics/cloudwatch/<region-name>/AWS/<namespace>/\ instances/<InstancdId>/Dimenion' with invalid InstancceId response is validated for appropriate headers, body and status Tests scenario when given instance name is not present in ouput from getDimensionsFromRegion """ adapterMock.return_value.describeRegions.return_value = self.regions adapterMock.return_value.describeSupportedMetrics.return_value = ( self.resources) adapterMock.return_value.describeResources.return_value = [ {'grn': u'aws://us-west-2/Instance/i-548acc3a', 'name': u'Bar', 'resID': u'i-548acc3a'}] response = self.app.get("/us-east-1/AWS/EC2/instances/i-1234567a", headers=self.headers) assertions.assertSuccess(self, response) result = app_utils.jsonDecode(response.body) self.assertEqual(result, [])
def testCompleteModelExportApiLifecycle(self): """ Happy path testing for the route "/_models/export" """ data = self.modelsTestData["create_data"] createResponse = self.app.put("/", utils.jsonEncode(data), headers=self.headers) assertions.assertSuccess(self, createResponse, code=201) # NOTE: export uses a new format expectedExportSpec = { "datasource": data["datasource"], "metricSpec": { "region": data["region"], "namespace": data["namespace"], "metric": data["metric"], "dimensions": data["dimensions"] } } # Test export all data response = self.app.get("/export", headers=self.headers) assertions.assertSuccess(self, response) exportedData = utils.jsonDecode(response.body) self.assertIsInstance(exportedData, list) self.assertEqual(exportedData[0], expectedExportSpec) responseData = utils.jsonDecode(createResponse.body) uid = responseData[0]['uid'] # Test for exporting single metric. response = self.app.get("/%s/export" % uid, headers=self.headers) assertions.assertSuccess(self, response) exportedData = utils.jsonDecode(response.body) self.assertIsInstance(exportedData, list) self.assertEqual(exportedData[0], expectedExportSpec) # Delete the model that was created earlier response = self.app.delete("/%s" % uid, headers=self.headers) assertions.assertDeleteSuccessResponse(self, response) # Import the model from exported data response = self.app.put("/", utils.jsonEncode(exportedData), headers=self.headers) assertions.assertSuccess(self, response, code=201) responseData = utils.jsonDecode(response.body) uid = responseData[0]['uid'] # Export the newly-imported model response = self.app.get("/%s/export" % uid, headers=self.headers) assertions.assertSuccess(self, response) exportedData = utils.jsonDecode(response.body) self.assertIsInstance(exportedData, list) self.assertEqual(exportedData[0], expectedExportSpec) # Delete the model that was created earlier response = self.app.delete("/%s" % uid, headers=self.headers) assertions.assertDeleteSuccessResponse(self, response) # Import the model using legacy format legacyImportSpec = dict(type="metric", **data) response = self.app.put("/", utils.jsonEncode(legacyImportSpec), headers=self.headers) assertions.assertSuccess(self, response, code=201) responseData = utils.jsonDecode(response.body) uid = responseData[0]['uid'] # Export the newly-imported model response = self.app.get("/%s/export" % uid, headers=self.headers) assertions.assertSuccess(self, response) exportedData = utils.jsonDecode(response.body) self.assertIsInstance(exportedData, list) self.assertEqual(exportedData[0], expectedExportSpec)
def testCompleteModelsApiLifecycle(self): """ Happy path testing for the route "/_models" """ # get all models in the system when there are no models # expected response is [] response = self.app.get("/", headers=self.headers) assertions.assertSuccess(self, response) allModelsResult = utils.jsonDecode(response.body) self.assertEqual(len(allModelsResult), 0) self.assertIsInstance(allModelsResult, list) data = self.modelsTestData["create_data"] # create a model using PUT; # Any HTTP POST call is forwarded to HTTP PUT in the Model API. # def POST(self): # return self.PUT() # The tests are just calling PUT. # TODO: wouldn't POST be a better method to test in that case, since it # would exercise both POST and PUT? response = self.app.put("/", utils.jsonEncode(data), headers=self.headers) assertions.assertSuccess(self, response, code=201) postResult = utils.jsonDecode(response.body) self.assertEqual(len(postResult), 1) self._checkCreateModelResult(postResult[0], data) # get model that was previously created uid = postResult[0]["uid"] response = self.app.get("/%s" % uid, headers=self.headers) assertions.assertSuccess(self, response) getModelResult = utils.jsonDecode(response.body) self.assertItemsEqual(getModelResult[0].keys(), self.modelsTestData["get_response"].keys()) # get all models in the system response = self.app.get("/", headers=self.headers) assertions.assertSuccess(self, response) allModelsResult = utils.jsonDecode(response.body) self.assertItemsEqual(allModelsResult[0].keys(), self.modelsTestData["get_response"].keys()) self.assertItemsEqual(allModelsResult[0].keys(), self.modelsTestData["get_response"].keys()) self.assertEqual(len(allModelsResult), 1) # Repeat the request to monitor same metric and verify that it returns the # same model uid instead of creating a new one response = self.app.post("/", utils.jsonEncode(data), headers=self.headers) assertions.assertSuccess(self, response, code=201) postResult = utils.jsonDecode(response.body) self.assertEqual(postResult[0]["uid"], uid) self.assertEqual(len(postResult), 1) self._checkCreateModelResult(postResult[0], data) # Compare http and https responses for all models for x in range(3): https_response = requests.get("https://localhost/_models", headers=self.headers, verify=False) http_response = requests.get("http://localhost/_models", headers=self.headers) self.assertEqual(http_response.status_code, 200) self.assertEqual(https_response.status_code, 200) httpsData = json.loads(https_response.text) try: self.assertIsInstance(httpsData, list) self.assertTrue(httpsData) for item in httpsData: self.assertIn("status", item) self.assertIn("last_rowid", item) self.assertIn("display_name", item) self.assertIn("uid", item) self.assertIn("datasource", item) httpData = json.loads(http_response.text) self.assertIsInstance(httpData, list) self.assertTrue(httpData) for item in httpData: self.assertIn("status", item) self.assertIn("last_rowid", item) self.assertIn("display_name", item) self.assertIn("uid", item) self.assertIn("datasource", item) self.assertEqual(http_response.text, https_response.text) break except AssertionError: time.sleep(10) else: self.fail("Unable to synchronize http and https responses.") # Compare http and https response for all models data https_response = requests.get("https://localhost/_models/data", headers=self.headers, verify=False) http_response = requests.get("http://localhost/_models/data", headers=self.headers) self.assertEqual(http_response.status_code, 200) self.assertEqual(https_response.status_code, 200) httpData = json.loads(http_response.text) self.assertIsInstance(httpData, dict) self.assertItemsEqual(httpData.keys(), ["metrics", "names"]) self.assertItemsEqual(httpData["names"], ["timestamp", "value", "anomaly_score", "rowid"]) httpsData = json.loads(https_response.text) self.assertIsInstance(httpsData, dict) self.assertItemsEqual(httpsData.keys(), ["metrics", "names"]) self.assertItemsEqual(httpsData["names"], ["timestamp", "value", "anomaly_score", "rowid"]) # delete the model that was created earlier response = self.app.delete("/%s" % uid, headers=self.headers) assertions.assertDeleteSuccessResponse(self, response)
def testMonitorMetricViaModelSpec(self): """ Happy path testing for the route "/_models" with new modelSpec format """ modelSpec = { "datasource": "cloudwatch", "metricSpec": { "region": "us-west-2", "namespace": "AWS/EC2", "metric": "CPUUtilization", "dimensions": { "InstanceId": "i-12d67826" } }, "modelParams": { "min": 0, # optional "max": 100 # optional } } # create a model response = self.app.post("/", utils.jsonEncode(modelSpec), headers=self.headers) assertions.assertSuccess(self, response, code=201) postResult = utils.jsonDecode(response.body) self.assertEqual(len(postResult), 1) self._checkCreateModelResult(postResult[0], modelSpec["metricSpec"]) # get model that was previously created uid = postResult[0]["uid"] response = self.app.get("/%s" % uid, headers=self.headers) assertions.assertSuccess(self, response) getModelResult = utils.jsonDecode(response.body) self.assertItemsEqual(getModelResult[0].keys(), self.modelsTestData["get_response"].keys()) # get all models in the system response = self.app.get("/", headers=self.headers) assertions.assertSuccess(self, response) allModelsResult = utils.jsonDecode(response.body) self.assertItemsEqual(allModelsResult[0].keys(), self.modelsTestData["get_response"].keys()) self.assertItemsEqual(allModelsResult[0].keys(), self.modelsTestData["get_response"].keys()) self.assertEqual(len(allModelsResult), 1) # Repeat the request to monitor same metric and verify that it returns the # same model uid instead of creating a new one response = self.app.post("/", utils.jsonEncode(modelSpec), headers=self.headers) assertions.assertSuccess(self, response, code=201) postResult = utils.jsonDecode(response.body) self.assertEqual(postResult[0]["uid"], uid) self.assertEqual(len(postResult), 1) self._checkCreateModelResult(postResult[0], modelSpec["metricSpec"]) # Unmonitor the metric response = self.app.delete("/%s" % uid, headers=self.headers) assertions.assertDeleteSuccessResponse(self, response)
def _getCloudWatchCommon(self, url, expectedResult): response = self.app.get(url, headers=self.headers) assertions.assertSuccess(self, response) result = app_utils.jsonDecode(response.body) self.assertIsInstance(result, dict) self.assertEqual(result, expectedResult)
def testLifecycleForMultipleInstances(self): """ Test for Get '/_instances' response is validated for appropriate headers, body and status This expects response from application in initial stage when no instances are under monitor Test for post '/_instances' response is validated for appropriate headers, body and status post multiple instances Test for Get '/_instances' response is validated for appropriate headers, body and status This test check for listed monitored instances from previous step Test for delete '/_instances' response is validated for appropriate headers, body and status invoke delete with valid instanceId for listed monitored instances from previous step Test for Get '/_instances' response is validated for appropriate headers, body and status This invokes get call to assert that all instances which were under monitor have been deleted and we get empty response """ # Check instance list at initial phase for empty response getIntialResponse = self.app.get("", headers=self.headers) assertions.assertSuccess(self, getIntialResponse) getIntialResult = app_utils.jsonDecode(getIntialResponse.body) self.assertItemsEqual(getIntialResult, []) # Test for post '/_instances' # TODO: Until MER-1172 is resolved # test will execute this as temporary. This will add expected instances # under monitor. Which will be used for further tests # here adding params = [VALID_EC2_INSTANCES["rpm-builder"]["instanceId"], VALID_EC2_INSTANCES["htm-it-docs"]["instanceId"]] region = "us-west-2" namespace = "EC2" for instance in params: postResponse = self.app.post("/%s/AWS/%s/%s" % (region, namespace, instance), headers=self.headers) assertions.assertSuccess(self, postResponse) postResult = app_utils.jsonDecode(postResponse.body) self.assertIsInstance(postResult, dict) self.assertEqual(postResult, {"result": "success"}) # TODO Use Api calls below once MER-1172 is resolved #postResponse = self.app.post("/us-west-2/AWS/EC2", # params=app_utils.jsonEncode(params), headers=self.headers, status="*") #assertions.assertSuccess(self, response) #postResult = app_utils.jsonDecode(postResponse.body) #self.assertIsInstance(postResult, dict) #self.assertEqual(postResult, {"result": "success"}) # Test for Get '/_instances' getPostCheckResponse = self.app.get("", headers=self.headers) assertions.assertSuccess(self, getPostCheckResponse) getPostCheckResult = app_utils.jsonDecode(getPostCheckResponse.body) instanceIds = [] self.assertIsInstance(getPostCheckResult, list) for instance in getPostCheckResult: instanceIds.append(instance["server"]) self.assertEqual(instance["namespace"], "AWS/EC2") self.assertEqual(instance["location"], "us-west-2") self.assertItemsEqual([instanceId.rpartition("/")[2] for instanceId in instanceIds], params) # Delete instances under monitor deleteResponse = self.app.delete("", params=app_utils.jsonEncode(instanceIds), headers=self.headers) assertions.assertDeleteSuccessResponse(self, deleteResponse) # check instances to confirm the delete action getPostDeleteCheckResponse = self.app.get("", headers=self.headers) assertions.assertSuccess(self, getPostDeleteCheckResponse) getPostDeleteResult = app_utils.jsonDecode(getPostDeleteCheckResponse.body) self.assertItemsEqual(getPostDeleteResult, [])