Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Waffles Part 2: Move waffle switches to django-waffle 🧇 #15229

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions bedrock/base/management/commands/import_waffle_switches.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.

from django.core.management.base import BaseCommand

from waffle.models import Switch

from bedrock.base.models import ConfigValue
from bedrock.utils.management.decorators import alert_sentry_on_exception


@alert_sentry_on_exception
class Command(BaseCommand):
def handle(self, *args, **options):
prefix = "SWITCH_"

for config in ConfigValue.objects.all():
# Ignore funnelcakes and other yummy things.
if not config.name.startswith(prefix):
continue

# Remove prefix.
name = config.name[len(prefix) :]
# Set active to boolean.
active = config.value == "on"

switch, created = Switch.objects.update_or_create(name=name, defaults={"active": active})
print(f"{'Created new' if created else 'Updated'} switch: {name} = {'on' if active else 'off'}")
131 changes: 0 additions & 131 deletions bedrock/base/management/commands/update_www_config.py

This file was deleted.

4 changes: 0 additions & 4 deletions bedrock/base/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,3 @@ class Meta:

def __str__(self):
return f"{self.name}={self.value}"


def get_config_dict():
return {c.name: c.value for c in ConfigValue.objects.all()}
14 changes: 2 additions & 12 deletions bedrock/base/templatetags/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,8 @@
@library.global_function
@jinja2.pass_context
def switch(cxt, name, locales=None):
"""A template helper that replaces waffle
* All calls default to True when DEV setting is True (for the listed locales).
* If the env var is explicitly false it will be false even when DEV = True.
* Otherwise the call is False by default and True is a specific env var exists and is truthy.
For example:
{% if switch('dude-and-walter') %}
would check for an environment variable called `SWITCH_DUDE_AND_WALTER`. The string from the
`switch()` call is converted to uppercase and dashes replaced with underscores.
"""
A template helper around `base.waffle.switch`. See docs there for details.
If the `locales` argument is a list of locales then it will only check the switch in those
locales, and return False otherwise. The `locales` argument could also contain a "locale group",
Expand Down
35 changes: 28 additions & 7 deletions bedrock/base/tests/test_waffle.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,35 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.

from unittest.mock import patch
from django.test import override_settings

from django.conf import settings
import pytest
from waffle.testutils import override_switch

from bedrock.base import waffle
from bedrock.base.waffle import switch

pytestmark = [
pytest.mark.django_db,
]

@patch("bedrock.base.waffle.config")
def test_switch_helper(config_mock):
waffle.switch("dude-and-walter")
config_mock.assert_called_with("DUDE_AND_WALTER", namespace="SWITCH", default=str(settings.DEV), parser=bool)

@override_settings(DEV=True)
def test_switch_helper_dev_true():
# When no switch exists, we return the value of `settings.DEV`.
assert switch("dude-and-walter") is True
# Then test explicityly set switch values.
with override_switch("DUDE_AND_WALTER", active=True):
assert switch("dude-and-walter") is True
with override_switch("DUDE_AND_WALTER", active=False):
assert switch("dude-and-walter") is False


@override_settings(DEV=False)
def test_switch_helper_dev_false():
# When no switch exists, we return the value of `settings.DEV`.
assert switch("dude-and-walter") is False
# Then test explicityly set switch values.
with override_switch("DUDE_AND_WALTER", active=True):
assert switch("dude-and-walter") is True
with override_switch("DUDE_AND_WALTER", active=False):
assert switch("dude-and-walter") is False
82 changes: 0 additions & 82 deletions bedrock/base/tests/test_waffle_config.py

This file was deleted.

37 changes: 24 additions & 13 deletions bedrock/base/waffle.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,39 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.

"""
Replacement library (function really) for Waffle that uses environment variables.
"""

from django.conf import settings

from bedrock.base.waffle_config import config
from waffle import switch_is_active


def switch(name):
"""A template helper that replaces waffle
"""
A wrapper around django-waffle's `switch_is_active`.

* All calls default to True when DEV setting is True.
* If the env var is explicitly false it will be false even when DEV = True.
* Otherwise the call is False by default and True is a specific env var exists and is truthy.
It will take whatever name you pass to it (must be only numbers, letters, and dashes), convert
it to uppercase, convert dashes to underscores, then call waffle's `switch_is_active`.

* When DEV=True
- When switch doesn't exist -> True
- When switch exists and is True -> True
- When switch exists and is False -> False
* When Dev=False
- When switch doesn't exist -> False
- When switch exists and is True -> True
- When switch exists and is False -> False

For example:

{% if switch('dude-and-walter') %}

would check for an environment variable called `SWITCH_DUDE_AND_WALTER`. The string from the
`switch()` call is converted to uppercase and dashes replaced with underscores.
would check for a waffle switch called `DUDE_AND_WALTER` and return True if active, else False.

"""
env_name = name.upper().replace("-", "_")
return config(env_name, default=str(settings.DEV), parser=bool, namespace="SWITCH")
switch_name = name.upper().replace("-", "_")
active = switch_is_active(switch_name)
# With `settings.WAFFLE_SWITCH_DEFAULT` set to `None`, we can test if a switch is explicitly set or not.
# Here, active is None we know the switch doesn't exist so we default to what `settings.DEV` is.
if active is None:
return settings.DEV
# Otherwise we return the defined switch value.
return active
Loading