Skip to content

Commit 4b46f96

Browse files
Release 0.1.2
Bugfix release. Changes: * Fix search * Fix history view * Bulk query for history removing * Execute for Periodic task and Template from API * Hide secret data via `encrypted` label * Add revision on Project page See merge request cloud/polemarch!49
2 parents 789a28e + c3278fa commit 4b46f96

31 files changed

+760
-402
lines changed

.gitlab-ci.yml

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# set to local images because too long execution
12
image: onegreyonewhite/tox:tox
23

34
variables:
@@ -16,6 +17,7 @@ stages:
1617

1718
.branch_tests_template: &branch_tests
1819
stage: test
20+
image: git.vst.lan/vst/tests:tox
1921
variables:
2022
TOX_ENVS: ""
2123
script:
@@ -37,6 +39,7 @@ stages:
3739

3840
.pack_tamplate: &packing-test
3941
stage: packaging-test
42+
image: git.vst.lan/vst/tests:tox
4043
variables:
4144
MYSQL_ROOT_PASSWORD: 'polemarch'
4245
MYSQL_DATABASE: 'polemarch'
@@ -61,9 +64,9 @@ stages:
6164
- dist/
6265
allow_failure: false
6366
only:
64-
- /^issue_.*$/
67+
# - /^issue_.*$/
6568
- developer
66-
- master
69+
# - master
6770
- make_bin_packages
6871
retry: 2
6972

@@ -83,6 +86,7 @@ stages:
8386
###########################################
8487
code_style:
8588
stage: code_standarts
89+
image: git.vst.lan/vst/tests:tox
8690
script:
8791
- make test ENVS=flake,pylint
8892
cache:
@@ -91,6 +95,7 @@ code_style:
9195
- .tox/flake
9296
only:
9397
- /^.{0,}issue_.*$/
98+
- developer
9499
retry: 2
95100

96101
py27-django111-coverage:
@@ -116,7 +121,7 @@ default_rpm_tests:
116121

117122
default_oracle_tests:
118123
<<: *packing-test
119-
image: onegreyonewhite/tox:oracle
124+
image: git.vst.lan/vst/tests:oracle
120125
script:
121126
- cat /etc/hosts
122127
- make rpm RELEASE=${CI_BUILD_ID}
@@ -128,7 +133,7 @@ default_oracle_tests:
128133

129134
default_deb_tests:
130135
<<: *packing-test
131-
image: onegreyonewhite/tox:ubuntu
136+
image: git.vst.lan/vst/tests:ubuntu
132137
script:
133138
- cat /etc/hosts
134139
- make deb RELEASE=${CI_BUILD_ID}
@@ -161,12 +166,10 @@ py35-django111:
161166
py36-django111:
162167
<<: *tests_template
163168

164-
165169
pep8_checks:
166170
stage: code_standarts
167171
only:
168172
- master
169-
- developer
170173
script:
171174
- make test ENVS=flake
172175
allow_failure: false
@@ -176,7 +179,6 @@ pylint_checks:
176179
stage: code_standarts
177180
only:
178181
- master
179-
- developer
180182
script:
181183
- make test ENVS=pylint
182184
allow_failure: false
@@ -201,7 +203,7 @@ release_deb:
201203
stage: release
202204
only:
203205
- tags
204-
image: onegreyonewhite/tox:ubuntu
206+
image: git.vst.lan/vst/tests:ubuntu
205207
script:
206208
- make deb
207209
allow_failure: false

polemarch/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from .environment import prepare_environment
22

3-
__version__ = "0.1.1"
3+
__version__ = "0.1.2"
44

55
def _main(**kwargs):
66
# pylint: disable=unused-variable

polemarch/api/v1/serializers.py

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,13 @@ class Meta:
514514
'vars',
515515
'url',)
516516

517+
def execute(self):
518+
inventory = self.instance.inventory
519+
history_id = self.instance.execute(sync=False)
520+
rdata = dict(detail="Started at inventory {}.".format(inventory),
521+
history_id=history_id)
522+
return Response(rdata, 201)
523+
517524

