예제 #1
0
    async def test_all_limits_are_defined(self):
        interface = AsgardInterface()

        with aioresponses() as rsps:
            rsps.get(
                f"{settings.ASGARD_API_ADDRESS}/v2/apps",
                status=200,
                payload={
                    "apps": [
                        {
                            "id": "/test_app",
                            "mem": "0.2",
                            "cpus": "0.5",
                            "labels": {
                                "asgard.autoscale.cpu": "0.2",
                                "asgard.autoscale.mem": "0.2",
                                "asgard.autoscale.min_cpu_limit": "0.2",
                                "asgard.autoscale.max_cpu_limit": "2",
                                "asgard.autoscale.min_mem_limit": "0.2",
                                "asgard.autoscale.max_mem_limit": "2",
                            },
                        }
                    ]
                },
            )

            apps = await interface.fetch_all_apps()

        self.assertEqual(1, len(apps))

        self.assertEqual(0.2, apps[0].min_cpu_scale_limit)
        self.assertEqual(2, apps[0].max_cpu_scale_limit)
        self.assertEqual(0.2, apps[0].min_mem_scale_limit)
        self.assertEqual(2, apps[0].max_mem_scale_limit)
예제 #2
0
    async def test_tune_everything_in_multiple_apps(self):
        interface = AsgardInterface()
        app1 = ScalableApp("test1")
        app2 = ScalableApp("test2")
        app3 = ScalableApp("test3")

        decisions = [
            Decision(app1.id, cpu=0.2, mem=10),
            Decision(app2.id, cpu=0.4, mem=20),
            Decision(app3.id, cpu=0.1, mem=9),
        ]

        with aioresponses() as rsps:
            rsps.put(
                f"{settings.ASGARD_API_ADDRESS}/v2/apps",
                status=200,
                payload={
                    "deploymentId": "test2",
                    "version": "1.0"
                },
            )
            applied_decisions = await interface.apply_decisions(decisions)

        self.assertEqual(len(applied_decisions), 3)
        for i in range(len(decisions)):
            self.assertEqual(applied_decisions[i]["id"], decisions[i].id)
            self.assertEqual(applied_decisions[i]["cpus"], decisions[i].cpu)
            self.assertEqual(applied_decisions[i]["mem"], decisions[i].mem)
    async def test_get_app_stats_non_existing_app_id(self):
        scaler = AsgardInterface()

        with aioresponses() as rsps:
            fixture = {
                "stats": {
                    "type": "ASGARD",
                    "errors": {},
                    "cpu_pct": "0",
                    "ram_pct": "0",
                    "cpu_thr_pct": "0",
                }
            }
            app = ScalableApp("app_test1")

            rsps.get(
                f"{settings.ASGARD_API_ADDRESS}/apps/{app.id}/stats/avg-1min",
                status=200,
                payload=fixture,
            )

            stats = await scaler.get_app_stats(app)

            self.assertEqual(None, stats)
            self.assertEqual(None, app.app_stats)
