From c7fb8916009e4e3d85e458f5ccd5293a78f42bfe Mon Sep 17 00:00:00 2001 From: Robert Raposa Date: Thu, 13 Aug 2020 11:33:07 -0400 Subject: [PATCH] add flags and switches to toggle state Adds basic waffle flag and waffle switch data to the toggle state endpoint. ARCHBOM-1427 --- .../waffle_utils/tests/test_views.py | 20 +++++ openedx/core/djangoapps/waffle_utils/views.py | 78 ++++++++++++++++++- 2 files changed, 96 insertions(+), 2 deletions(-) diff --git a/openedx/core/djangoapps/waffle_utils/tests/test_views.py b/openedx/core/djangoapps/waffle_utils/tests/test_views.py index 0d5c7c0beb..67cd79f8a5 100644 --- a/openedx/core/djangoapps/waffle_utils/tests/test_views.py +++ b/openedx/core/djangoapps/waffle_utils/tests/test_views.py @@ -3,10 +3,16 @@ Tests for waffle utils views. """ from django.test import TestCase from rest_framework.test import APIRequestFactory +from waffle.testutils import override_switch from student.tests.factories import UserFactory +from .. import WaffleFlag, WaffleFlagNamespace, WaffleSwitch, WaffleSwitchNamespace from ..views import ToggleStateView +from ..testutils import override_waffle_flag + +TEST_WAFFLE_FLAG_NAMESPACE = WaffleFlagNamespace('test') +TEST_WAFFLE_FLAG = WaffleFlag(TEST_WAFFLE_FLAG_NAMESPACE, 'flag') class ToggleStateViewTests(TestCase): @@ -20,6 +26,20 @@ class ToggleStateViewTests(TestCase): response = self._get_toggle_state_response(is_staff=False) self.assertEqual(response.status_code, 403) + @override_waffle_flag(TEST_WAFFLE_FLAG, True) + def test_response_with_waffle_flag(self): + response = self._get_toggle_state_response(is_staff=True) + self.assertIn('waffle_flags', response.data) + self.assertTrue(response.data['waffle_flags']) + self.assertEqual(response.data['waffle_flags'][0]['name'], 'test.flag') + + @override_switch('test.switch', True) + def test_response_with_waffle_switch(self): + response = self._get_toggle_state_response(is_staff=True) + self.assertIn('waffle_switches', response.data) + self.assertTrue(response.data['waffle_switches']) + self.assertEqual(response.data['waffle_switches'][0]['name'], 'test.switch') + def _get_toggle_state_response(self, is_staff=True): request = APIRequestFactory().get('/api/toggles/state/') user = UserFactory() diff --git a/openedx/core/djangoapps/waffle_utils/views.py b/openedx/core/djangoapps/waffle_utils/views.py index 3a35accca2..d791078294 100644 --- a/openedx/core/djangoapps/waffle_utils/views.py +++ b/openedx/core/djangoapps/waffle_utils/views.py @@ -1,9 +1,14 @@ -""" Views that we will use to view toggle state in edx-platform. """ +""" +Views that we will use to view toggle state in edx-platform. +""" +from collections import OrderedDict + from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthentication from edx_rest_framework_extensions.permissions import IsStaff from rest_framework.authentication import SessionAuthentication from rest_framework import permissions, views from rest_framework.response import Response +from waffle.models import Flag, Switch class ToggleStateView(views.APIView): @@ -14,5 +19,74 @@ class ToggleStateView(views.APIView): permission_classes = (permissions.IsAuthenticated, IsStaff,) def get(self, request): - response = {'hello': 'world'} + response = OrderedDict() + response['waffle_flags'] = self._get_all_waffle_flags() + response['waffle_switches'] = self._get_all_waffle_switches() return Response(response) + + def _get_all_waffle_switches(self): + """ + Gets all waffle switches and their state. + """ + switches_dict = {} + self._add_waffle_switch_state(switches_dict) + switch_list = list(switches_dict.values()) + switch_list.sort(key=lambda toggle: toggle['name']) + return switch_list + + def _add_waffle_switch_state(self, switches_dict): + """ + Add waffle switch state from the waffle Switch model. + """ + waffle_switches = Switch.objects.all() + for switch_data in waffle_switches: + switch = self._get_or_create_toggle_response(switches_dict, switch_data.name) + switch['is_active'] = 'true' if switch_data.active else 'false' + if switch_data.note: + switch['note'] = switch_data.note + switch['created'] = str(switch_data.created) + switch['modified'] = str(switch_data.modified) + + def _get_all_waffle_flags(self): + """ + Gets all waffle flags and their state. + """ + flags_dict = {} + self._add_waffle_flag_state(flags_dict) + flag_list = list(flags_dict.values()) + flag_list.sort(key=lambda toggle: toggle['name']) + return flag_list + + def _add_waffle_flag_state(self, flags_dict): + """ + Add waffle flag state from the waffle Flag model. + """ + waffle_flags = Flag.objects.all() + for flag_data in waffle_flags: + flag = self._get_or_create_toggle_response(flags_dict, flag_data.name) + if flag_data.everyone is True: + everyone = 'yes' + elif flag_data.everyone is False: + everyone = 'no' + else: + everyone = 'unknown' + flag['everyone'] = everyone + if flag_data.note: + flag['note'] = flag_data.note + flag['created'] = str(flag_data.created) + flag['modified'] = str(flag_data.modified) + + def _get_or_create_toggle_response(self, toggles_dict, toggle_name): + """ + Gets or creates a toggle response dict and adds it to the toggles_dict. + + Returns: + Either the pre-existing toggle response, or a new toggle dict with its name set. + + """ + if toggle_name in toggles_dict: + return toggles_dict[toggle_name] + toggle = OrderedDict() + toggle['name'] = toggle_name + toggles_dict[toggle_name] = toggle + return toggle