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 testDeleteInstanceHandler(self, listMetricIDsMock, engineFactoryMock): """ Test for Delete "/_instances/<instanceId>" response is validated for appropriate headers, body and status """ listMetricIDsMock.return_value = ["2490fb7a9df5470fa3678530c4cb0a43", "b491ab2310ef4a799b14c08fa3e09f1c"] response = self.app.delete("", headers=self.headers, params=json.dumps(["i-cd660efb"])) assertions.assertDeleteSuccessResponse(self, response) self.assertTrue(listMetricIDsMock.called) listMetricIDsMock.assert_called_once_with( (engineFactoryMock.return_value.connect.return_value.__enter__.return_value), "i-cd660efb" )
def testDeleteInstancesHandler(self, listMetricIDsMock, engineFactoryMock): """ Test for Delete "/_instances" response is validated for appropriate headers, body and status """ listMetricIDsMock.return_value = ["2490fb7a9df5470fa3678530c4cb0a43", "b491ab2310ef4a799b14c08fa3e09f1c"] params = ["grok-docs-elb", "i-e16bd2d5"] response = self.app.delete("", params=app_utils.jsonEncode(params), headers=self.headers) assertions.assertDeleteSuccessResponse(self, response) self.assertTrue(listMetricIDsMock.called) listMetricIDsMock.assert_called_with( (engineFactoryMock.return_value.connect.return_value.__enter__.return_value), params[1] )
def testDeleteInstancesHandler(self, listMetricIDsMock, engineFactoryMock): """ Test for Delete "/_instances" response is validated for appropriate headers, body and status """ listMetricIDsMock.return_value = \ ["2490fb7a9df5470fa3678530c4cb0a43", "b491ab2310ef4a799b14c08fa3e09f1c"] params = ["grok-docs-elb", "i-e16bd2d5"] response = self.app.delete("", params=app_utils.jsonEncode(params), headers=self.headers) assertions.assertDeleteSuccessResponse(self, response) self.assertTrue(listMetricIDsMock.called) listMetricIDsMock.assert_called_with( (engineFactoryMock.return_value.connect.return_value.__enter__. return_value), params[1])
def testDeleteInstanceHandler(self, listMetricIDsMock, engineFactoryMock): """ Test for Delete "/_instances/<instanceId>" response is validated for appropriate headers, body and status """ listMetricIDsMock.return_value = ["2490fb7a9df5470fa3678530c4cb0a43", "b491ab2310ef4a799b14c08fa3e09f1c"] response = self.app.delete("", headers=self.headers, params=json.dumps(["i-cd660efb"])) assertions.assertDeleteSuccessResponse(self, response) self.assertTrue(listMetricIDsMock.called) listMetricIDsMock.assert_called_once_with( (engineFactoryMock.return_value.connect.return_value.__enter__ .return_value), "i-cd660efb")
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["grok-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, [])
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["grok-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, [])
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 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)