diff --git a/awx/ui_next/src/screens/Credential/shared/CredentialForm.jsx b/awx/ui_next/src/screens/Credential/shared/CredentialForm.jsx
index fa24a5ffd4..25ae4ac23a 100644
--- a/awx/ui_next/src/screens/Credential/shared/CredentialForm.jsx
+++ b/awx/ui_next/src/screens/Credential/shared/CredentialForm.jsx
@@ -244,7 +244,7 @@ function CredentialForm({
description: credential.description || '',
organization: credential?.summary_fields?.organization || null,
credential_type: credentialTypes[initialTypeId]?.name || '',
- inputs: credential?.inputs || {},
+ inputs: { ...credential?.inputs },
passwordPrompts: {},
isOrgLookupDisabled: isOrgLookupDisabled || false,
};
@@ -253,7 +253,7 @@ function CredentialForm({
const fields = credentialType.inputs.fields || [];
fields.forEach(
({ ask_at_runtime, type, id, choices, default: defaultValue }) => {
- if (credential?.inputs && credential.inputs[id]) {
+ if (credential?.inputs && id in credential.inputs) {
if (ask_at_runtime) {
initialValues.passwordPrompts[id] =
credential.inputs[id] === 'ASK' || false;
diff --git a/awx/ui_next/src/screens/Credential/shared/CredentialForm.test.jsx b/awx/ui_next/src/screens/Credential/shared/CredentialForm.test.jsx
index 0cd1780b5c..8d77e90b3d 100644
--- a/awx/ui_next/src/screens/Credential/shared/CredentialForm.test.jsx
+++ b/awx/ui_next/src/screens/Credential/shared/CredentialForm.test.jsx
@@ -5,6 +5,7 @@ import machineCredential from './data.machineCredential.json';
import gceCredential from './data.gceCredential.json';
import scmCredential from './data.scmCredential.json';
import galaxyCredential from './data.galaxyCredential.json';
+import towerCredential from './data.towerCredential.json';
import credentialTypesArr from './data.credentialTypes.json';
import CredentialForm from './CredentialForm';
@@ -378,7 +379,7 @@ describe('', () => {
gceFieldExpects();
});
- test('should display from fields for galaxy/automation hub credentials', async () => {
+ test('should display form fields for galaxy/automation hub credentials', async () => {
await act(async () => {
wrapper = mountWithContexts(
', () => {
).toBe(true);
expect(wrapper.find('FormGroup[label="Credential Type"]').length).toBe(1);
});
+
+ test('should display form fields for tower credentials', async () => {
+ await act(async () => {
+ wrapper = mountWithContexts(
+
+ );
+ });
+ expect(wrapper.find('FormGroup[label="Name"]').length).toBe(1);
+ expect(wrapper.find('FormGroup[label="Description"]').length).toBe(1);
+ expect(wrapper.find('FormGroup[label="Organization"]').length).toBe(1);
+ expect(
+ wrapper.find('FormGroup[label="Organization"]').prop('isRequired')
+ ).toBe(false);
+ expect(wrapper.find('FormGroup[label="Credential Type"]').length).toBe(1);
+ expect(
+ wrapper.find('FormGroup[label="Ansible Tower Hostname"]').length
+ ).toBe(1);
+ expect(wrapper.find('FormGroup[label="Username"]').length).toBe(1);
+ expect(wrapper.find('FormGroup[label="Password"]').length).toBe(1);
+ expect(wrapper.find('FormGroup[label="OAuth Token"]').length).toBe(1);
+ expect(
+ wrapper.find('Checkbox#credential-verify_ssl').prop('isChecked')
+ ).toBe(false);
+ });
});
});
diff --git a/awx/ui_next/src/screens/Credential/shared/data.credentialTypes.json b/awx/ui_next/src/screens/Credential/shared/data.credentialTypes.json
index d3e048dbd7..2fbc4f90a9 100644
--- a/awx/ui_next/src/screens/Credential/shared/data.credentialTypes.json
+++ b/awx/ui_next/src/screens/Credential/shared/data.credentialTypes.json
@@ -85,6 +85,13 @@
"type": "string",
"secret": true
},
+ {
+ "id": "oauth_token",
+ "label": "OAuth Token",
+ "type": "string",
+ "secret": true,
+ "help_text": "An OAuth token to use to authenticate to Tower with.This should not be set if username/password are being used."
+ },
{
"id": "verify_ssl",
"label": "Verify SSL",
@@ -1280,14 +1287,14 @@
"type": "credential_type",
"url": "/api/v2/credential_types/42/",
"related": {
- "credentials": "/api/v2/credential_types/42/credentials/",
- "activity_stream": "/api/v2/credential_types/42/activity_stream/"
+ "credentials": "/api/v2/credential_types/42/credentials/",
+ "activity_stream": "/api/v2/credential_types/42/activity_stream/"
},
"summary_fields": {
- "user_capabilities": {
- "edit": true,
- "delete": true
- }
+ "user_capabilities": {
+ "edit": true,
+ "delete": true
+ }
},
"created": "2020-11-11T00:18:31.928286Z",
"modified": "2020-11-11T00:19:00.851597Z",
@@ -1297,31 +1304,29 @@
"namespace": "galaxy_api_token",
"managed_by_tower": true,
"inputs": {
- "fields": [
- {
- "id": "url",
- "label": "Galaxy Server URL",
- "type": "string",
- "help_text": "The URL of the Galaxy instance to connect to."
- },
- {
- "id": "auth_url",
- "label": "Auth Server URL",
- "type": "string",
- "help_text": "The URL of a Keycloak server token_endpoint, if using SSO auth."
- },
- {
- "id": "token",
- "label": "API Token",
- "type": "string",
- "secret": true,
- "help_text": "A token to use for authentication against the Galaxy instance."
- }
- ],
- "required": [
- "url"
- ]
+ "fields": [
+ {
+ "id": "url",
+ "label": "Galaxy Server URL",
+ "type": "string",
+ "help_text": "The URL of the Galaxy instance to connect to."
+ },
+ {
+ "id": "auth_url",
+ "label": "Auth Server URL",
+ "type": "string",
+ "help_text": "The URL of a Keycloak server token_endpoint, if using SSO auth."
+ },
+ {
+ "id": "token",
+ "label": "API Token",
+ "type": "string",
+ "secret": true,
+ "help_text": "A token to use for authentication against the Galaxy instance."
+ }
+ ],
+ "required": ["url"]
},
"injectors": {}
-}
+ }
]
diff --git a/awx/ui_next/src/screens/Credential/shared/data.towerCredential.json b/awx/ui_next/src/screens/Credential/shared/data.towerCredential.json
new file mode 100644
index 0000000000..bfa544a5ed
--- /dev/null
+++ b/awx/ui_next/src/screens/Credential/shared/data.towerCredential.json
@@ -0,0 +1,85 @@
+{
+ "id": 4,
+ "type": "credential",
+ "url": "/api/v2/credentials/4/",
+ "related": {
+ "named_url": "/api/v2/credentials/Tower cred++Ansible Tower+cloud++/",
+ "created_by": "/api/v2/users/2/",
+ "modified_by": "/api/v2/users/2/",
+ "activity_stream": "/api/v2/credentials/4/activity_stream/",
+ "access_list": "/api/v2/credentials/4/access_list/",
+ "object_roles": "/api/v2/credentials/4/object_roles/",
+ "owner_users": "/api/v2/credentials/4/owner_users/",
+ "owner_teams": "/api/v2/credentials/4/owner_teams/",
+ "copy": "/api/v2/credentials/4/copy/",
+ "input_sources": "/api/v2/credentials/4/input_sources/",
+ "credential_type": "/api/v2/credential_types/15/",
+ "user": "/api/v2/users/2/"
+ },
+ "summary_fields": {
+ "credential_type": {
+ "id": 16,
+ "name": "Ansible Tower",
+ "description": ""
+ },
+ "created_by": {
+ "id": 2,
+ "username": "test",
+ "first_name": "",
+ "last_name": ""
+ },
+ "modified_by": {
+ "id": 2,
+ "username": "test",
+ "first_name": "",
+ "last_name": ""
+ },
+ "object_roles": {
+ "admin_role": {
+ "description": "Can manage all aspects of the credential",
+ "name": "Admin",
+ "id": 37
+ },
+ "use_role": {
+ "description": "Can use the credential in a job template",
+ "name": "Use",
+ "id": 38
+ },
+ "read_role": {
+ "description": "May view settings for the credential",
+ "name": "Read",
+ "id": 39
+ }
+ },
+ "user_capabilities": {
+ "edit": true,
+ "delete": true,
+ "copy": true,
+ "use": true
+ },
+ "owners": [
+ {
+ "id": 2,
+ "type": "user",
+ "name": "test",
+ "description": " ",
+ "url": "/api/v2/users/2/"
+ }
+ ]
+ },
+ "created": "2021-04-20T14:05:16.538312Z",
+ "modified": "2021-04-20T14:05:26.177919Z",
+ "name": "Tower cred",
+ "description": "",
+ "organization": null,
+ "credential_type": 16,
+ "managed_by_tower": false,
+ "inputs": {
+ "host": "https://localhost",
+ "username": "",
+ "verify_ssl": false
+ },
+ "kind": "tower",
+ "cloud": true,
+ "kubernetes": false
+}