Example #1
0
 def get_toggle(self, slug):
     if slug not in [f.slug for f, _ in self.features()]:
         raise Http404()
     try:
         return Toggle.get(slug)
     except ResourceNotFound:
         return Toggle(slug=slug)
Example #2
0
    def load_objects(self, object_strings, force=False, dry_run=False):
        from corehq.toggles.models import Toggle
        count = 0
        for toggle_json in object_strings:
            if dry_run:
                count += 1
                continue

            toggle_dict = json.loads(toggle_json)
            slug = toggle_dict['slug']
            try:
                existing_toggle = Toggle.get(slug)
            except ResourceNotFound:
                Toggle.wrap(toggle_dict).save()
            else:
                existing_items = set(existing_toggle.enabled_users)
                items_to_load = set(toggle_dict['enabled_users'])
                enabled_for = existing_items | items_to_load
                existing_toggle.enabled_users = list(enabled_for)
                existing_toggle.save()

            count += 1

        self.stdout.write('Loaded {} Toggles'.format(count))
        return Counter({'Toggle': count})
Example #3
0
 def get_toggle(self):
     if not self.static_toggle:
         raise Http404()
     try:
         return Toggle.get(self.toggle_slug)
     except ResourceNotFound:
         return Toggle(slug=self.toggle_slug)
Example #4
0
def _get_toggles_to_migrate(domain):
    from corehq.toggles import all_toggles, NAMESPACE_DOMAIN
    from corehq.toggles.models import Toggle
    from corehq.toggles.shortcuts import namespaced_item

    domain_item = namespaced_item(domain, NAMESPACE_DOMAIN)
    usernames = set(get_all_usernames_by_domain(domain))

    for toggle in all_toggles() + all_previews():
        try:
            current_toggle = Toggle.get(toggle.slug)
        except ResourceNotFound:
            continue

        enabled_for = set(current_toggle.enabled_users)

        new_toggle = Toggle(slug=toggle.slug, enabled_users=[])
        if domain_item in enabled_for:
            new_toggle.enabled_users.append(domain_item)

        enabled_users = enabled_for & usernames
        new_toggle.enabled_users.extend(list(enabled_users))

        if new_toggle.enabled_users:
            yield new_toggle.to_json()
    def test_load_toggles(self):
        from corehq.toggles.models import Toggle

        dumped_data = [
            json.dumps(Toggle(slug=slug, enabled_users=items).to_json())
            for slug, items in self.expected_items.items()
        ]

        existing_toggle_docs = []
        for toggle in self.mocked_toggles.values():
            doc_dict = toggle.to_json()
            expected = self.expected_items[toggle.slug]
            # leave only items that aren't in the dump
            doc_dict['enabled_users'] = [
                item for item in doc_dict['enabled_users']
                if item not in expected
            ]
            existing_toggle_docs.append(doc_dict)

        with mock_out_couch(docs=existing_toggle_docs):
            ToggleLoader().load_objects(dumped_data)

            for mocked_toggle in self.mocked_toggles.values():
                loaded_toggle = Toggle.get(mocked_toggle.slug)
                self.assertItemsEqual(mocked_toggle.enabled_users,
                                      loaded_toggle.enabled_users)
Example #6
0
 def test_move_nonexistent_source(self):
     dsa = uuid.uuid4().hex
     try:
         Toggle(slug=dsa, enabled_users=['kieran']).save()
         move_toggles('missing-src', dsa)
         self.assertEqual(['kieran'], Toggle.get(dsa).enabled_users)
     finally:
         MigrationHelperTest._delete_toggles(dsa)
