diff --git a/awx/main/fields.py b/awx/main/fields.py index b8f8d9fbf3..ee5fb13f74 100644 --- a/awx/main/fields.py +++ b/awx/main/fields.py @@ -529,7 +529,7 @@ class CredentialTypeInputField(JSONSchemaField): 'items': { 'type': 'object', 'properties': { - 'type': {'enum': ['string', 'number']}, + 'type': {'enum': ['string', 'boolean']}, 'format': {'enum': ['ssh_private_key']}, 'choices': { 'type': 'array', @@ -578,6 +578,18 @@ class CredentialTypeInputField(JSONSchemaField): ) ids[id_] = True + if 'type' not in field: + # If no type is specified, default to string + field['type'] = 'string' + + for key in ('choices', 'multiline', 'format'): + if key in field and field['type'] != 'string': + raise django_exceptions.ValidationError( + _('%s not allowed for %s type (%s)' % (key, field['type'], field['id'])), + code='invalid', + params={'value': value}, + ) + class CredentialTypeInjectorField(JSONSchemaField): diff --git a/awx/main/tests/functional/test_credential.py b/awx/main/tests/functional/test_credential.py index 4c519285ec..7d76e3d377 100644 --- a/awx/main/tests/functional/test_credential.py +++ b/awx/main/tests/functional/test_credential.py @@ -60,15 +60,18 @@ def test_cloud_kind_uniqueness(): ({'fields': {}}, False), ({'fields': 123}, False), ({'fields': [{'id': 'username', 'label': 'Username', 'foo': 'bar'}]}, False), + ({'fields': [{'id': 'username', 'label': 'Username'}]}, True), ({'fields': [{'id': 'username', 'label': 'Username', 'type': 'string'}]}, True), ({'fields': [{'id': 'username', 'label': 'Username', 'help_text': 1}]}, False), ({'fields': [{'id': 'username', 'label': 'Username', 'help_text': 'Help Text'}]}, True), # noqa ({'fields': [{'id': 'username', 'label': 'Username'}, {'id': 'username', 'label': 'Username 2'}]}, False), # noqa - ({'fields': [{'id': '$invalid$', 'label': 'Invalid'}]}, False), # noqa - ({'fields': [{'id': 'password', 'label': 'Password', 'type': 'number'}]}, True), + ({'fields': [{'id': '$invalid$', 'label': 'Invalid', 'type': 'string'}]}, False), # noqa + ({'fields': [{'id': 'password', 'label': 'Password', 'type': 'invalid-type'}]}, False), ({'fields': [{'id': 'ssh_key', 'label': 'SSH Key', 'type': 'string', 'format': 'ssh_private_key'}]}, True), # noqa - ({'fields': [{'id': 'other', 'label': 'Other', 'type': 'boolean'}]}, False), + ({'fields': [{'id': 'flag', 'label': 'Some Flag', 'type': 'boolean'}]}, True), + ({'fields': [{'id': 'flag', 'label': 'Some Flag', 'type': 'boolean', 'choices': ['a', 'b']}]}, False), ({'fields': [{'id': 'certificate', 'label': 'Cert', 'multiline': True}]}, True), + ({'fields': [{'id': 'certificate', 'label': 'Cert', 'multiline': True, 'type': 'boolean'}]}, False), # noqa ({'fields': [{'id': 'certificate', 'label': 'Cert', 'multiline': 'bad'}]}, False), # noqa ({'fields': [{'id': 'token', 'label': 'Token', 'secret': True}]}, True), ({'fields': [{'id': 'token', 'label': 'Token', 'secret': 'bad'}]}, False), diff --git a/docs/custom_credential_types.md b/docs/custom_credential_types.md index f6d0ea099f..ef311d473a 100644 --- a/docs/custom_credential_types.md +++ b/docs/custom_credential_types.md @@ -118,40 +118,40 @@ ordered fields for that type: "inputs": { "fields": [{ - "id": "api_token", # required - a unique name used to - # reference the field value + "id": "api_token", # required - a unique name used to + # reference the field value - "label": "API Token", # required - a unique label for the - # field + "label": "API Token", # required - a unique label for the + # field "help_text": "User-facing short text describing the field.", - "type": ("string" | "number") # required, + "type": ("string" | "boolean") # defaults to 'string' - "format": "ssh_private_key" # optional, can be used to enforce data - # format validity for SSH private keys - # data + "format": "ssh_private_key" # optional, can be used to enforce data + # format validity for SSH private key + # data (only applicable to `type=string`) - "secret": true, # if true, the field will be treated - # as sensitive and stored encrypted + "secret": true, # if true, the field value will be encrypted - "multiline": false # if true, the field should be rendered - # as multi-line for input entry + "multiline": false # if true, the field should be rendered + # as multi-line for input entry + # (only applicable to `type=string`) },{ # field 2... },{ # field 3... }] - "required": ["api_token"] # optional; one or more fields can be marked as required + "required": ["api_token"] # optional; one or more fields can be marked as required }, -As an alternative to static types, fields can also specify multiple choice -strings: +When `type=string`, fields can optionally specify multiple choice options: "inputs": { "fields": [{ "id": "api_token", # required - a unique name used to reference the field value "label": "API Token", # required - a unique label for the field + "type": "string", "choices": ["A", "B", "C"] }] },