Skip to content

Commit

Permalink
Admin Dashboard: [Feature flag] Drop -M-A-G-I-C- Organizations (#893)
Browse files Browse the repository at this point in the history
  • Loading branch information
romartin authored Mar 26, 2024
1 parent c7815ff commit 05949b8
Show file tree
Hide file tree
Showing 18 changed files with 30 additions and 209 deletions.
6 changes: 1 addition & 5 deletions ansible_wisdom/ai/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -359,11 +359,7 @@ def validate_inlineSuggestion(self, value):

if user.rh_user_has_seat is False:
return value
if (
user.organization
and user.organization.is_schema_2_telemetry_enabled
and user.organization.telemetry_opt_out is False
):
if user.organization and user.organization.telemetry_opt_out is False:
return value
else:
raise serializers.ValidationError("invalid feedback type for user")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,6 @@ def get(self, request, *args, **kwargs):
if not organization:
return Response(status=HTTP_400_BAD_REQUEST)

if not organization.is_schema_2_telemetry_enabled:
raise ServiceUnavailable()

return Response(status=HTTP_200_OK, data={'optOut': organization.telemetry_opt_out})

except ServiceUnavailable:
Expand Down Expand Up @@ -107,9 +104,6 @@ def post(self, request, *args, **kwargs):
if not organization:
return Response(status=HTTP_400_BAD_REQUEST)

if not organization.is_schema_2_telemetry_enabled:
raise ServiceUnavailable()

# Extract Telemetry settings from request
telemetry_settings_serializer = TelemetrySettingsRequestSerializer(data=request.data)
telemetry_settings_serializer.is_valid(raise_exception=True)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,6 @@ def test_permission_classes(self, *args):
for permission in required_permissions:
self.assertTrue(permission in view.permission_classes)

@override_settings(LAUNCHDARKLY_SDK_KEY='dummy_key')
@patch.object(feature_flags, 'LDClient')
def test_get_settings_when_feature_disabled(self, LDClient, *args):
LDClient.return_value.variation.return_value = False
self.user.organization = Organization.objects.get_or_create(id=123)[0]
self.client.force_authenticate(user=self.user)
r = self.client.get(reverse('telemetry_settings'))
self.assertEqual(r.status_code, HTTPStatus.SERVICE_UNAVAILABLE)

@override_settings(SEGMENT_WRITE_KEY='DUMMY_KEY_VALUE')
def test_get_settings_without_org_id(self, *args):
self.client.force_authenticate(user=self.user)
Expand Down Expand Up @@ -95,15 +86,6 @@ def test_set_settings_authentication_error(self, *args):
r = self.client.post(reverse('telemetry_settings'))
self.assertEqual(r.status_code, HTTPStatus.UNAUTHORIZED)

@override_settings(LAUNCHDARKLY_SDK_KEY='dummy_key')
@patch.object(feature_flags, 'LDClient')
def test_set_settings_when_feature_disabled(self, LDClient, *args):
LDClient.return_value.variation.return_value = False
self.user.organization = Organization.objects.get_or_create(id=123)[0]
self.client.force_authenticate(user=self.user)
r = self.client.get(reverse('telemetry_settings'))
self.assertEqual(r.status_code, HTTPStatus.SERVICE_UNAVAILABLE)

@override_settings(SEGMENT_WRITE_KEY='DUMMY_KEY_VALUE')
def test_set_settings_without_org_id(self, *args):
self.client.force_authenticate(user=self.user)
Expand Down
20 changes: 2 additions & 18 deletions ansible_wisdom/ai/api/tests/test_serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,28 +192,12 @@ def test_commercial_user_raises_exception_on_inlineSuggestion(self):
with self.assertRaises(serializers.ValidationError):
serializer.is_valid(raise_exception=True)

def test_commercial_user_not_telemetry_enabled_raises_exception_on_inlineSuggestion(self):
org = Mock(telemetry_opt_out=False, is_schema_2_telemetry_enabled=False)
user = Mock(rh_user_has_seat=True, organization=org)
request = Mock(user=user)
serializer = FeedbackRequestSerializer(
context={'request': request},
data={
"inlineSuggestion": {
"latency": 1000,
"userActionTime": 5155,
"action": "0",
"suggestionId": "a1b2c3d4-e5f6-a7b8-c9d0-e1f2a3b4c5d6",
}
},
)

# inlineSuggestion feedback raises exception when seat and not telemetry enabled
with self.assertRaises(serializers.ValidationError):
serializer.is_valid(raise_exception=True)

def test_invalid_ansible_extension_version_on_inline_suggestion(self):
org = Mock(telemetry_opt_out=False, is_schema_2_telemetry_enabled=True)
org = Mock(telemetry_opt_out=False)
user = Mock(rh_user_has_seat=True, organization=org)
request = Mock(user=user)
serializer = FeedbackRequestSerializer(
Expand All @@ -236,7 +220,7 @@ def test_invalid_ansible_extension_version_on_inline_suggestion(self):
serializer.is_valid(raise_exception=True)

def test_commercial_user_not_opted_out_passes_on_inlineSuggestion(self):
org = Mock(telemetry_opt_out=False, is_schema_2_telemetry_enabled=True)
org = Mock(telemetry_opt_out=False)
user = Mock(rh_user_has_seat=True, organization=org)
request = Mock(user=user)
serializer = FeedbackRequestSerializer(
Expand Down
4 changes: 0 additions & 4 deletions ansible_wisdom/ai/api/utils/segment_analytics_telemetry.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,6 @@ def send_segment_analytics_event(
logger.info("Analytics telemetry not active, because of no organization assigned for user.")
return

if not organization.is_schema_2_telemetry_enabled:
logger.info(f"Analytics telemetry not active for organization '{organization.id}'.")
return

if organization.telemetry_opt_out:
logger.info(f"Organization '{organization.id}' has opted out of Analytics telemetry.")
return
Expand Down
2 changes: 0 additions & 2 deletions ansible_wisdom/ai/feature_flags.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
class WisdomFlags(str, Enum):
# model name selection
MODEL_NAME = "model_name"
# Schema 2 Telemetry is enabled for an Organization
SCHEMA_2_TELEMETRY_ORG_ENABLED = "schema_2_telemetry_org_enabled"
# For some organizations we can bypass the subscription check
BYPASS_AAP_SUBSCRIPTION_CHECK = "special_wca_access_orgs"

Expand Down
34 changes: 0 additions & 34 deletions ansible_wisdom/ai/tests/test_feature_flags.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@

from django.conf import settings
from django.test import override_settings
from ldclient import Context
from ldclient.config import Config

import ansible_wisdom.ai.feature_flags as feature_flags
from ansible_wisdom.ai.api.tests.test_views import WisdomServiceAPITestCaseBase
from ansible_wisdom.ai.feature_flags import WisdomFlags


class TestFeatureFlags(WisdomServiceAPITestCaseBase):
Expand Down Expand Up @@ -58,35 +56,3 @@ def test_feature_flags_with_local_file(self):
value = ff.get('model_name', self.user, 'default_value')
self.assertEqual(ff.client.get_sdk_key(), 'sdk-key-123abc')
self.assertEqual(value, 'dev_model')

@override_settings(LAUNCHDARKLY_SDK_KEY='dummy_key')
@patch.object(feature_flags, 'LDClient')
def test_feature_flags_check_flag_disabled(self, LDClient):
LDClient.return_value.variation.return_value = False

ff = feature_flags.FeatureFlags()
self.assertFalse(
ff.check_flag(
WisdomFlags.SCHEMA_2_TELEMETRY_ORG_ENABLED, {'kind': 'organization', 'org_id': 123}
)
)

@override_settings(LAUNCHDARKLY_SDK_KEY='dummy_key')
@patch.object(feature_flags, 'LDClient')
def test_feature_flags_check_flag_enabled(self, LDClient):
LDClient.return_value.variation.return_value = True

ff = feature_flags.FeatureFlags()
self.assertTrue(
ff.check_flag(
WisdomFlags.SCHEMA_2_TELEMETRY_ORG_ENABLED, {'kind': 'organization', 'key': '123'}
)
)

args = LDClient.return_value.variation.call_args_list[0]
name: str = args[0][0]
context: Context = args[0][1]
self.assertEqual(name, WisdomFlags.SCHEMA_2_TELEMETRY_ORG_ENABLED)
self.assertEqual(context.kind, 'organization')
self.assertEqual(context.key, '123')
self.assertFalse(args[0][2])
2 changes: 0 additions & 2 deletions ansible_wisdom/main/templates/console/console.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
<!-- It is safe to pass the value embedded in the host DOM -->
<!-- as it is only used for display purposes and servers no other value -->
<div id="user_name" hidden>{{user_name}}</div>
<!-- Flag whether Telemetry settings is supported -->
<div id="telemetry_schema_2_enabled" hidden>{{telemetry_schema_2_enabled}}</div>
<!-- Admin Dashboard URL -->
<div id="telemetry_schema_2_admin_dashboard_url" hidden>{{telemetry_schema_2_admin_dashboard_url}}</div>
{% endblock content %}
18 changes: 1 addition & 17 deletions ansible_wisdom/main/tests/test_console_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,30 +79,14 @@ def test_extra_data(self, *args):

@override_settings(LAUNCHDARKLY_SDK_KEY='dummy_key')
@patch.object(feature_flags, 'LDClient')
def test_extra_data_telemetry_feature_enabled(self, LDClient, *args):
def test_extra_data_telemetry_feature(self, LDClient, *args):
LDClient.return_value.variation.return_value = True
self.user.organization = Organization.objects.get_or_create(id=123)[0]
self.client.force_authenticate(user=self.user)
response = self.client.get(reverse('console'))
self.assertIsInstance(response.context_data, dict)
context = response.context_data
# The default setting for tests is True
self.assertTrue(context['telemetry_schema_2_enabled'])
self.assertEqual(
context['telemetry_schema_2_admin_dashboard_url'],
'https://console.stage.redhat.com/ansible/lightspeed-admin-dashboard',
)

@override_settings(LAUNCHDARKLY_SDK_KEY='dummy_key')
@patch.object(feature_flags, 'LDClient')
def test_extra_data_telemetry__feature_disabled(self, LDClient, *args):
LDClient.return_value.variation.return_value = False
self.user.organization = Organization.objects.get_or_create(id=123, telemetry_opt_out=True)[
0
]
self.client.force_authenticate(user=self.user)
response = self.client.get(reverse('console'))
self.assertIsInstance(response.context_data, dict)
context = response.context_data
self.assertFalse(context['telemetry_schema_2_enabled'])
self.assertIsNone(context.get('telemetry_schema_2_admin_dashboard_url'))
10 changes: 3 additions & 7 deletions ansible_wisdom/main/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,8 @@ def get_context_data(self, **kwargs):
context["rh_org_has_subscription"] = user.rh_org_has_subscription
organization = user.organization
if organization:
is_schema_2_telemetry_enabled = organization.is_schema_2_telemetry_enabled
context["telemetry_schema_2_enabled"] = is_schema_2_telemetry_enabled

if is_schema_2_telemetry_enabled:
context["telemetry_schema_2_admin_dashboard_url"] = (
settings.TELEMETRY_ADMIN_DASHBOARD_URL
)
context["telemetry_schema_2_admin_dashboard_url"] = (
settings.TELEMETRY_ADMIN_DASHBOARD_URL
)

return context
9 changes: 0 additions & 9 deletions ansible_wisdom/organizations/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,6 @@ class Organization(models.Model):
id = models.IntegerField(primary_key=True)
telemetry_opt_out = models.BooleanField(default=False)

@cached_property
def is_schema_2_telemetry_enabled(self) -> bool:
# Avoid circular dependency issue with lazy import
from ansible_wisdom.ai.feature_flags import WisdomFlags

return self.__make_organization_request_to_launchdarkly(
WisdomFlags.SCHEMA_2_TELEMETRY_ORG_ENABLED
)

@cached_property
def is_subscription_check_should_be_bypassed(self) -> bool:
# Avoid circular dependency issue with lazy import
Expand Down
6 changes: 0 additions & 6 deletions ansible_wisdom/organizations/tests/test_organizations.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,44 +10,38 @@ class TestOrganization(TestCase):
def test_org_with_telemetry_schema_2_opted_in(self):
organization = Organization.objects.get_or_create(id=123, telemetry_opt_out=False)[0]
self.assertFalse(organization.telemetry_opt_out)
self.assertFalse(organization.is_schema_2_telemetry_enabled)

def test_org_with_telemetry_schema_2_opted_out(self):
organization = Organization.objects.get_or_create(id=123, telemetry_opt_out=True)[0]
self.assertTrue(organization.telemetry_opt_out)
self.assertFalse(organization.is_schema_2_telemetry_enabled)

@override_settings(LAUNCHDARKLY_SDK_KEY='dummy_key')
@patch.object(feature_flags, 'LDClient')
def test_org_with_telemetry_schema_2_opted_in_with_feature_flag_override(self, LDClient):
LDClient.return_value.variation.return_value = True
organization = Organization.objects.get_or_create(id=123, telemetry_opt_out=True)[0]
self.assertTrue(organization.telemetry_opt_out)
self.assertTrue(organization.is_schema_2_telemetry_enabled)

@override_settings(LAUNCHDARKLY_SDK_KEY='dummy_key')
@patch.object(feature_flags, 'LDClient')
def test_org_with_telemetry_schema_2_opted_in_with_feature_flag_no_override(self, LDClient):
LDClient.return_value.variation.return_value = False
organization = Organization.objects.get_or_create(id=123, telemetry_opt_out=True)[0]
self.assertTrue(organization.telemetry_opt_out)
self.assertFalse(organization.is_schema_2_telemetry_enabled)

@override_settings(LAUNCHDARKLY_SDK_KEY='dummy_key')
@patch.object(feature_flags, 'LDClient')
def test_org_with_telemetry_schema_2_opted_out_with_feature_flag_override(self, LDClient):
LDClient.return_value.variation.return_value = True
organization = Organization.objects.get_or_create(id=123, telemetry_opt_out=False)[0]
self.assertFalse(organization.telemetry_opt_out)
self.assertTrue(organization.is_schema_2_telemetry_enabled)

@override_settings(LAUNCHDARKLY_SDK_KEY='dummy_key')
@patch.object(feature_flags, 'LDClient')
def test_org_with_telemetry_schema_2_opted_out_with_feature_flag_no_override(self, LDClient):
LDClient.return_value.variation.return_value = False
organization = Organization.objects.get_or_create(id=123, telemetry_opt_out=False)[0]
self.assertFalse(organization.telemetry_opt_out)
self.assertFalse(organization.is_schema_2_telemetry_enabled)

@override_settings(LAUNCHDARKLY_SDK_KEY='dummy_key')
@patch.object(feature_flags, 'LDClient')
Expand Down
45 changes: 0 additions & 45 deletions ansible_wisdom/users/tests/test_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -624,51 +624,6 @@ def test_rhsso_user_with_telemetry_opted_out(self, LDClient):
self.assertEqual(r.status_code, HTTPStatus.OK)
self.assertTrue(r.data.get('org_telemetry_opt_out'))

@override_settings(LAUNCHDARKLY_SDK_KEY='dummy_key')
@patch.object(feature_flags, 'LDClient')
def test_rhsso_user_with_telemetry_feature_disabled(self, LDClient):
LDClient.return_value.variation.return_value = False
user = create_user(
provider=USER_SOCIAL_AUTH_PROVIDER_OIDC,
social_auth_extra_data={"login": "sso_username"},
external_username="sso_username",
org_opt_out=True,
)
self.client.force_authenticate(user=user)
r = self.client.get(reverse('me'))
self.assertEqual(r.status_code, HTTPStatus.OK)
self.assertIsNone(r.data.get('org_telemetry_opt_out'))

@override_settings(LAUNCHDARKLY_SDK_KEY='dummy_key')
@patch.object(feature_flags, 'LDClient')
def test_rhsso_user_with_telemetry_feature_enabled_opted_out(self, LDClient):
LDClient.return_value.variation.return_value = True
user = create_user(
provider=USER_SOCIAL_AUTH_PROVIDER_OIDC,
social_auth_extra_data={"login": "sso_username"},
external_username="sso_username",
org_opt_out=True,
)
self.client.force_authenticate(user=user)
r = self.client.get(reverse('me'))
self.assertEqual(r.status_code, HTTPStatus.OK)
self.assertTrue(r.data.get('org_telemetry_opt_out'))

@override_settings(LAUNCHDARKLY_SDK_KEY='dummy_key')
@patch.object(feature_flags, 'LDClient')
def test_rhsso_user_with_telemetry_feature_enabled_opted_in(self, LDClient):
LDClient.return_value.variation.return_value = True
user = create_user(
provider=USER_SOCIAL_AUTH_PROVIDER_OIDC,
social_auth_extra_data={"login": "sso_username"},
external_username="sso_username",
org_opt_out=False,
)
self.client.force_authenticate(user=user)
r = self.client.get(reverse('me'))
self.assertEqual(r.status_code, HTTPStatus.OK)
self.assertFalse(r.data.get('org_telemetry_opt_out'))

@override_settings(LAUNCHDARKLY_SDK_KEY='dummy_key')
@patch.object(IsOrganisationAdministrator, 'has_permission', return_value=True)
@patch.object(IsOrganisationLightspeedSubscriber, 'has_permission', return_value=True)
Expand Down
2 changes: 1 addition & 1 deletion ansible_wisdom/users/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def retrieve(self, request, *args, **kwargs):

# Enrich with Organisational data, if necessary
organization = self.request.user.organization
if organization and organization.is_schema_2_telemetry_enabled:
if organization:
user_data["org_telemetry_opt_out"] = organization.telemetry_opt_out

return Response(user_data)
Expand Down
Loading

1 comment on commit 05949b8

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ClamAV Virus Definition DB Files:
----
total 228448
-rw-r--r--  1 root root 170479789 Mar 26 06:08 main.cvd
-rw-r--r--  1 root root        69 Mar 26 06:08 freshclam.dat
-rw-r--r--  1 root root  63143246 Mar 26 06:08 daily.cvd
-rw-r--r--  1 root root    289733 Mar 26 06:09 bytecode.cvd
drwxr-xr-x 16 root root      4096 Mar 26 16:17 ..
drwxr-xr-x  2 root root      4096 Mar 26 16:17 .
----
File: /var/lib/clamav/bytecode.cvd
Build time: 27 Feb 2024 10:37 -0500
Version: 335
Signatures: 86
Functionality level: 90
Builder: raynman
MD5: 16d388f042f5c44628a66228df427c20
Digital signature: 7fD3mweaw4tqQH9Dl7ZewBLXZBSrLKX5no/rYN/6NQBmhnWUyTBt3uzd7ZjEnIT5yN1ygLwsDcuzoKRoA+syrfk3PcDHf5/h6Wb/d8uikXSALygH5VYAPo2ksV5Pitn3reECJ90q2m9m0CH2VpT1tDkkcVi05LLV5PwBle2Ufpe
Verification OK.
----
File: /var/lib/clamav/daily.cvd
Build time: 25 Mar 2024 04:30 -0400
Version: 27225
Signatures: 2056578
Functionality level: 90
Builder: raynman
MD5: f2f896a103bcf92487d93e0dab11ff3b
Digital signature: yA+0wnfHmCfEzidE1Si9rcF6V7LsZFk82JXowGx336Zf3BGrVN6/bvS65y7mBqCvHComIZTLeU9yAGXoJ9P3fEMkzu1muVy1rUMYvJtY/cXB6Qm8GSABAsI6WmVkOm24n4GrfrImohGlj4k2K+LFPu0VhqG8La5o7Dgt6bFF7Rd
Verification OK.
----
File: /var/lib/clamav/main.cvd
Build time: 16 Sep 2021 08:32 -0400
Version: 62
Signatures: 6647427
Functionality level: 90
Builder: sigmgr
MD5: 137eccce31aacb21b5a98bb8c21cefd6
Digital signature: twaJBls8V5q64R7QY10AatEtPNuPWoVoxTaNO1jpBg7s5jIMMXpitgG1000YLp6rb0TWkEKjRqxneGTxuxWaWm7XBjsgwX2BRWh/y4fhs7uyImdKRLzQ5y8e2EkSChegF/i8clqfn+1qetq9j4gbktJ3JZpOXPoHlyr2Dv9S/Bg
Verification OK.
----
Scanning Results:
ClamAV 1.0.5/27225/Mon Mar 25 08:30:27 2024
LibClamAV Warning: Max file-size was set to 4194304000 bytes. Unfortunately, scanning files greater than 2147483647 bytes (2 GiB - 1) is not supported.

----------- SCAN SUMMARY -----------
Known viruses: 8688428
Engine version: 1.0.5
Scanned directories: 31765
Scanned files: 195342
Infected files: 0
Data scanned: 6513.16 MB
Data read: 3427.26 MB (ratio 1.90:1)
Time: 1442.907 sec (24 m 2 s)
Start Date: 2024:03:26 16:18:57
End Date:   2024:03:26 16:43:00

Please sign in to comment.