Example #7
0
 def test_move_nonexistent_destination(self):
     moz, dsa = [uuid.uuid4().hex for i in range(2)]
     try:
         Toggle(slug=moz, enabled_users=['claire']).save()
         move_toggles(moz, dsa)
         dsa_toggle = Toggle.get(dsa)
         self.assertEqual(['claire'], dsa_toggle.enabled_users)
         with self.assertRaises(ResourceNotFound):
             Toggle.get(moz)
     finally:
         MigrationHelperTest._delete_toggles(moz, dsa)
    def _get_mocked_toggles(self):
        from corehq.toggles.models import Toggle, generate_toggle_id
        from corehq.toggles.shortcuts import namespaced_item

        mocked_toggles = {
            toggle.slug: Toggle(_id=generate_toggle_id(toggle.slug),
                                slug=toggle.slug)
            for toggle in random.sample(all_toggles(), 3)
        }
        toggles = list(mocked_toggles.values())
        domain_item = namespaced_item(self.domain_name, NAMESPACE_DOMAIN)
        toggles[0].enabled_users = [domain_item]
        toggles[1].enabled_users = ['user1', 'other-user', 'user2']
        toggles[2].enabled_users = [
            'user1', domain_item,
            namespaced_item('other_domain', NAMESPACE_DOMAIN)
        ]

        expected_items = {
            toggles[0].slug: [domain_item],
            toggles[1].slug: ['user1', 'user2'],
            toggles[2].slug: ['user1', domain_item],
        }

        return mocked_toggles, expected_items
Example #9
0
 def test_move(self):
     moz, dsa = [uuid.uuid4().hex for i in range(2)]
     try:
         moz_users = ['marco', 'lauren', 'claire']
         dsa_users = ['kieran', 'jolani', 'claire']
         Toggle(slug=moz, enabled_users=moz_users).save()
         Toggle(slug=dsa, enabled_users=dsa_users).save()
         move_toggles(moz, dsa)
         # ensure original is delted
         with self.assertRaises(ResourceNotFound):
             Toggle.get(moz)
         dsa_toggle = Toggle.get(dsa)
         expected_users = set(moz_users) | set(dsa_users)
         self.assertEqual(len(expected_users),
                          len(dsa_toggle.enabled_users))
         self.assertEqual(expected_users, set(dsa_toggle.enabled_users))
     finally:
         MigrationHelperTest._delete_toggles(moz, dsa)
Example #10
0
def _get_toggle_item_count(toggles):
    count = 0
    for toggle in toggles:
        try:
            toggle_doc = Toggle.get(toggle.slug)
        except ResourceNotFound:
            count += 1
            continue

        count += len(set(toggle_doc.enabled_users))
    return count
Example #11
0
def _set_use_livequery(apps, schema_editor):
    toggle_id = generate_toggle_id('livequery_sync')
    try:
        toggle_doc = Toggle.get_db().get(toggle_id)
    except ResourceNotFound:
        # Flag isn't enabled for anyone on this server
        return
    for user in toggle_doc.get('enabled_users', []):
        domain_obj = Domain.get_by_name(user.split('domain:')[1])
        if domain_obj and not domain_obj.use_livequery:
            domain_obj.use_livequery = True
            domain_obj.save()
Example #12
0
 def page_context(self):
     toggles = list(all_toggles())
     domain_counts = {}
     active_domain_count = {}
     user_counts = {}
     last_used = {}
     last_modified = {}
     if self.show_usage:
         for t in toggles:
             counter = Counter()
             try:
                 usage = Toggle.get(t.slug)
             except ResourceNotFound:
                 domain_counts[t.slug] = 0
                 user_counts[t.slug] = 0
                 active_domain_count[t.slug] = 0
             else:
                 for u in usage.enabled_users:
                     namespace = u.split(":", 1)[0] if u.find(":") != -1 else NAMESPACE_USER
                     counter[namespace] += 1
                 usage_info = _get_usage_info(usage)
                 domain_counts[t.slug] = counter.get(NAMESPACE_DOMAIN, 0)
                 active_domain_count[t.slug] = usage_info["_active_domains"]
                 user_counts[t.slug] = counter.get(NAMESPACE_USER, 0)
                 last_used[t.slug] = usage_info["_latest"]
                 last_modified[t.slug] = usage.last_modified
     return {
         'domain_counts': domain_counts,
         'active_domain_count': active_domain_count,
         'page_url': self.page_url,
         'show_usage': self.show_usage,
         'toggles': toggles,
         'tags': ALL_TAG_GROUPS,
         'user_counts': user_counts,
         'last_used': last_used,
         'last_modified': last_modified,
     }
