pref: 修改 applet host

pull/8997/head
ibuler 2022-10-27 16:26:15 +08:00
parent 1239247b5a
commit 28f4905a81
12 changed files with 54 additions and 218 deletions

View File

@ -96,6 +96,7 @@ class Migration(migrations.Migration):
('password_selector', models.CharField(blank=True, default='', max_length=128, verbose_name='Password selector')), ('password_selector', models.CharField(blank=True, default='', max_length=128, verbose_name='Password selector')),
('submit_selector', models.CharField(blank=True, default='', max_length=128, verbose_name='Submit selector')), ('submit_selector', models.CharField(blank=True, default='', max_length=128, verbose_name='Submit selector')),
('username_selector', models.CharField(blank=True, default='', max_length=128, verbose_name='Username selector')), ('username_selector', models.CharField(blank=True, default='', max_length=128, verbose_name='Username selector')),
('script', models.JSONField(blank=True, default=list, verbose_name='Script')),
], ],
options={ options={
'abstract': False, 'abstract': False,

View File

@ -22,6 +22,7 @@ class Migration(migrations.Migration):
('id', models.UUIDField(db_index=True, default=uuid.uuid4)), ('id', models.UUIDField(db_index=True, default=uuid.uuid4)),
('secret_type', models.CharField(choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), ('token', 'Token')], default='password', max_length=16, verbose_name='Secret type')), ('secret_type', models.CharField(choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), ('token', 'Token')], default='password', max_length=16, verbose_name='Secret type')),
('secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')), ('secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')),
('version', models.IntegerField(default=0, verbose_name='Version'),),
('history_id', models.AutoField(primary_key=True, serialize=False)), ('history_id', models.AutoField(primary_key=True, serialize=False)),
('history_date', models.DateTimeField(db_index=True)), ('history_date', models.DateTimeField(db_index=True)),
('history_change_reason', models.CharField(max_length=100, null=True)), ('history_change_reason', models.CharField(max_length=100, null=True)),
@ -46,6 +47,8 @@ class Migration(migrations.Migration):
('secret_type', models.CharField(choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), ('token', 'Token')], default='password', max_length=16, verbose_name='Secret type')), ('secret_type', models.CharField(choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), ('token', 'Token')], default='password', max_length=16, verbose_name='Secret type')),
('secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')), ('secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')),
('comment', models.TextField(blank=True, verbose_name='Comment')), ('comment', models.TextField(blank=True, verbose_name='Comment')),
('connectivity', models.CharField(choices=[('unknown', 'Unknown'), ('ok', 'Ok'), ('failed', 'Failed')], default='unknown', max_length=16, verbose_name='Connectivity')),
('date_verified', models.DateTimeField(null=True, verbose_name='Date verified')),
('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')), ('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')),
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('created_by', models.CharField(max_length=128, null=True, verbose_name='Created by')), ('created_by', models.CharField(max_length=128, null=True, verbose_name='Created by')),

View File

