Skip to content

Commit b910221

Browse files
committed
WIP2
1 parent 58d6469 commit b910221

File tree

7 files changed

+79
-31
lines changed

7 files changed

+79
-31
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ jobs:
7676
pip install -U -r requirements-test.txt
7777
pip install -U -e .
7878
pip install ${{ matrix.django-version }}
79+
pip install -U --force-reinstall --no-deps https://github.com/openwisp/openwisp-utils/tarball/exclude_validation
7980
8081
- name: Start postgres and redis
8182
if: ${{ !cancelled() && steps.deps.conclusion == 'success' }}

openwisp_controller/config/api/serializers.py

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ def get_queryset(self):
107107

108108

109109
class BaseConfigSerializer(ValidatedDeviceIdSerializer):
110+
exclude_validation = ['device']
111+
110112
class Meta:
111113
model = Config
112114
fields = ['status', 'error_reason', 'backend', 'templates', 'context', 'config']
@@ -131,14 +133,16 @@ def validate(self, data):
131133
"""
132134
# Existing device
133135
device = self.context.get('device')
136+
# data.pop('device', None)
137+
# import ipdb; ipdb.set_trace()
134138
if not self.instance and device:
135139
# Existing device with existing config
136140
# Or it's an exsiting device with a new config
137141
if device._has_config():
138142
self.instance = device.config
139-
return super().validate(data)
143+
# return super().validate(data)
140144
# New device
141-
self.exclude_validation = ['device']
145+
# self.exclude_validation = ['device']
142146
return super().validate(data)
143147

144148

@@ -153,11 +157,29 @@ def _prepare_config(self, device, config_data):
153157
config.full_clean()
154158
return config
155159

160+
def _is_config_data_relevant(self, config_data):
161+
"""
162+
Returns True if ``config_data`` does not equal
163+
the default values and hence the config is useful.
164+
"""
165+
return not (
166+
config_data.get('backend') == app_settings.DEFAULT_BACKEND
167+
and not config_data.get('templates')
168+
and not config_data.get('context')
169+
and not config_data.get('config')
170+
)
171+
156172
@transaction.atomic
157173
def _create_config(self, device, config_data):
174+
# templates = config_data.get('templates')
175+
# if len(templates) == 1 and templates[0].name == 't1-org2':
176+
# import ipdb; ipdb.set_trace()
158177
config_templates = self._get_config_templates(config_data)
159178
try:
160179
if not device._has_config():
180+
# if the user hasn't set any useful config data, skip
181+
if not self._is_config_data_relevant(config_data):
182+
return
161183
config = Config(device=device, **config_data)
162184
config.full_clean()
163185
config.save()
@@ -173,15 +195,10 @@ def _create_config(self, device, config_data):
173195
raise serializers.ValidationError({'config': error.messages})
174196

175197
def _update_config(self, device, config_data):
176-
if (
177-
config_data.get('backend') == app_settings.DEFAULT_BACKEND
178-
and not config_data.get('templates')
179-
and not config_data.get('context')
180-
and not config_data.get('config')
181-
):
182-
# Do not create Config object if config_data only
183-
# contains the default value.
184-
# See https://github.com/openwisp/openwisp-controller/issues/699
198+
# Do not create Config object if config_data only
199+
# contains the default values.
200+
# See https://github.com/openwisp/openwisp-controller/issues/699
201+
if not self._is_config_data_relevant(config_data):
185202
return
186203
if not device._has_config():
187204
return self._create_config(device, config_data)
@@ -199,6 +216,10 @@ def _update_config(self, device, config_data):
199216
except ValidationError as error:
200217
raise serializers.ValidationError({'config': error.messages})
201218

219+
# def run_validation(self, *args, **kwargs):
220+
# import ipdb; ipdb.set_trace()
221+
# return super().run_validation(*args, **kwargs)
222+
202223

203224
class DeviceListConfigSerializer(BaseConfigSerializer):
204225
config = serializers.JSONField(
@@ -265,6 +286,10 @@ class DeviceDetailConfigSerializer(BaseConfigSerializer):
265286
)
266287
templates = FilterTemplatesByOrganization(many=True)
267288

289+
# def validate(self, *args, **kwargs):
290+
# import ipdb; ipdb.set_trace()
291+
# return super().validate(*args, **kwargs)
292+
268293

269294
class DeviceDetailSerializer(DeviceConfigSerializer):
270295
config = DeviceDetailConfigSerializer(allow_null=True)
@@ -291,6 +316,10 @@ class Meta(BaseMeta):
291316
'modified',
292317
]
293318

319+
# def to_internal_value(self, *args, **kwargs):
320+
# import ipdb; ipdb.set_trace()
321+
# return super().to_internal_value(*args, **kwargs)
322+
294323
def update(self, instance, validated_data):
295324
config_data = validated_data.pop('config', {})
296325
raw_data_for_signal_handlers = {
@@ -299,7 +328,7 @@ def update(self, instance, validated_data):
299328
if config_data:
300329
self._update_config(instance, config_data)
301330

302-
elif hasattr(instance, 'config') and validated_data.get('organization'):
331+
elif instance._has_config() and validated_data.get('organization'):
303332
if instance.organization != validated_data.get('organization'):
304333
# config.device.organization is used for validating
305334
# the organization of templates. It is also used for adding

openwisp_controller/config/api/views.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,21 @@ def perform_destroy(self, instance):
114114
force_deletion = self.request.query_params.get('force', None) == 'true'
115115
instance.delete(check_deactivated=(not force_deletion))
116116

117+
# def update(self, request, *args, **kwargs):
118+
# import ipdb; ipdb.set_trace()
119+
# partial = kwargs.pop('partial', False)
120+
# instance = self.get_object()
121+
# serializer = self.get_serializer(instance, data=request.data, partial=partial)
122+
# serializer.is_valid(raise_exception=True)
123+
# self.perform_update(serializer)
124+
#
125+
# if getattr(instance, '_prefetched_objects_cache', None):
126+
# # If 'prefetch_related' has been applied to a queryset, we need to
127+
# # forcibly invalidate the prefetch cache on the instance.
128+
# instance._prefetched_objects_cache = {}
129+
#
130+
# return Response(serializer.data)
131+
117132

118133
class DeviceActivateView(ProtectedAPIMixin, GenericAPIView):
119134
serializer_class = serializers.Serializer

openwisp_controller/config/tests/test_api.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from copy import deepcopy
2+
13
from django.contrib.auth.models import Permission
24
from django.test import TestCase
35
from django.test.client import BOUNDARY, MULTIPART_CONTENT, encode_multipart
@@ -138,10 +140,10 @@ def test_device_create_no_config_api(self):
138140
self.assertEqual(Device.objects.count(), 1)
139141
self.assertEqual(Config.objects.count(), 0)
140142

141-
def test_device_create_config_default_values(self):
143+
def test_device_create_default_config_values(self):
142144
self.assertEqual(Device.objects.count(), 0)
143145
path = reverse('config_api:device_list')
144-
data = self._get_device_data.copy()
146+
data = deepcopy(self._get_device_data)
145147
org = self._get_org()
146148
data['organization'] = org.pk
147149
data['config'].update({'context': {}, 'config': {}})
@@ -204,8 +206,8 @@ def test_device_post_with_templates_of_different_org(self):
204206
org_1 = self._get_org()
205207
data['organization'] = org_1.pk
206208
org_2 = self._create_org(name='test org2', slug='test-org2')
207-
t1 = self._create_template(name='t1', organization=org_2)
208-
data['config']['templates'] += [str(t1.pk)]
209+
t1 = self._create_template(name='t1-org2', organization=org_2)
210+
data['config']['templates'] = [str(t1.pk)]
209211
response = self.client.post(path, data, content_type='application/json')
210212
self.assertEqual(response.status_code, 400)
211213
self.assertEqual(

openwisp_controller/serializers.py

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,19 @@
33

44

55
class ValidatedDeviceIdSerializer(ValidatedModelSerializer):
6-
def validate(self, data):
7-
"""
8-
Adds "device_id" to the data dictionary which
9-
is going to be used to create the temporary
10-
instance used for validation
11-
"""
12-
for key in ['device', 'device_id']:
13-
if key in self.context:
14-
data[key] = self.context[key]
15-
return super().validate(data)
6+
pass
7+
# def validate(self, data):
8+
# """Adds "device" to the data dictionary.
9+
#
10+
# Used to satisfy validation needs."""
11+
# # for key in ['device', 'device_id']:
12+
# # if key in self.context:
13+
# # data[key] = self.context[key]
14+
# if 'device' in self.context:
15+
# data['device'] = self.context['device']
16+
# data = super().validate(data)
17+
# data.pop('device', None)
18+
# return data
1619