Example #13
0
def move_toggles(from_toggle_id, to_toggle_id):
    """
    Moves all enabled items from one toggle to another.
    """
    try:
        from_toggle = Toggle.get(from_toggle_id)
    except ResourceNotFound:
        # if no source found this is a noop
        return
    try:
        to_toggle = Toggle.get(to_toggle_id)
    except ResourceNotFound:
        to_toggle = Toggle(slug=to_toggle_id, enabled_users=[])

    for item in from_toggle.enabled_users:
        if item not in to_toggle.enabled_users:
            to_toggle.enabled_users.append(item)
            namespace, item = parse_toggle(item)

    to_toggle.save()
    from_toggle.delete()
Example #14
0
 def _delete_toggles(self, *toggles):
     for toggle in toggles:
         try:
             Toggle.get(toggle).delete()
         except ResourceNotFound:
             pass
Example #15
0
def _get_toggle_rows(toggle):
    relevant_environments = toggle.relevant_environments
    relevant_to_env = bool(
        not relevant_environments
        or settings.SERVER_ENVIRONMENT in relevant_environments)
    toggle_data = {
        "env": settings.SERVER_ENVIRONMENT,
        "label": toggle.label,
        "slug": toggle.slug,
        "tag": toggle.tag.name,
        "type": toggle.__class__.__name__,
        "help": toggle.help_link,
        "description": toggle.description,
        "randomness": getattr(toggle, "randomness", "---"),
        "enabled_for_new_domains_after": toggle.enabled_for_new_domains_after
        or "---",
        "enabled_for_new_users_after": toggle.enabled_for_new_users_after
        or "---",
        "relevant_to_env": relevant_to_env,
    }

    try:
        toggle_doc = Toggle.get(toggle.slug)
    except ResourceNotFound:
        return [{
            **toggle_data,
            **{
                "user_count": 0,
                "domain_count": 0,
                "email_domain_count": 0,
                "other_count": 0,
            }
        }]

    enabled_items = toggle_doc.enabled_users
    items_by_ns = defaultdict(set)
    for item in enabled_items:
        namespace = "user"
        if ":" in item:
            namespace, item = item.split(':', 1)
        items_by_ns[namespace].add(item)
    items_by_ns[NAMESPACE_DOMAIN].update(toggle.always_enabled)
    items_by_ns[NAMESPACE_DOMAIN].difference_update(toggle.always_disabled)

    # map 'None' to the user namespace
    namespaces = [
        NAMESPACE_USER if ns is None else ns for ns in toggle.namespaces
    ]

    def _ns_count(ns):
        return len(items_by_ns[ns]) if ns in namespaces else 0

    toggle_data.update({
        "user_count": _ns_count(NAMESPACE_USER),
        "domain_count": _ns_count(NAMESPACE_DOMAIN),
        "email_domain_count": _ns_count(NAMESPACE_EMAIL_DOMAIN),
        "other_count": _ns_count(NAMESPACE_OTHER),
    })

    if not items_by_ns or not any(items_by_ns.values()):
        return [toggle_data]

    def _item_info(item, ns):
        return {"item": item, "item_namespace": ns}

    rows = []
    for ns in items_by_ns:
        for item in items_by_ns[ns]:
            item_info = _item_info(item, ns)
            ns_info = {}
            if ns == NAMESPACE_DOMAIN:
                ns_info = _get_domain_info(item)
            if ns == NAMESPACE_USER:
                ns_info = _get_user_info(item)
            rows.append({**toggle_data, **item_info, **ns_info})
    return rows