diff --git a/apps/assets/automations/change_password/manager.py b/apps/assets/automations/change_password/manager.py index aa86c6d08..6c315cb82 100644 --- a/apps/assets/automations/change_password/manager.py +++ b/apps/assets/automations/change_password/manager.py @@ -6,7 +6,7 @@ from collections import defaultdict import yaml from django.utils.translation import gettext as _ -from ops.ansible import PlaybookRunner, JMSInventory +from ops.ansible import PlaybookRunner from ..base.manager import BasePlaybookManager from assets.automations.methods import platform_automation_methods @@ -19,6 +19,7 @@ class ChangePasswordManager(BasePlaybookManager): for method in platform_automation_methods } self.method_hosts_mapper = defaultdict(list) + self.playbooks = [] def host_duplicator(self, host, asset=None, account=None, platform=None, **kwargs): accounts = asset.accounts.all() @@ -72,19 +73,23 @@ class ChangePasswordManager(BasePlaybookManager): if isinstance(host_playbook_play, list): host_playbook_play = host_playbook_play[0] - plays = [] - for name in host_names: + step = 10 + hosts_grouped = [host_names[i:i+step] for i in range(0, len(host_names), step)] + for i, hosts in enumerate(hosts_grouped): + plays = [] play = deepcopy(host_playbook_play) - play['hosts'] = name + play['hosts'] = ':'.join(hosts) plays.append(play) - with open(sub_playbook_path, 'w') as f: - yaml.safe_dump(plays, f) + playbook_path = os.path.join(sub_playbook_dir, 'part_{}.yml'.format(i)) + with open(playbook_path, 'w') as f: + yaml.safe_dump(plays, f) + self.playbooks.append(playbook_path) - playbook.append({ - 'name': method['name'], - 'import_playbook': os.path.join(method_playbook_dir_name, 'main.yml') - }) + playbook.append({ + 'name': method['name'] + ' for part {}'.format(i), + 'import_playbook': os.path.join(method_playbook_dir_name, 'part_{}.yml'.format(i)) + }) with open(self.playbook_path, 'w') as f: yaml.safe_dump(playbook, f) @@ -99,4 +104,3 @@ class ChangePasswordManager(BasePlaybookManager): ) - diff --git a/apps/assets/migrations/0107_auto_20221010_0959.py b/apps/assets/migrations/0107_auto_20221010_0959.py new file mode 100644 index 000000000..f9cace60f --- /dev/null +++ b/apps/assets/migrations/0107_auto_20221010_0959.py @@ -0,0 +1,116 @@ +# Generated by Django 3.2.14 on 2022-10-10 01:59 + +import common.db.fields +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('assets', '0106_auto_20220916_1556'), + ] + + operations = [ + migrations.CreateModel( + name='BaseAutomation', + fields=[ + ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), + ('updated_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Updated by')), + ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), + ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('name', models.CharField(max_length=128, verbose_name='Name')), + ('is_periodic', models.BooleanField(default=False)), + ('interval', models.IntegerField(blank=True, default=24, null=True, verbose_name='Cycle perform')), + ('crontab', models.CharField(blank=True, max_length=128, null=True, verbose_name='Regularly perform')), + ('accounts', models.JSONField(default=list, verbose_name='Accounts')), + ('type', models.CharField(max_length=16, verbose_name='Type')), + ('comment', models.TextField(blank=True, verbose_name='Comment')), + ('assets', models.ManyToManyField(blank=True, to='assets.Asset', verbose_name='Assets')), + ('nodes', models.ManyToManyField(blank=True, to='assets.Node', verbose_name='Nodes')), + ], + options={ + 'verbose_name': 'Automation plan', + 'unique_together': {('org_id', 'name')}, + }, + ), + migrations.AddField( + model_name='label', + name='created_by', + field=models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by'), + ), + migrations.AddField( + model_name='label', + name='date_updated', + field=models.DateTimeField(auto_now=True, verbose_name='Date updated'), + ), + migrations.AddField( + model_name='label', + name='updated_by', + field=models.CharField(blank=True, max_length=32, null=True, verbose_name='Updated by'), + ), + migrations.CreateModel( + name='DiscoveryAutomation', + fields=[ + ('baseautomation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.baseautomation')), + ], + options={ + 'verbose_name': 'Discovery strategy', + }, + bases=('assets.baseautomation',), + ), + migrations.CreateModel( + name='ReconcileAutomation', + fields=[ + ('baseautomation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.baseautomation')), + ], + options={ + 'verbose_name': 'Reconcile strategy', + }, + bases=('assets.baseautomation',), + ), + migrations.CreateModel( + name='VerifyAutomation', + fields=[ + ('baseautomation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.baseautomation')), + ], + options={ + 'verbose_name': 'Verify strategy', + }, + bases=('assets.baseautomation',), + ), + migrations.CreateModel( + name='AutomationExecution', + fields=[ + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('status', models.CharField(default='pending', max_length=16)), + ('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')), + ('date_start', models.DateTimeField(db_index=True, null=True, verbose_name='Date start')), + ('date_finished', models.DateTimeField(null=True, verbose_name='Date finished')), + ('snapshot', common.db.fields.EncryptJsonDictTextField(blank=True, default=dict, null=True, verbose_name='Automation snapshot')), + ('trigger', models.CharField(choices=[('manual', 'Manual trigger'), ('timing', 'Timing trigger')], default='manual', max_length=128, verbose_name='Trigger mode')), + ('automation', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='executions', to='assets.baseautomation', verbose_name='Automation strategy')), + ], + options={ + 'verbose_name': 'Automation strategy execution', + }, + ), + migrations.CreateModel( + name='ChangePasswordAutomation', + fields=[ + ('baseautomation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.baseautomation')), + ('password', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')), + ('recipients', models.ManyToManyField(blank=True, related_name='recipients_change_auth_strategy', to=settings.AUTH_USER_MODEL, verbose_name='Recipient')), + ], + options={ + 'verbose_name': 'Change auth strategy', + }, + bases=('assets.baseautomation',), + ), + ] diff --git a/apps/ops/migrations/0026_auto_20221009_2050.py b/apps/ops/migrations/0026_auto_20221009_2050.py new file mode 100644 index 000000000..699246531 --- /dev/null +++ b/apps/ops/migrations/0026_auto_20221009_2050.py @@ -0,0 +1,100 @@ +# Generated by Django 3.2.14 on 2022-10-09 12:50 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('assets', '0106_auto_20220916_1556'), + ('ops', '0025_auto_20221008_1631'), + ] + + operations = [ + migrations.CreateModel( + name='Playbook', + fields=[ + ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), + ('updated_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Updated by')), + ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), + ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('name', models.CharField(max_length=128, verbose_name='Name')), + ('is_periodic', models.BooleanField(default=False)), + ('interval', models.IntegerField(blank=True, default=24, null=True, verbose_name='Cycle perform')), + ('crontab', models.CharField(blank=True, max_length=128, null=True, verbose_name='Regularly perform')), + ('account', models.CharField(default='root', max_length=128, verbose_name='Account')), + ('account_policy', models.CharField(default='root', max_length=128, verbose_name='Account policy')), + ('date_last_run', models.DateTimeField(null=True, verbose_name='Date last run')), + ('path', models.FilePathField(max_length=1024, verbose_name='Playbook')), + ('comment', models.TextField(blank=True, verbose_name='Comment')), + ('assets', models.ManyToManyField(to='assets.Asset', verbose_name='Assets')), + ], + options={ + 'abstract': False, + }, + ), + migrations.AlterField( + model_name='adhocexecution', + name='date_finished', + field=models.DateTimeField(null=True, verbose_name='Date finished'), + ), + migrations.CreateModel( + name='PlaybookTemplate', + fields=[ + ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), + ('updated_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Updated by')), + ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), + ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('name', models.CharField(max_length=128, verbose_name='Name')), + ('path', models.FilePathField(verbose_name='Path')), + ('comment', models.TextField(blank=True, verbose_name='Comment')), + ], + options={ + 'verbose_name': 'Playbook template', + 'ordering': ['name'], + 'unique_together': {('org_id', 'name')}, + }, + ), + migrations.CreateModel( + name='PlaybookExecution', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('status', models.CharField(default='running', max_length=16, verbose_name='Status')), + ('result', models.JSONField(blank=True, null=True, verbose_name='Result')), + ('summary', models.JSONField(default=dict, verbose_name='Summary')), + ('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')), + ('date_start', models.DateTimeField(db_index=True, null=True, verbose_name='Date start')), + ('date_finished', models.DateTimeField(null=True, verbose_name='Date finished')), + ('path', models.FilePathField(max_length=1024, verbose_name='Run dir')), + ('creator', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='Creator')), + ('task', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='ops.playbook', verbose_name='Task')), + ], + options={ + 'ordering': ['-date_start'], + 'abstract': False, + }, + ), + migrations.AddField( + model_name='playbook', + name='last_execution', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='ops.playbookexecution', verbose_name='Last execution'), + ), + migrations.AddField( + model_name='playbook', + name='owner', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='Owner'), + ), + migrations.AddField( + model_name='playbook', + name='template', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='ops.playbooktemplate', verbose_name='Template'), + ), + ]