@ -35,7 +35,6 @@ class Migration(migrations.Migration):
name='BaseAutomation', name='BaseAutomation',
fields=[ fields=[
('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), ('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_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')),
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
@ -144,7 +143,7 @@ class Migration(migrations.Migration):
('execution', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.automationexecution')), ('execution', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.automationexecution')),
], ],
options={ options={
'verbose_name': 'Change secret', 'verbose_name': 'Change secret record',
}, },
), ),
migrations.AddField( migrations.AddField(
@ -156,13 +155,11 @@ class Migration(migrations.Migration):
name='ChangeSecretAutomation', name='ChangeSecretAutomation',
fields=[ 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')), ('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')),
('secret_types', models.JSONField(default=list, verbose_name='Secret types')), ('secret_type', models.CharField(choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), ('token', 'Token')], default='password', max_length=16, verbose_name='Secret type')),
('password_strategy', models.CharField(choices=[('specific', 'Specific'), ('random_one', 'All assets use the same random password'), ('random_all', 'All assets use different random password')], default='random_one', max_length=16, verbose_name='Password strategy')), ('secret_strategy', models.CharField(choices=[('specific', 'Specific'), ('random_one', 'All assets use the same random password'), ('random_all', 'All assets use different random password')], default='specific', max_length=16, verbose_name='Secret strategy')),
('password', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')), ('secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')),
('password_rules', models.JSONField(default=dict, verbose_name='Password rules')), ('password_rules', models.JSONField(default=dict, verbose_name='Password rules')),
('ssh_key_strategy', models.CharField(choices=[('specific', 'Specific'), ('random_one', 'All assets use the same random password'), ('random_all', 'All assets use different random password')], default='random_one', max_length=16)), ('ssh_key_change_strategy', models.CharField(choices=[('add', 'Append SSH KEY'), ('set', 'Empty and append SSH KEY'), ('set_jms', 'Replace (The key generated by JumpServer) ')], default='add', max_length=16, verbose_name='SSH key change strategy')),
('ssh_key', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH key')),
('ssh_key_change_strategy', models.CharField(choices=[('add', 'Append SSH KEY'), ('set', 'Empty and append SSH KEY'), ('set_jms', 'Replace (The key generated by JumpServer) ')], default='add', max_length=16, verbose_name='SSH key strategy')),
('recipients', models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Recipient')), ('recipients', models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Recipient')),
], ],
options={ options={

View File

@ -1,75 +0,0 @@
# Generated by Django 3.2.14 on 2022-10-19 09:06
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('assets', '0107_auto_20221019_1115'),
]
operations = [
migrations.AlterModelOptions(
name='automationexecution',
options={'verbose_name': 'Automation task execution'},
),
migrations.AlterModelOptions(
name='baseautomation',
options={'verbose_name': 'Automation task'},
),
migrations.AlterModelOptions(
name='changesecretrecord',
options={'verbose_name': 'Change secret record'},
),
migrations.AlterModelOptions(
name='verifyaccountautomation',
options={'verbose_name': 'Verify account automation'},
),
migrations.RenameField(
model_name='changesecretautomation',
old_name='password',
new_name='secret',
),
migrations.RemoveField(
model_name='baseautomation',
name='updated_by',
),
migrations.RemoveField(
model_name='changesecretautomation',
name='password_strategy',
),
migrations.RemoveField(
model_name='changesecretautomation',
name='secret_types',
),
migrations.RemoveField(
model_name='changesecretautomation',
name='ssh_key',
),
migrations.RemoveField(
model_name='changesecretautomation',
name='ssh_key_strategy',
),
migrations.AddField(
model_name='changesecretautomation',
name='secret_strategy',
field=models.CharField(choices=[('specific', 'Specific'), ('random_one', 'All assets use the same random password'), ('random_all', 'All assets use different random password')], default='specific', max_length=16, verbose_name='Secret strategy'),
),
migrations.AddField(
model_name='changesecretautomation',
name='secret_type',
field=models.CharField(choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), ('token', 'Token')], default='password', max_length=16, verbose_name='Secret type'),
),
migrations.AlterField(
model_name='automationexecution',
name='automation',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='executions', to='assets.baseautomation', verbose_name='Automation task'),
),
migrations.AlterField(
model_name='changesecretautomation',
name='ssh_key_change_strategy',
field=models.CharField(choices=[('add', 'Append SSH KEY'), ('set', 'Empty and append SSH KEY'), ('set_jms', 'Replace (The key generated by JumpServer) ')], default='add', max_length=16, verbose_name='SSH key change strategy'),
),
]

View File

@ -1,24 +0,0 @@
# Generated by Django 3.2.14 on 2022-10-19 12:40
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('assets', '0108_auto_20221019_1706'),
]
operations = [
migrations.AddField(
model_name='web',
name='script',
field=models.JSONField(blank=True, default=list, verbose_name='Script'),
),
migrations.AddField(
model_name='historicalaccount',
name='version',
field=models.IntegerField(default=0, verbose_name='Version'),
),
]

View File

@ -1,23 +0,0 @@
# Generated by Django 3.2.14 on 2022-10-21 07:06
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('assets', '0109_auto_20221019_2040'),
]
operations = [
migrations.AddField(
model_name='account',
name='connectivity',
field=models.CharField(choices=[('unknown', 'Unknown'), ('ok', 'Ok'), ('failed', 'Failed')], default='unknown', max_length=16, verbose_name='Connectivity'),
),
migrations.AddField(
model_name='account',
name='date_verified',
field=models.DateTimeField(null=True, verbose_name='Date verified'),
),
]

View File

@ -31,8 +31,7 @@ class OrgResourceSerializerMixin(CommonSerializerMixin, serializers.Serializer):
validators = [] validators = []
for v in _validators: for v in _validators:
if isinstance(v, UniqueTogetherValidator) \ if isinstance(v, UniqueTogetherValidator) and "org_id" in v.fields:
and "org_id" in v.fields:
v = ProjectUniqueValidator(v.queryset, v.fields) v = ProjectUniqueValidator(v.queryset, v.fields)
validators.append(v) validators.append(v)
return validators return validators

View File