예제 #4
0
    async def test_cpu_decision_is_rounded_to_3_decimal_places(self):
        interface = AsgardInterface()

        decisions = [Decision("test", cpu=0.436_721_072_367)]

        body_fixture = [{"id": "test", "cpus": 0.437}]
        headers_fixture = {
            "Content-Type": "application/json",
            "Authorization": f"Token {settings.AUTOSCALER_AUTH_TOKEN}",
        }

        with aioresponses() as rsps:
            rsps.put(
                f"{settings.ASGARD_API_ADDRESS}/v2/apps",
                status=200,
                payload={
                    "deploymentId": "test",
                    "version": "1.0"
                },
            )

            await interface.apply_decisions(decisions)
            calls = rsps.requests.get(
                ("put", URL(f"{settings.ASGARD_API_ADDRESS}/v2/apps")))

            self.assertIsNotNone(calls)
            self.assertEqual(body_fixture, calls[0].kwargs.get("json"))
            self.assertEqual(
                headers_fixture,
                interface._asgard_client._http_client.default_headers,
            )
    async def test_get_all_apps_which_should_be_scaled_all_apps_should(self):
        scaler = AsgardInterface()

        with aioresponses() as rsps:
            payload = {
                "apps": [
                    {
                        "id": "/test_app1",
                        "cpus": "0.2",
                        "mem": "0.2",
                        "labels": {
                            "asgard.autoscale.cpu": 0.3,
                            "asgard.autoscale.mem": 0.8,
                        },
                    },
                    {
                        "id": "/test_app2",
                        "cpus": "0.2",
                        "mem": "0.2",
                        "labels": {
                            "asgard.autoscale.cpu": 0.1,
                            "asgard.autoscale.mem": 0.1,
                        },
                    },
                    {
                        "id": "/test_app3",
                        "cpus": "0.2",
                        "mem": "0.2",
                        "labels": {
                            "asgard.autoscale.cpu": 0.5,
                            "asgard.autoscale.mem": 0.7,
                        },
                    },
                ]
            }

            fixture = [
                ScalableApp("test_app1", cpu_threshold=0.3, mem_threshold=0.8),
                ScalableApp("test_app2", cpu_threshold=0.1, mem_threshold=0.1),
                ScalableApp("test_app3", cpu_threshold=0.5, mem_threshold=0.7),
            ]

            rsps.get(
                f"{settings.ASGARD_API_ADDRESS}/v2/apps",
                status=200,
                payload=payload,
            )

            apps = await scaler.get_all_scalable_apps()

            self.assertEqual(len(fixture), len(apps))

            for i in range(len(fixture)):
                self.assertEqual(fixture[i].id, apps[i].id)
                self.assertEqual(
                    fixture[i].cpu_threshold, apps[i].cpu_threshold
                )
                self.assertEqual(
                    fixture[i].mem_threshold, apps[i].mem_threshold
                )
    async def test_get_app_stats_existing_app_id(self):
        scaler = AsgardInterface()

        with aioresponses() as rsps:
            payload = {
                "stats": {
                    "type": "ASGARD",
                    "errors": {},
                    "cpu_pct": "0.93",
                    "ram_pct": "8.91",
                    "cpu_thr_pct": "0.06",
                }
            }
            app = ScalableApp("app_test1")

            rsps.get(
                f"{settings.ASGARD_API_ADDRESS}/apps/{app.id}/stats/avg-1min",
                status=200,
                payload=payload,
            )

            fixture = AppStats(cpu_usage=0.93, mem_usage=8.91)

            app_stats = await scaler.get_app_stats(app)

            self.assertEqual(fixture.cpu_usage, app_stats.cpu_usage)
            self.assertEqual(fixture.mem_usage, app_stats.mem_usage)
예제 #7
0
    async def test_only_mem_should_not_be_scaled_mem_ignored(self):
        interface = AsgardInterface()

        with aioresponses() as rsps:
            rsps.get(
                f"{settings.ASGARD_API_ADDRESS}/v2/apps",
                status=200,
                payload={
                    "apps": [
                        {
                            "id": "/test_app",
                            "mem": "0.2",
                            "cpus": "0.5",
                            "labels": {
                                "asgard.autoscale.cpu": "0.2",
                                "asgard.autoscale.mem": "0.2",
                            },
                        },
                        {
                            "id": "/test_app2",
                            "cpus": "0.1",
                            "mem": "0.2",
                            "labels": {
                                "asgard.autoscale.cpu": "0.2",
                                "asgard.autoscale.mem": "0.2",
                                "asgard.autoscale.ignore": "mem",
                            },
                        },
                        {
                            "id": "/test_app3",
                            "cpus": "0.1",
                            "mem": "0.6",
                            "labels": {
                                "asgard.autoscale.cpu": "0.2",
                                "asgard.autoscale.mem": "0.2",
                            },
                        },
                    ]
                },
            )

            apps = await interface.fetch_all_apps()

        self.assertEqual(3, len(apps))

        self.assertEqual(True, apps[0].is_set_to_scale())
        self.assertEqual(True, apps[0].is_set_to_scale_cpu())
        self.assertEqual(True, apps[0].is_set_to_scale_mem())

        self.assertEqual(True, apps[1].is_set_to_scale())
        self.assertEqual(True, apps[1].is_set_to_scale_cpu())
        self.assertEqual(False, apps[1].is_set_to_scale_mem())

        self.assertEqual(True, apps[2].is_set_to_scale())
        self.assertEqual(True, apps[2].is_set_to_scale_cpu())
        self.assertEqual(True, apps[2].is_set_to_scale_mem())
