Skip to content

Commit

Permalink
3.0.1
Browse files Browse the repository at this point in the history
### Changelog:
* Feature(backend): History ``inventory`` field now has value of ``arg_shown_on_history_as_inventory`` of execution plugin.
* Fix(backend): Migrate initiator fields to new model instances.

See merge request polemarch/ce!305
  • Loading branch information
onegreyonewhite committed Mar 25, 2023
2 parents cef8d38 + 4138837 commit 4e12a13
Show file tree
Hide file tree
Showing 7 changed files with 404 additions and 57 deletions.
10 changes: 5 additions & 5 deletions doc/api_schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ info:
application: 3.0.0
library: 3.0.0
vstutils: 5.4.0
django: 4.1.6
django: 4.1.7
djangorestframework: 3.14.0
drf_yasg: 1.21.5
ansible: 2.9.27
Expand Down Expand Up @@ -13766,7 +13766,7 @@ definitions:
model:
$ref: '#/definitions/AnsiblePlaybook'
value_field: playbook
view_field: name
view_field: playbook
usePrefetch: true
args:
title: Args
Expand Down Expand Up @@ -15274,7 +15274,7 @@ definitions:
model:
$ref: '#/definitions/AnsiblePlaybook'
value_field: playbook
view_field: name
view_field: playbook
usePrefetch: true
args:
title: Args
Expand Down Expand Up @@ -15513,7 +15513,7 @@ definitions:
model:
$ref: '#/definitions/AnsiblePlaybook'
value_field: playbook
view_field: name
view_field: playbook
usePrefetch: true
args:
title: Args
Expand Down Expand Up @@ -16032,7 +16032,7 @@ definitions:
model:
$ref: '#/definitions/AnsiblePlaybook'
value_field: playbook
view_field: name
view_field: playbook
usePrefetch: true
args:
title: Args
Expand Down
2 changes: 1 addition & 1 deletion polemarch/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@
"VST_ROOT_URLCONF": os.getenv("VST_ROOT_URLCONF", 'vstutils.urls'),
}

__version__ = "3.0.0"
__version__ = "3.0.1"

prepare_environment(**default_settings)
145 changes: 115 additions & 30 deletions polemarch/main/migrations/0003_v3_migrate_data_to_new_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,20 +91,22 @@ def to_template_data(option):

def to_options_data(options_qs):
return {
option.name: to_template_data(option)
slugify(option.name): to_template_data(option)
for option in options_qs
}


def migrate_templates_data_direct(apps, schema_editor):
Template = apps.get_model('main', 'Template')
PeriodicTask = apps.get_model('main', 'PeriodicTask')
History = apps.get_model('main', 'History')

ExecutionTemplate = apps.get_model('main', 'ExecutionTemplate')
ExecutionTemplateOption = apps.get_model('main', 'ExecutionTemplateOption')
TemplatePeriodicTask = apps.get_model('main', 'TemplatePeriodicTask')

db_alias = schema_editor.connection.alias
history_to_update = []

for old_template in Template.objects.all():
new_template = ExecutionTemplate.objects.using(db_alias).create(
Expand All @@ -129,24 +131,55 @@ def migrate_templates_data_direct(apps, schema_editor):
for old_option_key, old_option_value in json.loads(old_template.options_data or '{}').items()
]

ExecutionTemplateOption.objects.using(db_alias).bulk_create([default_option, *other_options])

if old_template.periodic_task.exists():
TemplatePeriodicTask.objects.using(db_alias).bulk_create([
TemplatePeriodicTask(
name=old_periodic_task.name,
template_option=default_option if not old_periodic_task.template_opt else [
option for option in other_options
if slugify(option.name) == old_periodic_task.template_opt
][0],
notes=old_periodic_task.notes,
type=old_periodic_task.type,
schedule=old_periodic_task.schedule,
enabled=old_periodic_task.enabled,
save_result=old_periodic_task.save_result,
)
for old_periodic_task in old_template.periodic_task.all()
])
other_options_created = ExecutionTemplateOption.objects.using(db_alias).bulk_create(
[default_option, *other_options]
)

history_to_update_qs = History.objects \
.using(db_alias) \
.filter(initiator_type='template', initiator=old_template.id)
for history in history_to_update_qs:
history.initiator = new_template.id
options = json.loads(history.json_options)
old_template_option = options.get('template_option')
if old_template_option is None:
options['template_option'] = str(default_option.id)
else:
try:
new_option = [
option for option in other_options_created
if slugify(option.name) == old_template_option
][0]
options['template_option'] = str(new_option.id)
except IndexError:
pass
history.json_options = json.dumps(options)
history_to_update.append(history)

