From aaa0ed4c72d9190a7f87b31531885144d6482221 Mon Sep 17 00:00:00 2001 From: Ryan Petrello Date: Fri, 30 Jun 2017 15:57:25 -0400 Subject: [PATCH 1/3] add help text for built-in Tower credential types see: #6561 --- .../0042_v320_drop_v1_credential_fields.py | 2 +- awx/main/models/credential.py | 56 +++++++++++++++---- 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/awx/main/migrations/0042_v320_drop_v1_credential_fields.py b/awx/main/migrations/0042_v320_drop_v1_credential_fields.py index b1eb8d6489..ea6f905e0f 100644 --- a/awx/main/migrations/0042_v320_drop_v1_credential_fields.py +++ b/awx/main/migrations/0042_v320_drop_v1_credential_fields.py @@ -99,7 +99,7 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='credential', name='credential_type', - field=models.ForeignKey(related_name='credentials', to='main.CredentialType', null=False, help_text='Type for this credential. Credential Types define valid fields (e.g,. "username", "password") and their properties (e.g,. "username is required" or "password should be stored with encryption").') + field=models.ForeignKey(related_name='credentials', to='main.CredentialType', null=False, help_text='Specify the type of credential you want to create. Refer to the Ansible Tower documentation for details on each type.') ), migrations.AlterField( model_name='credential', diff --git a/awx/main/models/credential.py b/awx/main/models/credential.py index 585d57ae8e..c3aecae4b7 100644 --- a/awx/main/models/credential.py +++ b/awx/main/models/credential.py @@ -219,10 +219,8 @@ class Credential(PasswordFieldsModel, CommonModelNameNotUnique, ResourceMixin): 'CredentialType', related_name='credentials', null=False, - help_text=_('Type for this credential. Credential Types define ' - 'valid fields (e.g,. "username", "password") and their ' - 'properties (e.g,. "username is required" or "password ' - 'should be stored with encryption").') + help_text=_('Specify the type of credential you want to create. Refer ' + 'to the Ansible Tower documentation for details on each type.') ) organization = models.ForeignKey( 'Organization', @@ -608,7 +606,10 @@ def ssh(cls): 'id': 'become_method', 'label': 'Privilege Escalation Method', 'choices': map(operator.itemgetter(0), - V1Credential.FIELDS['become_method'].choices) + V1Credential.FIELDS['become_method'].choices), + 'help_text': ('Specify a method for "become" operations. This is ' + 'equivalent to specifying the --become-method ' + 'Ansible parameter.') }, { 'id': 'become_username', 'label': 'Privilege Escalation Username', @@ -738,6 +739,10 @@ def aws(cls): 'label': 'STS Token', 'type': 'string', 'secret': True, + 'help_text': ('Security Token Service (STS) is a web service ' + 'that enables you to request temporary, ' + 'limited-privilege credentials for AWS Identity ' + 'and Access Management (IAM) users.'), }], 'required': ['username', 'password'] } @@ -764,6 +769,8 @@ def openstack(cls): 'id': 'host', 'label': 'Host (Authentication URL)', 'type': 'string', + 'help_text': ('The host to authenticate with. For example, ' + 'https://openstack.business.com/v2.0/') }, { 'id': 'project', 'label': 'Project (Tenant Name)', @@ -771,7 +778,11 @@ def openstack(cls): }, { 'id': 'domain', 'label': 'Domain Name', - 'type': 'string' + 'type': 'string', + 'help_text': ('OpenStack domains define administrative boundaries. ' + 'It is only needed for Keystone v3 authentication ' + 'URLs. Refer to Ansible Tower documentation for ' + 'common scenarios.') }], 'required': ['username', 'password', 'host', 'project'] } @@ -789,6 +800,8 @@ def vmware(cls): 'id': 'host', 'label': 'VCenter Host', 'type': 'string', + 'help_text': ('Enter the hostname or IP address which corresponds ' + 'to your VMware vCenter.') }, { 'id': 'username', 'label': 'Username', @@ -815,6 +828,8 @@ def satellite6(cls): 'id': 'host', 'label': 'Satellite 6 URL', 'type': 'string', + 'help_text': ('Enter the URL which corresponds to your Red Hat ' + 'Satellite 6 server. For example, https://satellite.example.org') }, { 'id': 'username', 'label': 'Username', @@ -840,6 +855,9 @@ def cloudforms(cls): 'id': 'host', 'label': 'CloudForms URL', 'type': 'string', + 'help_text': ('Enter the URL for the virtual machine which ' + 'corresponds to your CloudForm instance. ' + 'For example, https://cloudforms.example.org') }, { 'id': 'username', 'label': 'Username', @@ -864,18 +882,25 @@ def gce(cls): 'fields': [{ 'id': 'username', 'label': 'Service Account Email Address', - 'type': 'string' + 'type': 'string', + 'help_text': ('The email address assigned to the Google Compute ' + 'Engine service account.') }, { 'id': 'project', 'label': 'Project', - 'type': 'string' + 'type': 'string', + 'help_text': ('The Project ID is the GCE assigned identification. ' + 'It is constructed as two words followed by a three ' + 'digit number. Example: adjective-noun-000') }, { 'id': 'ssh_key_data', 'label': 'RSA Private Key', 'type': 'string', 'format': 'ssh_private_key', 'secret': True, - 'multiline': True + 'multiline': True, + 'help_text': ('Paste the contents of the PEM file associated ' + 'with the service account email.') }] } ) @@ -891,14 +916,19 @@ def azure(cls): 'fields': [{ 'id': 'username', 'label': 'Subscription ID', - 'type': 'string' + 'type': 'string', + 'help_text': ('Subscription ID is an Azure construct, which is ' + 'mapped to a username.') }, { 'id': 'ssh_key_data', 'label': 'Management Certificate', 'type': 'string', 'format': 'ssh_private_key', 'secret': True, - 'multiline': True + 'multiline': True, + 'help_text': ('Paste the contents of the PEM file that corresponds ' + 'to the certificate you uploaded in the Microsoft ' + 'Azure console.') }] } ) @@ -914,7 +944,9 @@ def azure_rm(cls): 'fields': [{ 'id': 'subscription', 'label': 'Subscription ID', - 'type': 'string' + 'type': 'string', + 'help_text': ('Subscription ID is an Azure construct, which is ' + 'mapped to a username.') }, { 'id': 'username', 'label': 'Username', From 0a4c5d9d30d6ae5b738e8c88ca61fa8cdc28ae1c Mon Sep 17 00:00:00 2001 From: Ryan Petrello Date: Fri, 30 Jun 2017 16:42:59 -0400 Subject: [PATCH 2/3] translate labels and help_text for Credential Types (where possible) see: #6327 --- awx/api/serializers.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/awx/api/serializers.py b/awx/api/serializers.py index 8b39357843..9ae0273a4d 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -1923,6 +1923,17 @@ class CredentialTypeSerializer(BaseSerializer): ) return res + def to_representation(self, data): + value = super(CredentialTypeSerializer, self).to_representation(data) + + # translate labels and help_text for credential fields "managed by Tower" + if value.get('managed_by_tower'): + for field in value.get('inputs', {}).get('fields', []): + field['label'] = _(field['label']) + if 'help_text' in field: + field['help_text'] = _(field['help_text']) + return value + # TODO: remove when API v1 is removed @six.add_metaclass(BaseSerializerMetaclass) From 2f6d6bfd674d9354e1483a110e5045bfb158cadb Mon Sep 17 00:00:00 2001 From: Ryan Petrello Date: Mon, 3 Jul 2017 11:41:21 -0400 Subject: [PATCH 3/3] update help text for credential inputs and injectors see: #6078 --- .../0040_v320_add_credentialtype_model.py | 4 ++-- .../0042_v320_drop_v1_credential_fields.py | 2 +- awx/main/models/credential.py | 17 +++++++++++------ 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/awx/main/migrations/0040_v320_add_credentialtype_model.py b/awx/main/migrations/0040_v320_add_credentialtype_model.py index 226c160fbf..626f061d10 100644 --- a/awx/main/migrations/0040_v320_add_credentialtype_model.py +++ b/awx/main/migrations/0040_v320_add_credentialtype_model.py @@ -25,8 +25,8 @@ class Migration(migrations.Migration): ('name', models.CharField(max_length=512)), ('kind', models.CharField(max_length=32, choices=[(b'ssh', 'SSH'), (b'vault', 'Vault'), (b'net', 'Network'), (b'scm', 'Source Control'), (b'cloud', 'Cloud'), (b'insights', 'Insights')])), ('managed_by_tower', models.BooleanField(default=False, editable=False)), - ('inputs', awx.main.fields.CredentialTypeInputField(default={}, blank=True)), - ('injectors', awx.main.fields.CredentialTypeInjectorField(default={}, blank=True)), + ('inputs', awx.main.fields.CredentialTypeInputField(default={}, blank=True, help_text='Enter inputs using either JSON or YAML syntax. Use the radio button to toggle between the two. Refer to the Ansible Tower documentation for example syntax.')), + ('injectors', awx.main.fields.CredentialTypeInjectorField(default={}, blank=True, help_text='Enter injectors using either JSON or YAML syntax. Use the radio button to toggle between the two. Refer to the Ansible Tower documentation for example syntax.')), ('created_by', models.ForeignKey(related_name="{u'class': 'credentialtype', u'app_label': 'main'}(class)s_created+", on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)), ('modified_by', models.ForeignKey(related_name="{u'class': 'credentialtype', u'app_label': 'main'}(class)s_modified+", on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)), ('tags', taggit.managers.TaggableManager(to='taggit.Tag', through='taggit.TaggedItem', blank=True, help_text='A comma-separated list of tags.', verbose_name='Tags')), diff --git a/awx/main/migrations/0042_v320_drop_v1_credential_fields.py b/awx/main/migrations/0042_v320_drop_v1_credential_fields.py index ea6f905e0f..a618e952a7 100644 --- a/awx/main/migrations/0042_v320_drop_v1_credential_fields.py +++ b/awx/main/migrations/0042_v320_drop_v1_credential_fields.py @@ -104,7 +104,7 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='credential', name='inputs', - field=awx.main.fields.CredentialInputField(default={}, help_text='Data structure used to specify input values (e.g., {"username": "jane-doe", "password": "secret"}). Valid fields and their requirements vary depending on the fields defined on the chosen CredentialType.', blank=True), + field=awx.main.fields.CredentialInputField(default={}, help_text='Enter inputs using either JSON or YAML syntax. Use the radio button to toggle between the two. Refer to the Ansible Tower documentation for example syntax.', blank=True), ), migrations.RemoveField( model_name='job', diff --git a/awx/main/models/credential.py b/awx/main/models/credential.py index c3aecae4b7..d0524dfa78 100644 --- a/awx/main/models/credential.py +++ b/awx/main/models/credential.py @@ -233,10 +233,9 @@ class Credential(PasswordFieldsModel, CommonModelNameNotUnique, ResourceMixin): inputs = CredentialInputField( blank=True, default={}, - help_text=_('Data structure used to specify input values (e.g., ' - '{"username": "jane-doe", "password": "secret"}). Valid ' - 'fields and their requirements vary depending on the ' - 'fields defined on the chosen CredentialType.') + help_text=_('Enter inputs using either JSON or YAML syntax. Use the ' + 'radio button to toggle between the two. Refer to the ' + 'Ansible Tower documentation for example syntax.') ) admin_role = ImplicitRoleField( parent_role=[ @@ -419,11 +418,17 @@ class CredentialType(CommonModelNameNotUnique): ) inputs = CredentialTypeInputField( blank=True, - default={} + default={}, + help_text=_('Enter inputs using either JSON or YAML syntax. Use the ' + 'radio button to toggle between the two. Refer to the ' + 'Ansible Tower documentation for example syntax.') ) injectors = CredentialTypeInjectorField( blank=True, - default={} + default={}, + help_text=_('Enter injectors using either JSON or YAML syntax. Use the ' + 'radio button to toggle between the two. Refer to the ' + 'Ansible Tower documentation for example syntax.') ) def get_absolute_url(self, request=None):