예제 #8
0
파일: app.py 프로젝트: shairez/asgard-api
async def scale_all_apps(app: App):
    cloud_interface = AsgardInterface()
    state_checker = PeriodicStateChecker(cloud_interface)
    decision_maker = DecisionComponent()

    logger.debug({"AUTOSCALER": "iniciando autoscaler"})
    apps_stats = await state_checker.get_scalable_apps_stats()
    logger.debug({"AUTOSCALER_FETCH_APPS": [app.id for app in apps_stats]})
    scaling_decisions = decision_maker.decide_scaling_actions(apps_stats)
    await cloud_interface.apply_decisions(scaling_decisions)
    async def test_sending_auth_in_headers(self):
        headers_fixture = {
            "Content-Type": "application/json",
            "Authorization": f"Token {settings.AUTOSCALER_AUTH_TOKEN}",
        }

        scaler = AsgardInterface()

        self.assertEqual(
            scaler._asgard_client._http_client.default_headers, headers_fixture
        )
예제 #10
0
    async def test_get_all_apps_data_no_data_found(self):
        scaler = AsgardInterface()

        with aioresponses() as rsps:
            rsps.get(
                f"{settings.ASGARD_API_ADDRESS}/v2/apps",
                status=200,
                payload={"apps": []},
            )

            apps = await scaler.fetch_all_apps()

        self.assertEqual([], apps)
예제 #11
0
    async def test_get_all_apps_data(self):
        scaler = AsgardInterface()

        with aioresponses() as rsps:
            rsps.get(
                f"{settings.ASGARD_API_ADDRESS}/v2/apps",
                status=200,
                payload={
                    "apps": [
                        {
                            "id": "/test_app",
                            "cpus": "0.1",
                            "mem": "0.2",
                            "labels": {},
                        },
                        {
                            "id": "/test_app2",
                            "cpus": "0.1",
                            "mem": "0.2",
                            "labels": {},
                        },
                        {
                            "id": "/test_app3",
                            "cpus": "0.1",
                            "mem": "0.2",
                            "labels": {},
                        },
                        {
                            "id": "/test_app4",
                            "cpus": "0.1",
                            "mem": "0.2",
                            "labels": {},
                        },
                    ]
                },
            )
            apps = await scaler.fetch_all_apps()

        fixture = [
            ScalableApp("test_app"),
            ScalableApp("test_app2"),
            ScalableApp("test_app3"),
            ScalableApp("test_app4"),
        ]

        self.assertEqual(len(fixture), len(apps))

        for i in range(len(fixture)):
            self.assertEqual(fixture[i].id, apps[i].id)
예제 #12
0
    async def test_everything_should_be_scaled_all_apps(self):
        interface = AsgardInterface()

        with aioresponses() as rsps:
            rsps.get(
                f"{settings.ASGARD_API_ADDRESS}/v2/apps",
                status=200,
                payload={
                    "apps": [
                        {
                            "id": "/test_app",
                            "cpus": "0.1",
                            "mem": "0.2",
                            "labels": {
                                "asgard.autoscale.cpu": "0.2",
                                "asgard.autoscale.mem": "0.2",
                            },
                        },
                        {
                            "id": "/test_app2",
                            "cpus": "0.1",
                            "mem": "0.2",
                            "labels": {
                                "asgard.autoscale.cpu": "0.2",
                                "asgard.autoscale.mem": "0.2",
                            },
                        },
                        {
                            "id": "/test_app3",
                            "cpus": "0.1",
                            "mem": "0.2",
                            "labels": {
                                "asgard.autoscale.cpu": "0.2",
                                "asgard.autoscale.mem": "0.2",
                            },
                        },
                    ]
                },
            )

            apps = await interface.fetch_all_apps()

        self.assertEqual(3, len(apps))

        for i in range(3):
            self.assertEqual(True, apps[i].is_set_to_scale())
            self.assertEqual(True, apps[i].is_set_to_scale_cpu())
            self.assertEqual(True, apps[i].is_set_to_scale_mem())