518525
class TemplateSerializer(_WithVariablesSerializer):
519526
data = DictField(required=True, write_only=True)
@@ -557,11 +564,15 @@ class Meta:
557564
'owner',
558565
'data',
559566
)
567+
568+
def execute(self, request):
569+
serializer = OneProjectSerializer(self.instance.project)
570+
return self.instance.execute(serializer, request.user)
571+
572+
560573
###################################
561574
# Subclasses for operations
562575
# with hosts and groups
563-
564-
565576
class _InventoryOperations(_WithVariablesSerializer):
566577

567578
def hosts_operations(self, method, data):
@@ -696,30 +707,29 @@ def sync(self):
696707
data = dict(detail="Sync with {}.".format(self.instance.repository))
697708
return Response(data, 200)
698709

699-
def _execution(self, kind, request):
700-
data = dict(request.data)
710+
def _execution(self, kind, data, user):
701711
inventory = data.pop("inventory")
702712
try:
703713
inventory = Inventory.objects.get(id=int(inventory))
704-
if not inventory.viewable_by(request.user): # nocv
714+
if not inventory.viewable_by(user): # nocv
705715
raise PermissionDenied(
706716
"You don't have permission to inventory."
707717
)
708718
except ValueError:
709719
pass
710720
history_id = self.instance.execute(
711721
kind, str(data.pop(kind)), inventory,
712-
initiator=request.user.id, **data
722+
initiator=user.id, **data
713723
)
714724
rdata = dict(detail="Started at inventory {}.".format(inventory),
715725
history_id=history_id)
716726
return Response(rdata, 201)
717727

718728
def execute_playbook(self, request):
719-
return self._execution("playbook", request)
729+
return self._execution("playbook", dict(request.data), request.user)
720730

721731
def execute_module(self, request):
722-
return self._execution("module", request)
732+
return self._execution("module", dict(request.data), request.user)
723733

724734

725735
class PermissionsSerializer(_SignalSerializer):

polemarch/api/v1/views.py

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,11 @@ class PeriodicTaskViewSet(base.LimitedPermissionMixin, base.ModelViewSetSet):
147147
serializer_class_one = serializers.OnePeriodictaskSerializer
148148
filter_class = filters.PeriodicTaskFilter
149149

150+
@detail_route(methods=["post"])
151+
def execute(self, request, *args, **kwargs):
152+
serializer = self.get_serializer(self.get_object())
153+
return serializer.execute().resp
154+
150155

151156
class HistoryViewSet(base.LimitedPermissionMixin, base.HistoryModelViewSet):
152157
model = serializers.models.History
@@ -190,6 +195,11 @@ class TemplateViewSet(base.PermissionMixin, base.ModelViewSetSet):
190195
def supported_kinds(self, request):
191196
return base.Response(self.model.template_fields, 200).resp
192197

198+
@detail_route(methods=["post"])
199+
def execute(self, request, *args, **kwargs):
200+
obj = self.get_object()
201+
return self.get_serializer(obj).execute(request).resp
202+
193203

194204
class HookViewSet(base.ModelViewSetSet):
195205
model = serializers.models.Hook
@@ -210,14 +220,21 @@ class BulkViewSet(rest_views.APIView):
210220
serializer_classes = serializers
211221

212222
_op_types = {
223+
"get": "perform_get",
213224
"add": "perform_create",
214225
"set": "perform_update",
215226
"del": "perform_delete",
216227
"mod": "perform_modify"
217228
}
218-
_allowed_types = [
219-
'host', 'group', 'inventory', 'project', 'periodictask', 'template'
220-
]
229+
_allowed_types = {
230+
'host': _op_types.keys(),
231+
'group': _op_types.keys(),
232+
'inventory': _op_types.keys(),
233+
'project': _op_types.keys(),
234+
'periodictask': _op_types.keys(),
235+
'template': _op_types.keys(),
236+
'history': ['del', "get"]
237+
}
221238

222239
def get_serializer_class(self, item):
223240
if item not in self._allowed_types:
@@ -229,14 +246,19 @@ def get_serializer(self, *args, **kwargs):
229246
kwargs["context"] = {'request': self.request}
230247
return self.get_serializer_class(kwargs.pop("item"))(*args, **kwargs)
231248

232-
def get_object(self, item, pk):
249+
def get_object(self, item, pk, access="editable"):
233250
serializer_class = self.get_serializer_class(item)
234251
model = serializer_class.Meta.model
235252
obj = model.objects.get(pk=pk)
236-
if not obj.editable_by(self.request.user):
253+
if not getattr(obj, access + "_by")(self.request.user):
237254
raise PermissionDenied("You don't have permission to this object.")
238255
return obj
239256

