diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.tools.test.ts b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.tools.test.ts index 007f22a2a44b9..c816312b7cc7c 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.tools.test.ts +++ b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.tools.test.ts @@ -40,6 +40,7 @@ describe('Get instance data:: ', () => { region: 'us-west1', aws_access_key: 'aws-secret-key-example', aws_secret_key: 'aws-secret-key-example', + aws_role_arn: 'arn:aws:iam::123456789012:role/PmmRdsReadOnlyRole', az: 'test az', }; const testInstance = { @@ -54,6 +55,7 @@ describe('Get instance data:: ', () => { region: 'us-west1', aws_access_key: 'aws-secret-key-example', aws_secret_key: 'aws-secret-key-example', + aws_role_arn: 'arn:aws:iam::123456789012:role/PmmRdsReadOnlyRole', az: 'test az', }, }; diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.tools.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.tools.tsx index f6de78f53c841..db2e3390c7dcf 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.tools.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.tools.tsx @@ -65,6 +65,7 @@ const getRDSCredentials = (credentials: any, instanceType: InstanceAvailableType region: credentials.region, aws_access_key: credentials.aws_access_key, aws_secret_key: credentials.aws_secret_key, + aws_role_arn: credentials.aws_role_arn, instance_id: credentials.instance_id, az: credentials.az, }, diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.types.ts b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.types.ts index 22eaf34f87c4c..6471111497a7b 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.types.ts +++ b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.types.ts @@ -199,6 +199,7 @@ export interface RDSPayload extends CommonRDSAzurePayload { replication_set: string; aws_access_key: string; aws_secret_key: string; + aws_role_arn: string; rds_exporter: boolean; qan_mysql_perfschema: boolean; disable_parsing_comments: boolean; diff --git a/public/app/percona/add-instance/components/Discovery/Discovery.constants.ts b/public/app/percona/add-instance/components/Discovery/Discovery.constants.ts index 8839b67a4e2b9..ddfdab9e4c177 100644 --- a/public/app/percona/add-instance/components/Discovery/Discovery.constants.ts +++ b/public/app/percona/add-instance/components/Discovery/Discovery.constants.ts @@ -1,2 +1,2 @@ export const DISCOVERY_RDS_CANCEL_TOKEN = 'discoveryRds'; -export const INITIAL_CREDENTIALS = { aws_secret_key: '', aws_access_key: '' }; +export const INITIAL_CREDENTIALS = { aws_secret_key: '', aws_access_key: '', aws_role_arn: '' }; diff --git a/public/app/percona/add-instance/components/Discovery/Discovery.service.ts b/public/app/percona/add-instance/components/Discovery/Discovery.service.ts index 4c107bd419d0b..8e5a209bdce63 100644 --- a/public/app/percona/add-instance/components/Discovery/Discovery.service.ts +++ b/public/app/percona/add-instance/components/Discovery/Discovery.service.ts @@ -12,7 +12,7 @@ const { awsNoCredentialsError, noCredentialsError } = Messages; class DiscoveryService { static async discoveryRDS( - { aws_access_key, aws_secret_key }: RDSCredentialsForm, + { aws_access_key, aws_secret_key, aws_role_arn }: RDSCredentialsForm, token?: CancelToken, disableNotifications = false ) { @@ -22,6 +22,7 @@ class DiscoveryService { { aws_access_key, aws_secret_key, + aws_role_arn, }, true, token diff --git a/public/app/percona/add-instance/components/Discovery/components/Credentials/Credentials.messages.ts b/public/app/percona/add-instance/components/Discovery/components/Credentials/Credentials.messages.ts index ffc9f0ab02ede..4809bc02ff2d0 100644 --- a/public/app/percona/add-instance/components/Discovery/components/Credentials/Credentials.messages.ts +++ b/public/app/percona/add-instance/components/Discovery/components/Credentials/Credentials.messages.ts @@ -11,6 +11,12 @@ export const Messages = { name: 'aws_secret_key', label: 'Amazon RDS secret key', }, + awsRoleArn: { + placeholder: 'arn:aws:iam::123456789012:role/PmmRdsReadOnlyRole', + name: 'aws_role_arn', + label: 'AWS IAM role ARN', + tooltipText: 'Optional. PMM Server assumes this role before discovering RDS instances.', + }, }, submitButton: 'Discover', toMenuButton: 'Return to menu', diff --git a/public/app/percona/add-instance/components/Discovery/components/Credentials/Credentials.styles.ts b/public/app/percona/add-instance/components/Discovery/components/Credentials/Credentials.styles.ts index 3c521cb4b2f2f..9d55bad3a728d 100644 --- a/public/app/percona/add-instance/components/Discovery/components/Credentials/Credentials.styles.ts +++ b/public/app/percona/add-instance/components/Discovery/components/Credentials/Credentials.styles.ts @@ -16,6 +16,11 @@ export const getStyles = ({ breakpoints, spacing }: GrafanaTheme) => { width: 100%; `, fieldsWrapper: css` + display: flex; + flex-direction: column; + width: 100%; + `, + credentialsRow: css` display: flex; width: 100%; div { @@ -34,6 +39,9 @@ export const getStyles = ({ breakpoints, spacing }: GrafanaTheme) => { credentialsField: css` width: 48%; `, + roleArnField: css` + width: 100%; + `, credentialsSubmit: css` margin-left: ${spacing.md}; margin-right: ${spacing.sm}; diff --git a/public/app/percona/add-instance/components/Discovery/components/Credentials/Credentials.test.tsx b/public/app/percona/add-instance/components/Discovery/components/Credentials/Credentials.test.tsx index 41dc69f4b12f0..f76e651d72b35 100644 --- a/public/app/percona/add-instance/components/Discovery/components/Credentials/Credentials.test.tsx +++ b/public/app/percona/add-instance/components/Discovery/components/Credentials/Credentials.test.tsx @@ -3,11 +3,18 @@ import { render, screen, fireEvent } from '@testing-library/react'; import Credentials from './Credentials'; describe('Credentials:: ', () => { - it('should render access and secret keys fields', () => { + it('should render access key, secret key, and role ARN fields in order', () => { render(); - expect(screen.getByTestId('aws_access_key-text-input')).toBeInTheDocument(); - expect(screen.getByTestId('aws_secret_key-password-input')).toBeInTheDocument(); + const accessKeyInput = screen.getByTestId('aws_access_key-text-input'); + const secretKeyInput = screen.getByTestId('aws_secret_key-password-input'); + const roleArnInput = screen.getByTestId('aws_role_arn-text-input'); + + expect(accessKeyInput).toBeInTheDocument(); + expect(secretKeyInput).toBeInTheDocument(); + expect(roleArnInput).toBeInTheDocument(); + expect(accessKeyInput.compareDocumentPosition(secretKeyInput)).toBe(Node.DOCUMENT_POSITION_FOLLOWING); + expect(secretKeyInput.compareDocumentPosition(roleArnInput)).toBe(Node.DOCUMENT_POSITION_FOLLOWING); }); it('should call discover on submit', () => { @@ -15,8 +22,13 @@ describe('Credentials:: ', () => { render(); const form = screen.getByTestId('credentials-form'); + fireEvent.change(screen.getByTestId('aws_role_arn-text-input'), { + target: { value: 'arn:aws:iam::123456789012:role/PmmRdsReadOnlyRole' }, + }); fireEvent.submit(form); - expect(discover).toHaveBeenCalled(); + expect(discover).toHaveBeenCalledWith( + expect.objectContaining({ aws_role_arn: 'arn:aws:iam::123456789012:role/PmmRdsReadOnlyRole' }) + ); }); }); diff --git a/public/app/percona/add-instance/components/Discovery/components/Credentials/Credentials.tsx b/public/app/percona/add-instance/components/Discovery/components/Credentials/Credentials.tsx index 051365581800f..5c5fa3b41fcb3 100644 --- a/public/app/percona/add-instance/components/Discovery/components/Credentials/Credentials.tsx +++ b/public/app/percona/add-instance/components/Discovery/components/Credentials/Credentials.tsx @@ -15,7 +15,7 @@ const Credentials: FC = ({ discover }) => { const onSubmit = useCallback( (values: RDSCredentialsForm) => { - discover(values); + discover({ aws_access_key: '', aws_secret_key: '', aws_role_arn: '', ...values }); }, [discover] ); @@ -31,17 +31,26 @@ const Credentials: FC = ({ discover }) => { data-testid="credentials-form" >
+
+ + +
-
diff --git a/public/app/percona/add-instance/components/Discovery/components/Credentials/Credentials.types.ts b/public/app/percona/add-instance/components/Discovery/components/Credentials/Credentials.types.ts index aec06bc772d17..33c006c188d04 100644 --- a/public/app/percona/add-instance/components/Discovery/components/Credentials/Credentials.types.ts +++ b/public/app/percona/add-instance/components/Discovery/components/Credentials/Credentials.types.ts @@ -1,6 +1,7 @@ export interface RDSCredentialsForm { aws_access_key: string; aws_secret_key: string; + aws_role_arn: string; } export interface CredentialsProps { diff --git a/public/app/percona/add-instance/panel.types.ts b/public/app/percona/add-instance/panel.types.ts index f9799a6a6e841..558f500be1ae3 100644 --- a/public/app/percona/add-instance/panel.types.ts +++ b/public/app/percona/add-instance/panel.types.ts @@ -13,6 +13,7 @@ export interface RemoteInstanceCredentials { region?: string; aws_access_key?: string; aws_secret_key?: string; + aws_role_arn?: string; azure_client_id?: string; azure_client_secret?: string; azure_tenant_id?: string;