Esempio n. 1
0
def checkQuotaForInstanceAndRaise(conn, instanceName):
    """ Perform instance quota check and raise QuotaError exception if request to
  create a model for `instanceName` would result in a new "instance" being
  created beyond quota.

  This function answers the question:

    Is there room to add a new model for a new, or existing instance?

  And raises an exception if the answer is no.

  :param conn: SQLAlchemy connection object
  :type conn: sqlalchemy.engine.Connection
  :param instanceName: Instance name
  :type instanceName str:

  :raises: grok.app.exceptions.QuotaError
  """
    instanceCount = repository.getInstanceCount(conn)
    instanceQuota = Quota.getInstanceQuota()

    if instanceCount >= instanceQuota:
        if not repository.listMetricIDsForInstance(conn, instanceName):
            raise QuotaError(
                "Server limit exceeded; edition=%s; count=%i; limit=%i." %
                (product.get("edition",
                             "type").title(), instanceCount, instanceQuota))
    def testPOSTAutostacksQuota(self, adapterMock, quotaRepositoryMock,
                                _repositoryMock):
        quotaRepositoryMock.getInstanceCount.return_value = 0

        adapterMock.return_value.createAutostack.side_effect = QuotaError()

        with self.assertRaises(AppError) as e:
            self.app.post("/", self.jsonAutostack, headers=self.headers)

        self.assertIn("Bad response: 403 Forbidden", str(e.exception))
        self.assertTrue(adapterMock.return_value.createAutostack.called)
class InstanceDefaultsHandlerTest(unittest.TestCase):
    """Unit tests for class InstanceDefaultsHandler from Instances API."""
    def setUp(self):
        self.app = TestApp(instances_api.app.wsgifunc())
        self.headers = getDefaultHTTPHeaders(config)

    @patch.object(repository, "listMetricIDsForInstance", autospec=True)
    @patch("grok.app.webservices.models_api.ModelHandler.createModel",
           new=Mock(spec_set=models_api.ModelHandler.createModel))
    def testInstanceDefaultsHandlerPOST(self, listMetricIDsMock,
                                        _engineFactoryMock):
        """
    Test for POST "/_instances/region/namespace/instanceId"
    response is validated for appropriate headers, body and status
    """

        listMetricIDsMock.return_value = []

        region = "us-west-2"

        # Currently we are not supporting certain namespaces
        # unsupportedNamespaces reflects such unsupported namespaces
        # These namespaces are currently validated for "400 Bad Request"
        # and expected error message.
        # Update this list with changes in namespace support
        unsupportedNamespaces = ("Billing", "StorageGateway")

        for namespace in unsupportedNamespaces:
            response = self.app.post("/%s/AWS/%s/abcd1234" %
                                     (region, namespace),
                                     headers=self.headers,
                                     status="*")
            assertions.assertBadRequest(self, response, "json")
            result = json.loads(response.body)["result"]
            self.assertTrue(result.startswith("Not supported."))

        cwAdapter = datasource.createDatasourceAdapter("cloudwatch")
        supportedNamespaces = set()
        for resourceInfo in cwAdapter.describeSupportedMetrics().values():
            for metricInfo in resourceInfo.values():
                supportedNamespaces.add(metricInfo["namespace"])

        for namespace in supportedNamespaces:
            response = self.app.post("/%s/%s/abcd1234" % (region, namespace),
                                     headers=self.headers)
            assertions.assertSuccess(self, response)
            result = app_utils.jsonDecode(response.body)
            self.assertIsInstance(result, dict)
            self.assertEqual(result, {"result": "success"})

    @patch.object(repository, "getMetricCountForServer", autospec=True)
    @patch("grok.app.webservices.models_api.ModelHandler.createModel",
           new=Mock(spec_set=models_api.ModelHandler.createModel,
                    side_effect=QuotaError("Server limit reached.")))
    def testInstanceDefaultsHandlerPOSTQuotaError(self,
                                                  getMetricCountForServerMock,
                                                  _engineFactoryMock):
        """
    Test for POST "/_instances/region/namespace/instanceId"
    Test for QuotaError thrown when reached number of server limit
    reached
    """

        getMetricCountForServerMock.return_value = 0

        response = self.app.post("/us-west-2/AWS/EC2/abcd1234",
                                 headers=self.headers,
                                 status="*")
        assertions.assertForbiddenResponse(self, response)
        result = app_utils.jsonDecode(response.body)
        self.assertEqual(result, {"result": "Server limit reached."})

    @patch("grok.app.webservices.models_api.ModelHandler.createModel",
           new=Mock(spec_set=models_api.ModelHandler.createModel))
    def testInstanceDefaultsHandlerPOSTWithoutInstanceId(
            self, _engineFactoryMock):
        """
    Test for POST "/_instances/region/namespace/instanceId" without instanceId
    response is validated for appropriate headers, body and status
    """
        response = self.app.post("/us-west-2/AWS/EC2/",
                                 headers=self.headers,
                                 status="*")
        assertions.assertBadRequest(self, response, "json")
        self.assertIn("Invalid request", response.body)

    @patch("grok.app.webservices.models_api.ModelHandler.createModel",
           new=Mock(spec_set=models_api.ModelHandler.createModel))
    def testInstanceDefaultsHandlerPOSTInvalidNamespace(
            self, _engineFactoryMock):
        """
    Test for POST "/_instances/region/namespace/instanceId" with invalid
    namespace
    response is validated for appropriate headers, body and status
    """
        response = self.app.post("/us-west-2/AWS/foo/abcd1234",
                                 headers=self.headers,
                                 status="*")
        assertions.assertBadRequest(self, response, "json")
        self.assertIn("Not supported.", response.body)

    @patch("grok.app.webservices.models_api.ModelHandler.createModel",
           new=Mock(spec_set=models_api.ModelHandler.createModel))
    def testInstanceDefaultsHandlerPOSTInvalidNamespeceInsteadAWS(
            self, _engineFactoryMock):
        """
    Test for POST "/_instances/region/namespace/instanceId" with invalid
    namespace.
    response is validated for appropriate headers, body and status
    """
        response = self.app.post("/us-west-2/foo/EC2/abcd1234",
                                 headers=self.headers,
                                 status="*")
        assertions.assertBadRequest(self, response, "json")
        self.assertIn("Not supported.", response.body)

    @patch("grok.app.webservices.models_api.ModelHandler.createModel",
           new=Mock(spec_set=models_api.ModelHandler.createModel))
    def testInstanceDefaultsHandlerPOSTInvalidRegion(self, _engineFactoryMock):
        """
    Test for POST "/_instances/region/namespace/instanceId" with invalid
    region
    response is validated for appropriate headers, body and status
    """
        response = self.app.post("/fake-region/AWS/EC2/abcd1234",
                                 headers=self.headers,
                                 status="*")
        assertions.assertBadRequest(self, response, "json")
        self.assertIn("Not supported.", response.body)