257+
def perform_get(self, item, pk):
258+
obj = self.get_object(item, pk, access="viewable")
259+
serializer = self.get_serializer(obj, item=item)
260+
return base.Response(serializer.data, 200).resp_dict
261+
240262
def perform_create(self, item, data):
241263
serializer = self.get_serializer(data=data, item=item)
242264
serializer.is_valid(raise_exception=True)
@@ -261,12 +283,20 @@ def perform_modify(self, item, pk, data, method, data_type):
261283
operation = getattr(serializer, "{}_operations".format(data_type))
262284
return operation(method, data).resp_dict
263285

286+
def _check_type(self, op_type, item):
287+
allowed_types = self._allowed_types.get(item, [])
288+
if op_type not in allowed_types:
289+
raise serializers.exceptions.UnsupportedMediaType(
290+
media_type=op_type
291+
)
292+
264293
@transaction.atomic
265294
def post(self, request, *args, **kwargs):
266295
operations = request.data
267296
results = []
268297
for operation in operations:
269298
op_type = operation.pop("type")
299+
self._check_type(op_type, operation.get("item", None))
270300
perf_method = getattr(self, self._op_types[op_type])
271301
result = perf_method(**operation)
272302
result['type'] = op_type

polemarch/main/models/tasks.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from django.contrib.auth.models import User
1919
from django.db.models import functions as dbfunc, Count
2020
from django.utils.timezone import now
21+
from rest_framework.exceptions import UnsupportedMediaType
2122

2223
from .base import ForeignKeyACL
2324

@@ -142,10 +143,10 @@ def get_schedule(self):
142143
return crontab(**self.crontab_kwargs)
143144
return float(self.schedule)
144145

145-
def execute(self):
146-
self.project.execute(
146+
def execute(self, sync=True):
147+
return self.project.execute(
147148
self.kind, self.mode, self.inventory,
148-
sync=True, save_result=self.save_result,
149+
sync=sync, save_result=self.save_result,
149150
initiator=self.id, initiator_type="scheduler",
150151
**self.vars
151152
)
@@ -181,6 +182,11 @@ class Meta:
181182
template_fields["Host"] = ["name", "vars"]
182183
template_fields["Group"] = template_fields["Host"] + ["children"]
183184

185+
_exec_types = {
186+
"Task": "playbook",
187+
"Module": "module",
188+
}
189+
184190
def get_data(self):
185191
data = json.loads(self.template_data)
186192
if "project" in self.template_fields[self.kind] and self.project:
@@ -192,6 +198,17 @@ def get_data(self):
192198
data['inventory'] = self.inventory
193199
return data
194200

201+
def execute(self, serializer, user):
202+
# pylint: disable=protected-access
203+
tp = self._exec_types.get(self.kind, None)
204+
if tp is None:
205+
raise UnsupportedMediaType(media_type=self.kind)
206+
data = self.get_data()
207+
data.pop("project", None)
208+
vars = data.pop("vars", {})
209+
data.update(vars)
210+
return serializer._execution(tp, data, user)
211+
195212
def _convert_to_data(self, value):
196213
if isinstance(value, (six.string_types, six.text_type)):
197214
return json.loads(value)

polemarch/main/models/utils.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -188,16 +188,17 @@ def error_handler(self, exception):
188188
self.history.status = default_code
189189

190190
def execute(self, target, inventory, history, project, **extra_args):
191-
self.prepare(target, inventory, history, project)
192-
self.history.status = "OK"
193191
try:
192+
self.prepare(target, inventory, history, project)
193+
self.history.status = "OK"
194194
extra = self.__parse_extra_args(**extra_args)
195195
args = self.get_args(self.target, extra.args)
196196
self.history.raw_stdout = self.executor.execute(args, self.workdir)
197197
except Exception as exception:
198198
self.error_handler(exception)
199199
finally:
200-
self.inventory_object.close()
200+
inventory_object = getattr(self, "inventory_object", None)
201+
inventory_object and inventory_object.close()
201202
self.history.stop_time = timezone.now()
202203
self.history.save()
203204

0 commit comments

Comments
 (0)