diff --git a/apps/assets/const/base.py b/apps/assets/const/base.py index aa5070d5e..4b147f8ef 100644 --- a/apps/assets/const/base.py +++ b/apps/assets/const/base.py @@ -6,8 +6,10 @@ from .protocol import Protocol class BaseType(TextChoices): """ - 约束应该考虑代是对平台对限制,避免多余对选项,如: mysql 开启 ssh, 或者开启了也没有作用, 比如 k8s 开启了 domain,目前还不支持 + 约束应该考虑代是对平台对限制,避免多余对选项,如: mysql 开启 ssh, + 或者开启了也没有作用, 比如 k8s 开启了 domain,目前还不支持 """ + @classmethod def get_constrains(cls): constrains = {} @@ -36,7 +38,7 @@ class BaseType(TextChoices): if choices == '__self__': choices = [tp] protocols = [{'name': name, **settings.get(name, {})} for name in choices] - protocols[0]['primary'] = True + protocols[0]['default'] = True return protocols @classmethod @@ -74,5 +76,3 @@ class BaseType(TextChoices): choice for choice in cls_choices if choice[0] in tps ] - - diff --git a/apps/assets/migrations/0111_auto_20230321_1633.py b/apps/assets/migrations/0111_auto_20230321_1633.py new file mode 100644 index 000000000..0f1ba7f14 --- /dev/null +++ b/apps/assets/migrations/0111_auto_20230321_1633.py @@ -0,0 +1,35 @@ +# Generated by Django 3.2.17 on 2023-03-21 08:33 + +from django.db import migrations, models + + +def migrate_platform_charset(apps, schema_editor): + platform_model = apps.get_model('assets', 'Platform') + platform_model.objects.filter(charset='utf8').update(charset='utf-8') + + +def migrate_platform_protocol_primary(apps, schema_editor): + platform_model = apps.get_model('assets', 'Platform') + platforms = platform_model.objects.all() + + for platform in platforms: + p = platform.protocols.first() + p.primary = True + p.save() + + +class Migration(migrations.Migration): + + dependencies = [ + ('assets', '0110_auto_20230315_1741'), + ] + + operations = [ + migrations.AddField( + model_name='platformprotocol', + name='primary', + field=models.BooleanField(default=False, verbose_name='Primary'), + ), + migrations.RunPython(migrate_platform_charset), + migrations.RunPython(migrate_platform_protocol_primary), + ] diff --git a/apps/assets/models/asset/common.py b/apps/assets/models/asset/common.py index 3a38699e8..8643f4a6c 100644 --- a/apps/assets/models/asset/common.py +++ b/apps/assets/models/asset/common.py @@ -191,25 +191,6 @@ class Asset(NodesRelationMixin, AbsConnectivity, JMSOrgBaseModel): names.append(n.name + ':' + n.value) return names - @lazyproperty - def primary_protocol(self): - from assets.const.types import AllTypes - primary_protocol_name = AllTypes.get_primary_protocol_name(self.category, self.type) - protocol = self.protocols.filter(name=primary_protocol_name).first() - return protocol - - @lazyproperty - def protocol(self): - if not self.primary_protocol: - return 'none' - return self.primary_protocol.name - - @lazyproperty - def port(self): - if not self.primary_protocol: - return 0 - return self.primary_protocol.port - @lazyproperty def type(self): return self.platform.type diff --git a/apps/assets/models/platform.py b/apps/assets/models/platform.py index 488525ccd..e2262af04 100644 --- a/apps/assets/models/platform.py +++ b/apps/assets/models/platform.py @@ -10,29 +10,17 @@ __all__ = ['Platform', 'PlatformProtocol', 'PlatformAutomation'] class PlatformProtocol(models.Model): - SETTING_ATTRS = { - 'console': False, - 'security': 'any,tls,rdp', - 'sftp_enabled': True, - 'sftp_home': '/tmp' - } - default = models.BooleanField(default=False, verbose_name=_('Default')) - required = models.BooleanField(default=False, verbose_name=_('Required')) name = models.CharField(max_length=32, verbose_name=_('Name')) port = models.IntegerField(verbose_name=_('Port')) + primary = models.BooleanField(default=False, verbose_name=_('Primary')) + required = models.BooleanField(default=False, verbose_name=_('Required')) + default = models.BooleanField(default=False, verbose_name=_('Default')) setting = models.JSONField(verbose_name=_('Setting'), default=dict) platform = models.ForeignKey('Platform', on_delete=models.CASCADE, related_name='protocols') def __str__(self): return '{}/{}'.format(self.name, self.port) - @property - def primary(self): - primary_protocol_name = AllTypes.get_primary_protocol_name( - self.platform.category, self.platform.type - ) - return self.name == primary_protocol_name - @property def secret_types(self): return Protocol.settings().get(self.name, {}).get('secret_types') @@ -100,11 +88,6 @@ class Platform(JMSBaseModel): ) return linux.id - @property - def primary_protocol(self): - primary_protocol_name = AllTypes.get_primary_protocol_name(self.category, self.type) - return self.protocols.filter(name=primary_protocol_name).first() - def __str__(self): return self.name diff --git a/apps/assets/serializers/platform.py b/apps/assets/serializers/platform.py index 15b4e7cca..7485224e7 100644 --- a/apps/assets/serializers/platform.py +++ b/apps/assets/serializers/platform.py @@ -72,16 +72,15 @@ class PlatformAutomationSerializer(serializers.ModelSerializer): } -class PlatformProtocolsSerializer(serializers.ModelSerializer): +class PlatformProtocolSerializer(serializers.ModelSerializer): setting = ProtocolSettingSerializer(required=False, allow_null=True) - primary = serializers.BooleanField(read_only=True, label=_("Primary")) class Meta: model = PlatformProtocol fields = [ "id", "name", "port", "primary", - "default", "required", "secret_types", - "setting", + "required", "default", + "secret_types", "setting", ] @@ -91,7 +90,7 @@ class PlatformSerializer(WritableNestedModelSerializer): ) type = LabeledChoiceField(choices=AllTypes.choices(), label=_("Type")) category = LabeledChoiceField(choices=Category.choices, label=_("Category")) - protocols = PlatformProtocolsSerializer( + protocols = PlatformProtocolSerializer( label=_("Protocols"), many=True, required=False ) automation = PlatformAutomationSerializer(label=_("Automation"), required=False) @@ -126,6 +125,16 @@ class PlatformSerializer(WritableNestedModelSerializer): ) return queryset + def validate_protocols(self, protocols): + if not protocols: + raise serializers.ValidationError(_("Protocols is required")) + primary = [p for p in protocols if p.get('primary')] + if not primary: + protocols[0]['primary'] = True + # 这里不设置不行,write_nested 不使用 validated 中的 + self.initial_data['protocols'] = protocols + return protocols + class PlatformOpsMethodSerializer(serializers.Serializer): id = serializers.CharField(read_only=True) diff --git a/apps/ops/ansible/inventory.py b/apps/ops/ansible/inventory.py index 8c45cba39..fb143cda5 100644 --- a/apps/ops/ansible/inventory.py +++ b/apps/ops/ansible/inventory.py @@ -99,13 +99,33 @@ class JMSInventory: if gateway: host.update(self.make_proxy_command(gateway)) + @staticmethod + def get_primary_protocol(protocols): + primary_protocol = [p for p in protocols if p.primary] + if len(primary_protocol) >= 1: + primary = primary_protocol[0] + elif protocols: + primary = protocols[0] + else: + primary = None + + if primary: + protocol = primary.name + port = primary.port + else: + protocol = 'null' + port = 0 + return protocol, port + def asset_to_host(self, asset, account, automation, protocols, platform): + protocol, port = self.get_primary_protocol(protocols) + host = { 'name': '{}'.format(asset.name.replace(' ', '_')), 'jms_asset': { 'id': str(asset.id), 'name': asset.name, 'address': asset.address, 'type': asset.type, 'category': asset.category, - 'protocol': asset.protocol, 'port': asset.port, + 'protocol': protocol, 'port': port, 'spec_info': asset.spec_info, 'secret_info': asset.secret_info, 'protocols': [{'name': p.name, 'port': p.port} for p in protocols], },