for old_periodic_task in old_template.periodic_task.all():
new_periodic_task = TemplatePeriodicTask.objects.using(db_alias).create(
name=old_periodic_task.name,
template_option=default_option if not old_periodic_task.template_opt else [
option for option in other_options
if slugify(option.name) == old_periodic_task.template_opt
][0],
notes=old_periodic_task.notes,
type=old_periodic_task.type,
schedule=old_periodic_task.schedule,
enabled=old_periodic_task.enabled,
save_result=old_periodic_task.save_result,
)

history_to_update_qs = History.objects \
.using(db_alias) \
.filter(initiator_type='scheduler', initiator=old_periodic_task.id)
for history in history_to_update_qs:
history.initiator = new_periodic_task.id
history.json_options = json.dumps({
'template': new_periodic_task.template_option.template.id,
'template_option': str(new_periodic_task.template_option.id),
})
history_to_update.append(history)

for old_periodic_task in PeriodicTask.objects.filter(template_id=None):
variables = {}
Expand Down Expand Up @@ -177,7 +210,7 @@ def migrate_templates_data_direct(apps, schema_editor):
inventory=old_periodic_task._inventory_id or old_periodic_task.inventory_file),
template=new_template,
)
TemplatePeriodicTask.objects.using(db_alias).create(
new_periodic_task = TemplatePeriodicTask.objects.using(db_alias).create(
name=old_periodic_task.name,
template_option=default_option,
notes='',
Expand All @@ -187,10 +220,24 @@ def migrate_templates_data_direct(apps, schema_editor):
save_result=old_periodic_task.save_result,
)

history_to_update_qs = History.objects \
.using(db_alias) \
.filter(initiator_type='scheduler', initiator=old_periodic_task.id)
for history in history_to_update_qs:
history.initiator = new_periodic_task.id
history.json_options = json.dumps({
'template': new_periodic_task.template_option.template.id,
'template_option': str(new_periodic_task.template_option.id),
})
history_to_update.append(history)

History.objects.using(db_alias).bulk_update(history_to_update, fields=['initiator', 'json_options'])


def migrate_templates_data_backwards(apps, schema_editor):
Template = apps.get_model('main', 'Template')
PeriodicTask = apps.get_model('main', 'PeriodicTask')
History = apps.get_model('main', 'History')

ExecutionTemplate = apps.get_model('main', 'ExecutionTemplate')
ExecutionTemplateOption = apps.get_model('main', 'ExecutionTemplateOption')
Expand All @@ -216,8 +263,26 @@ def migrate_templates_data_backwards(apps, schema_editor):
new_template_id=new_template.id,
)