예제 #13
0
    async def test_get_all_apps_which_should_be_scaled_no_app_should(self):
        scaler = AsgardInterface()

        with aioresponses() as rsps:
            fixture = {
                "apps": [
                    {
                        "id": "/test_app1",
                        "cpus": "0.2",
                        "mem": "0.2",
                        "labels": {
                            "asgard.autoscale.cpu": 0.3,
                            "asgard.autoscale.mem": 0.8,
                            "asgard.autoscale.ignore": "all",
                        },
                    },
                    {
                        "id": "/test_app2",
                        "cpus": "0.2",
                        "mem": "0.2",
                        "labels": {
                            "asgard.autoscale.cpu": 0.1,
                            "asgard.autoscale.mem": 0.1,
                            "asgard.autoscale.ignore": "cpu;mem",
                        },
                    },
                    {
                        "id": "/test_app3",
                        "cpus": "0.2",
                        "mem": "0.2",
                        "labels": {
                            "asgard.autoscale.cpu": 0.5,
                            "asgard.autoscale.ignore": "cpu",
                        },
                    },
                ]
            }

            rsps.get(
                f"{settings.ASGARD_API_ADDRESS}/v2/apps",
                status=200,
                payload=fixture,
            )

            apps = await scaler.get_all_scalable_apps()

            self.assertEqual([], apps)
            self.assertEqual(0, len(apps))
예제 #14
0
    async def test_tune_one_thing_in_one_app(self):
        interface = AsgardInterface()
        app = ScalableApp("test")
        decisions = [Decision(app.id, cpu=0.3)]

        with aioresponses() as rsps:
            rsps.put(
                f"{settings.ASGARD_API_ADDRESS}/v2/apps",
                status=200,
                payload={
                    "deploymentId": "test1",
                    "version": "1.0"
                },
            )
            applied_decisions = await interface.apply_decisions(decisions)

        self.assertEqual(len(applied_decisions), 1)
        self.assertEqual(applied_decisions[0]["id"], decisions[0].id)
        self.assertEqual(applied_decisions[0]["cpus"], decisions[0].cpu)
        self.assertEqual("mem" in applied_decisions[0], False)
예제 #15
0
    async def test_tune_multiple_apps_with_different_params(self):
        interface = AsgardInterface()
        app1 = ScalableApp("test1")
        app2 = ScalableApp("test2")
        app3 = ScalableApp("test3")

        decisions = [
            Decision(app1.id, mem=10),
            Decision(app2.id, cpu=0.4),
            Decision(app3.id, cpu=0.1, mem=9),
        ]

        with aioresponses() as rsps:
            rsps.put(
                f"{settings.ASGARD_API_ADDRESS}/v2/apps",
                status=200,
                payload={
                    "deploymentId": "test2",
                    "version": "1.0"
                },
            )
            applied_decisions = await interface.apply_decisions(decisions)

        self.assertEqual(len(applied_decisions), 3)

        self.assertEqual(applied_decisions[0]["id"], decisions[0].id)
        self.assertEqual(applied_decisions[0]["mem"], decisions[0].mem)
        self.assertEqual("cpus" in applied_decisions[0], False)

        self.assertEqual(applied_decisions[1]["id"], decisions[1].id)
        self.assertEqual(applied_decisions[1]["cpus"], decisions[1].cpu)
        self.assertEqual("mem" in applied_decisions[1], False)

        self.assertEqual(applied_decisions[2]["id"], decisions[2].id)
        self.assertEqual(applied_decisions[2]["mem"], decisions[2].mem)
        self.assertEqual(applied_decisions[2]["cpus"], decisions[2].cpu)