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)
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})
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)
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)
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)
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
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)
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
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()
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, }
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()
def _delete_toggles(self, *toggles): for toggle in toggles: try: Toggle.get(toggle).delete() except ResourceNotFound: pass
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