Adds managed_by_policy checkbox to instances form. Adds warnings when associating or disassociating instances from instance groups. (#13994)

This commit is contained in:
Michael Abashian 2023-05-31 12:31:55 -04:00 committed by GitHub
parent bdfd6f47ff
commit d89cad0d9e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 87 additions and 4 deletions

View File

@ -27,6 +27,7 @@ function AssociateModal({
isModalOpen = false,
displayKey = 'name',
ouiaId,
modalNote,
}) {
const history = useHistory();
const { selected, handleSelect } = useSelected([]);
@ -120,6 +121,7 @@ function AssociateModal({
</Button>,
]}
>
{modalNote}
<OptionsList
displayKey={displayKey}
contentError={contentError}

View File

@ -1,5 +1,13 @@
import React, { useState, useEffect, useContext } from 'react';
import { arrayOf, func, shape, string, oneOfType, number } from 'prop-types';
import {
arrayOf,
func,
shape,
string,
oneOfType,
number,
node,
} from 'prop-types';
import { t } from '@lingui/macro';
import { Button, Tooltip, DropdownItem } from '@patternfly/react-core';
@ -180,7 +188,7 @@ DisassociateButton.propTypes = {
})
),
]),
modalNote: string,
modalNote: node,
modalTitle: string,
onDisassociate: func.isRequired,
};

View File

@ -1,7 +1,7 @@
import React, { useCallback, useEffect, useState } from 'react';
import { useParams, useHistory } from 'react-router-dom';
import { t, Plural } from '@lingui/macro';
import { t, Trans, Plural } from '@lingui/macro';
import {
Button,
Progress,
@ -71,6 +71,10 @@ function InstanceDetails({ setBreadcrumb, instanceGroup }) {
const [showHealthCheckAlert, setShowHealthCheckAlert] = useState(false);
const [forks, setForks] = useState();
const policyRulesDocsLink = `${getDocsBaseUrl(
config
)}/html/administration/containers_instance_groups.html#ag-instance-group-policies`;
const {
isLoading,
error: contentError,
@ -319,6 +323,23 @@ function InstanceDetails({ setBreadcrumb, instanceGroup }) {
itemsToDisassociate={[instance]}
isProtectedInstanceGroup={instanceGroup.name === 'controlplane'}
modalTitle={t`Disassociate instance from instance group?`}
modalNote={
instance.managed_by_policy ? (
<Trans>
<b>
Note: This instance may be re-associated with this
instance group if it is managed by{' '}
<a
href={policyRulesDocsLink}
target="_blank"
rel="noopener noreferrer"
>
policy rules.
</a>
</b>
</Trans>
) : null
}
/>
)}
<InstanceToggle

View File

@ -1,5 +1,5 @@
import React, { useCallback, useEffect, useState } from 'react';
import { t } from '@lingui/macro';
import { t, Trans } from '@lingui/macro';
import { useLocation, useParams } from 'react-router-dom';
import 'styled-components/macro';
@ -22,6 +22,8 @@ import useRequest, {
import useSelected from 'hooks/useSelected';
import { InstanceGroupsAPI, InstancesAPI } from 'api';
import { getQSConfig, parseQueryString, mergeParams } from 'util/qs';
import getDocsBaseUrl from 'util/getDocsBaseUrl';
import { useConfig } from 'contexts/Config';
import HealthCheckButton from 'components/HealthCheckButton/HealthCheckButton';
import HealthCheckAlert from 'components/HealthCheckAlert';
import InstanceListItem from './InstanceListItem';
@ -33,6 +35,7 @@ const QS_CONFIG = getQSConfig('instance', {
});
function InstanceList({ instanceGroup }) {
const config = useConfig();
const [isModalOpen, setIsModalOpen] = useState(false);
const [showHealthCheckAlert, setShowHealthCheckAlert] = useState(false);
const [pendingHealthCheck, setPendingHealthCheck] = useState(false);
@ -40,6 +43,10 @@ function InstanceList({ instanceGroup }) {
const location = useLocation();
const { id: instanceGroupId } = useParams();
const policyRulesDocsLink = `${getDocsBaseUrl(
config
)}/html/administration/containers_instance_groups.html#ag-instance-group-policies`;
const {
result: {
instances,
@ -262,6 +269,25 @@ function InstanceList({ instanceGroup }) {
itemsToDisassociate={selected}
modalTitle={t`Disassociate instance from instance group?`}
isProtectedInstanceGroup={instanceGroup.name === 'controlplane'}
modalNote={
selected.some(
(instance) => instance.managed_by_policy === true
) ? (
<Trans>
<b>
Note: Instances may be re-associated with this instance
group if they are managed by{' '}
<a
href={policyRulesDocsLink}
target="_blank"
rel="noopener noreferrer"
>
policy rules.
</a>
</b>
</Trans>
) : null
}
/>,
<HealthCheckButton
isDisabled={!canAdd || !canRunHealthCheck}
@ -321,6 +347,24 @@ function InstanceList({ instanceGroup }) {
{ key: 'hostname', name: t`Name` },
{ key: 'node_type', name: t`Node Type` },
]}
modalNote={
<b>
<Trans>
<b>
Note: Manually associated instances may be automatically
disassociated from an instance group if the instance is
managed by{' '}
<a
href={policyRulesDocsLink}
target="_blank"
rel="noopener noreferrer"
>
policy rules.
</a>
</b>
</Trans>
</b>
}
/>
)}
{error && (

View File

@ -58,6 +58,12 @@ function InstanceFormFields() {
label={t`Enable Instance`}
tooltip={t`Set the instance enabled or disabled. If disabled, jobs will not be assigned to this instance.`}
/>
<CheckboxField
id="managed-by-policy"
name="managed_by_policy"
label={t`Managed by Policy`}
tooltip={t`Controls whether or not this instance is managed by policy. If enabled, the instance will be available for automatic assignment to and unassignment from instance groups based on policy rules.`}
/>
</FormGroup>
</>
);
@ -79,6 +85,7 @@ function InstanceForm({
node_state: 'installed',
listener_port: 27199,
enabled: true,
managed_by_policy: true,
}}
onSubmit={(values) => {
handleSubmit(values);

View File

@ -89,6 +89,7 @@ describe('<InstanceForm />', () => {
expect(handleSubmit).toBeCalledWith({
description: 'This is a repeat song',
enabled: true,
managed_by_policy: true,
hostname: 'new Foo',
listener_port: 'This is a repeat song',
node_state: 'installed',