@ -1,26 +1,20 @@
from rest_framework import viewsets from rest_framework import viewsets
from rest_framework.decorators import action
from orgs.utils import tmp_to_root_org from orgs.utils import tmp_to_builtin_org
from orgs.models import Organization
from assets.models import Host
from terminal import serializers, models from terminal import serializers, models
__all__ = ['AppletHostViewSet', 'AppletHostDeploymentViewSet'] __all__ = ['AppletHostViewSet', 'AppletHostDeploymentViewSet']
class AppletHostViewSet(viewsets.ModelViewSet): class AppletHostViewSet(viewsets.ModelViewSet):
queryset = models.AppletHost.objects.all()
serializer_class = serializers.AppletHostSerializer serializer_class = serializers.AppletHostSerializer
@action(methods=['get'], detail=False) def get_queryset(self):
def hosts(self, request): return models.AppletHost.objects.all()
with tmp_to_root_org():
kwargs = { def dispatch(self, request, *args, **kwargs):
'platform__name': 'RemoteAppHost', with tmp_to_builtin_org(system=1):
'org_id': Organization.SYSTEM_ID return super().dispatch(request, *args, **kwargs)
}
return Host.objects.filter(**kwargs)
class AppletHostDeploymentViewSet(viewsets.ModelViewSet): class AppletHostDeploymentViewSet(viewsets.ModelViewSet):

View File

@ -1,4 +1,4 @@
# Generated by Django 3.2.14 on 2022-10-24 06:52 # Generated by Django 3.2.14 on 2022-10-27 03:25
from django.db import migrations, models from django.db import migrations, models
import django.db.models.deletion import django.db.models.deletion
@ -8,7 +8,7 @@ import uuid
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
('assets', '0110_auto_20221021_1506'), ('assets', '0107_auto_20221019_1115'),
('terminal', '0053_auto_20220830_1244'), ('terminal', '0053_auto_20220830_1244'),
] ]
@ -26,8 +26,7 @@ class Migration(migrations.Migration):
('version', models.CharField(max_length=16, verbose_name='Version')), ('version', models.CharField(max_length=16, verbose_name='Version')),
('author', models.CharField(max_length=128, verbose_name='Author')), ('author', models.CharField(max_length=128, verbose_name='Author')),
('type', models.CharField(choices=[('general', 'General'), ('web', 'Web')], default='general', max_length=16, verbose_name='Type')), ('type', models.CharField(choices=[('general', 'General'), ('web', 'Web')], default='general', max_length=16, verbose_name='Type')),
('vcs_type', models.CharField(max_length=16, null=True, verbose_name='VCS type')), ('is_active', models.BooleanField(default=True, verbose_name='Is active')),
('vcs_url', models.CharField(max_length=256, null=True, verbose_name='URL')),
('protocols', models.JSONField(default=list, verbose_name='Protocol')), ('protocols', models.JSONField(default=list, verbose_name='Protocol')),
('tags', models.JSONField(default=list, verbose_name='Tags')), ('tags', models.JSONField(default=list, verbose_name='Tags')),
('comment', models.TextField(blank=True, default='', verbose_name='Comment')), ('comment', models.TextField(blank=True, default='', verbose_name='Comment')),
@ -39,12 +38,7 @@ class Migration(migrations.Migration):
migrations.CreateModel( migrations.CreateModel(
name='AppletHost', name='AppletHost',
fields=[ fields=[
('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), ('host_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.host')),
('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)),
('comment', models.TextField(blank=True, default='', verbose_name='Comment')),
('account_automation', models.BooleanField(default=False, verbose_name='Account automation')), ('account_automation', models.BooleanField(default=False, verbose_name='Account automation')),
('date_synced', models.DateTimeField(blank=True, null=True, verbose_name='Date synced')), ('date_synced', models.DateTimeField(blank=True, null=True, verbose_name='Date synced')),
('status', models.CharField(max_length=16, verbose_name='Status')), ('status', models.CharField(max_length=16, verbose_name='Status')),
@ -52,6 +46,7 @@ class Migration(migrations.Migration):
options={ options={
'abstract': False, 'abstract': False,
}, },
bases=('assets.host',),
), ),
migrations.CreateModel( migrations.CreateModel(
name='AppletPublication', name='AppletPublication',
@ -91,9 +86,4 @@ class Migration(migrations.Migration):
name='applets', name='applets',
field=models.ManyToManyField(through='terminal.AppletPublication', to='terminal.Applet', verbose_name='Applet'), field=models.ManyToManyField(through='terminal.AppletPublication', to='terminal.Applet', verbose_name='Applet'),
), ),
migrations.AddField(
model_name='applethost',
name='host',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='assets.host', verbose_name='Host'),
),
] ]

View File

@ -1,26 +0,0 @@
# Generated by Django 3.2.14 on 2022-10-26 08:31
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('terminal', '0054_auto_20221024_1452'),
]
operations = [
migrations.RemoveField(
model_name='applet',
name='vcs_type',
),
migrations.RemoveField(
model_name='applet',
name='vcs_url',
),
migrations.AddField(
model_name='applet',
name='is_active',
field=models.BooleanField(default=True, verbose_name='Is active'),
),
]