PeriodicTask.objects.using(db_alias).bulk_create([
PeriodicTask(
history_to_update = []

history_to_update_qs = History.objects \
.using(db_alias) \
.filter(initiator_type='template', initiator=new_template.id)
for history in history_to_update_qs:
history.initiator = old_template.id
options = json.loads(history.json_options)
template_option_id = options.get('template_option')
if str(default_option.id) == template_option_id:
del options['template_option']
elif template_option_id is not None:
option = other_options.filter(id=template_option_id).first()
if option:
options['template_option'] = option.name
history.json_options = json.dumps(options)
history_to_update.append(history)

for periodic_task in default_option.periodic_tasks.all():
old_periodic_task = PeriodicTask.objects.create(
name=periodic_task.name,
notes=periodic_task.notes,
mode='',
Expand All @@ -233,11 +298,21 @@ def migrate_templates_data_backwards(apps, schema_editor):
project=new_template.project,
template=old_template,
)
for periodic_task in default_option.periodic_tasks.all()
])

PeriodicTask.objects.using(db_alias).bulk_create([
PeriodicTask(
history_to_update_qs = History.objects \
.using(db_alias) \
.filter(initiator_type='scheduler', initiator=periodic_task.id)
for history in history_to_update_qs:
history.initiator = old_periodic_task.id
options = json.loads(history.json_options)
if 'template' in options:
del options['template']
if 'template_option' in options:
del options['template_option']
history.json_options = json.dumps(options)
history_to_update.append(history)

for periodic_task in TemplatePeriodicTask.objects.filter(template_option__in=other_options):
old_periodic_task = PeriodicTask.objects.create(
name=periodic_task.name,
notes=periodic_task.notes,
mode='',
Expand All @@ -253,9 +328,19 @@ def migrate_templates_data_backwards(apps, schema_editor):
project=new_template.project,
template=old_template,
)
for periodic_task in TemplatePeriodicTask.objects.filter(template_option__in=other_options)
])

history_to_update_qs = History.objects \
.using(db_alias) \
.filter(initiator_type='scheduler', initiator=periodic_task.id)
for history in history_to_update_qs:
history.initiator = old_periodic_task.id
options = json.loads(history.json_options)
if 'template' in options:
del options['template']
options['template_option'] = old_periodic_task.template_opt
history.json_options = json.dumps(options)
history_to_update.append(history)

History.objects.using(db_alias).bulk_update(history_to_update, fields=['initiator', 'json_options'])

def migrate_history_data_direct(apps, schema_editor):
History = apps.get_model('main', 'History')
Expand Down
34 changes: 18 additions & 16 deletions polemarch/main/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,16 +348,10 @@ def execute(self, plugin: str, project, execute_args, **kwargs):
validate_inventory_arguments(plugin, execute_args, project)

task_class = project.task_handlers.backend('EXECUTION')
plugin_class = self.backend(plugin)

mode = f'[{plugin} plugin]'
if plugin_class.arg_shown_on_history_as_mode is not None:
mode = execute_args.get(plugin_class.arg_shown_on_history_as_mode, mode)

history = self.create_history(
project,
plugin,
mode,
execute_args=execute_args,
initiator=kwargs.pop('initiator', 0),
initiator_type=kwargs.pop('initiator_type', 'project'),
Expand All @@ -383,27 +377,35 @@ def execute(self, plugin: str, project, execute_args, **kwargs):

return history

def create_history(self, project, kind, mode, execute_args, **kwargs):
def create_history(self, project, plugin, execute_args, **kwargs):
if not kwargs['save_result']:
return None

history_execute_args = {**execute_args}
inventory = history_execute_args.get('inventory', None)
if isinstance(inventory, str):
history_execute_args['inventory'] = inventory
inventory = None
elif isinstance(inventory, int):
inventory = project.inventories.get(id=inventory)
plugin_class = self.backend(plugin)

mode = f'[{plugin} plugin]'
if plugin_class.arg_shown_on_history_as_mode is not None:
mode = execute_args.get(plugin_class.arg_shown_on_history_as_mode, mode)

inventory = None
if plugin_class.arg_shown_on_history_as_inventory is not None:
inventory_field_name = plugin_class.arg_shown_on_history_as_inventory
inventory = execute_args.get(inventory_field_name, None)
if isinstance(inventory, str):
execute_args['inventory'] = inventory
inventory = None
elif isinstance(inventory, int):
inventory = project.inventories.get(id=inventory)

return project.history.create(
status='DELAY',
mode=mode,
start_time=timezone.now(),
inventory=inventory,
project=project,
kind=kind,
kind=plugin,
raw_stdout='',
execute_args=history_execute_args,
execute_args=execute_args,
initiator=kwargs['initiator'],
initiator_type=kwargs['initiator_type'],
executor=kwargs['executor'],
Expand Down
8 changes: 7 additions & 1 deletion polemarch/plugins/execution/ansible.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ class BaseAnsiblePlugin(BasePlugin):
-15: HistoryStatus.INTERRUPTED,
}

arg_shown_on_history_as_inventory = 'inventory'

def __init__(self, options=None, output_handler=None):
super().__init__(options, output_handler)
self.inventory = None
Expand Down Expand Up @@ -160,7 +162,11 @@ class AnsiblePlaybook(BaseAnsiblePlugin):
reference = ANSIBLE_REFERENCE.raw_dict['playbook']
arg_shown_on_history_as_mode = 'playbook'
serializer_fields = {
'playbook': AutoCompletionField(autocomplete='AnsiblePlaybook', autocomplete_property='playbook')
'playbook': AutoCompletionField(
autocomplete='AnsiblePlaybook',
autocomplete_property='playbook',
autocomplete_represent='playbook',
)
}

@property
Expand Down
5 changes: 5 additions & 0 deletions polemarch/plugins/execution/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ class BasePlugin:
``[<plugin name> plugin]`` string.
"""

arg_shown_on_history_as_inventory: Optional[str] = None # pylint: disable=invalid-name
"""
Name of argument presented in generated serializer which will be shown on list history page as *Inventory*.
"""

error_codes: Mapping[int, str] = {}
"""
This mapping will be looked up to choose an appropriate error message for history output if execution finished with
Expand Down
Loading

0 comments on commit 4e12a13

Please sign in to comment.