1720

1821
class BaseSerializer(FilterSerializerByOrgManaged, ValidatedModelSerializer):
@@ -32,9 +35,7 @@ class BaseDeviceIdSerializer(FilterSerializerByOrgManaged, ValidatedDeviceIdSeri
3235

3336

3437
class DeviceContextMixin:
35-
"""
36-
TODO
37-
"""
38+
"""Adds the device object to the serializer context."""
3839

3940
def get_object(self):
4041
obj = super().get_object()

requirements-test.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
pytest-cov~=6.1.0
2-
openwisp-utils[qa,selenium,channels-test] @ https://github.com/openwisp/openwisp-utils/tarball/exclude_validation
2+
openwisp-utils[qa,selenium,channels-test] @ https://github.com/openwisp/openwisp-utils/tarball/1.2
33
django_redis~=5.4.0
44
mock-ssh-server~=0.9.1
55
responses~=0.25.6

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ django-x509 @ https://github.com/openwisp/django-x509/tarball/1.3
77
django-loci @ https://github.com/DragnEmperor/django-loci/tarball/1.2
88
django-flat-json-widget~=0.3.1
99
openwisp-users @ https://github.com/openwisp/openwisp-users/tarball/1.2
10-
openwisp-utils[celery,channels] @ https://github.com/openwisp/openwisp-utils/tarball/exclude_validation
10+
openwisp-utils[celery,channels] @ https://github.com/openwisp/openwisp-utils/tarball/1.2
1111
openwisp-notifications @ https://github.com/openwisp/openwisp-notifications/tarball/1.2
1212
openwisp-ipam @ https://github.com/openwisp/openwisp-ipam/tarball/1.2
1313
djangorestframework-gis @ https://github.com/openwisp/django-rest-framework-gis/tarball/1.2

0 commit comments

Comments
 (0)