View File

@ -2,14 +2,13 @@ from django.db import models
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from common.db.models import JMSBaseModel from common.db.models import JMSBaseModel
from assets.models import Host
__all__ = ['AppletHost', 'AppletHostDeployment'] __all__ = ['AppletHost', 'AppletHostDeployment']
class AppletHost(JMSBaseModel): class AppletHost(Host):
host = models.ForeignKey('assets.Host', on_delete=models.PROTECT, verbose_name=_('Host'))
comment = models.TextField(default='', blank=True, verbose_name=_('Comment'))
account_automation = models.BooleanField(default=False, verbose_name=_('Account automation')) account_automation = models.BooleanField(default=False, verbose_name=_('Account automation'))
date_synced = models.DateTimeField(null=True, blank=True, verbose_name=_('Date synced')) date_synced = models.DateTimeField(null=True, blank=True, verbose_name=_('Date synced'))
status = models.CharField(max_length=16, verbose_name=_('Status')) status = models.CharField(max_length=16, verbose_name=_('Status'))
@ -19,7 +18,7 @@ class AppletHost(JMSBaseModel):
) )
def __str__(self): def __str__(self):
return self.host.name return self.name
class AppletHostDeployment(JMSBaseModel): class AppletHostDeployment(JMSBaseModel):

View File

@ -2,9 +2,9 @@ from rest_framework import serializers
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from common.drf.fields import ObjectRelatedField, LabeledChoiceField from common.drf.fields import ObjectRelatedField, LabeledChoiceField
from assets.models import Host, Platform from common.validators import ProjectUniqueValidator
from assets.models import Platform
from assets.serializers import HostSerializer from assets.serializers import HostSerializer
from orgs.utils import tmp_to_builtin_org
from ..models import Applet, AppletPublication, AppletHost, AppletHostDeployment from ..models import Applet, AppletPublication, AppletHost, AppletHostDeployment
@ -48,41 +48,42 @@ class AppletPublicationSerializer(serializers.ModelSerializer):
] + read_only_fields ] + read_only_fields
class AppletHostSerializer(serializers.ModelSerializer): class AppletHostSerializer(HostSerializer):
host = HostSerializer(allow_null=True, required=False) class Meta(HostSerializer.Meta):
class Meta:
model = AppletHost model = AppletHost
fields_mini = ['id', 'host'] fields = HostSerializer.Meta.fields + [
read_only_fields = ['date_synced', 'status', 'date_created', 'date_updated'] 'account_automation', 'status', 'date_synced'
fields = fields_mini + ['comment', 'account_automation'] + read_only_fields ]
extra_kwargs = {
'status': {'read_only': True},
'date_synced': {'read_only': True}
}
def __init__(self, *args, **kwargs): def __init__(self, *args, data=None, **kwargs):
self.host_data = kwargs.get('data', {}).pop('host', {}) self.set_initial_data(data)
super().__init__(*args, **kwargs) super().__init__(*args, data=data, **kwargs)
def _create_host(self): @staticmethod
def set_initial_data(data):
if not data:
return
platform = Platform.objects.get(name='RemoteAppHost') platform = Platform.objects.get(name='RemoteAppHost')
data = { data.update({
**self.host_data,
'platform': platform.id, 'platform': platform.id,
'nodes_display': [ 'nodes_display': [
'RemoteAppHosts' 'RemoteAppHosts'
] ]
} })
serializer = HostSerializer(data=data)
try:
serializer.is_valid(raise_exception=True)
except serializers.ValidationError:
raise serializers.ValidationError({'host': serializer.errors})
host = serializer.save()
return host
def create(self, validated_data): def get_validators(self):
with tmp_to_builtin_org(system=1): validators = super().get_validators()
host = self._create_host() # 不知道为啥没有继承过来
instance = super().create({**validated_data, 'host': host}) uniq_validator = ProjectUniqueValidator(
return instance queryset=AppletHost.objects.all(),
fields=('org_id', 'name')
)
validators.append(uniq_validator)
return validators
class AppletHostDeploymentSerializer(serializers.ModelSerializer): class AppletHostDeploymentSerializer(serializers.ModelSerializer):