-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support arbitrary role resource version in the editor #51160
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -16,14 +16,16 @@ | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||
*/ | ||||
|
||||
import Box from 'design/Box'; | ||||
import Text from 'design/Text'; | ||||
import FieldInput from 'shared/components/FieldInput'; | ||||
import { FieldSelect } from 'shared/components/FieldSelect'; | ||||
import { precomputed } from 'shared/components/Validation/rules'; | ||||
|
||||
import { LabelsInput } from 'teleport/components/LabelsInput'; | ||||
|
||||
import { SectionBox, SectionProps } from './sections'; | ||||
import { MetadataModel } from './standardmodel'; | ||||
import { MetadataModel, roleVersionOptions } from './standardmodel'; | ||||
import { MetadataValidationResult } from './validation'; | ||||
|
||||
export const MetadataSection = ({ | ||||
|
@@ -55,14 +57,25 @@ export const MetadataSection = ({ | |||
onChange({ ...value, description: e.target.value }) | ||||
} | ||||
/> | ||||
<Text typography="body3" mb={1}> | ||||
Labels | ||||
</Text> | ||||
<LabelsInput | ||||
disableBtns={isProcessing} | ||||
labels={value.labels} | ||||
setLabels={labels => onChange?.({ ...value, labels })} | ||||
rule={precomputed(validation.fields.labels)} | ||||
<Box mb={3}> | ||||
<Text typography="body3" mb={1}> | ||||
Labels | ||||
</Text> | ||||
<LabelsInput | ||||
disableBtns={isProcessing} | ||||
labels={value.labels} | ||||
setLabels={labels => onChange?.({ ...value, labels })} | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||
rule={precomputed(validation.fields.labels)} | ||||
/> | ||||
</Box> | ||||
<FieldSelect | ||||
label="Version" | ||||
isDisabled={isProcessing} | ||||
options={roleVersionOptions} | ||||
value={value.version} | ||||
onChange={version => onChange({ ...value, version })} | ||||
// rule={precomputed(validation.fields.verbs)} | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
dead code There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove comment |
||||
mb={0} | ||||
/> | ||||
</SectionBox> | ||||
); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,7 +28,8 @@ import { Mark } from 'design/Mark'; | |
import Text, { H4 } from 'design/Text'; | ||
import FieldInput from 'shared/components/FieldInput'; | ||
import { FieldMultiInput } from 'shared/components/FieldMultiInput/FieldMultiInput'; | ||
import FieldSelect, { | ||
import { | ||
FieldSelect, | ||
FieldSelectCreatable, | ||
} from 'shared/components/FieldSelect'; | ||
import { MenuButton, MenuItem } from 'shared/components/MenuAction'; | ||
|
@@ -321,7 +322,10 @@ export function KubernetesAccessSection({ | |
onClick={() => | ||
onChange?.({ | ||
...value, | ||
resources: [...value.resources, newKubernetesResourceModel()], | ||
resources: [ | ||
...value.resources, | ||
newKubernetesResourceModel(value.roleVersion), | ||
], | ||
}) | ||
} | ||
> | ||
|
@@ -351,6 +355,7 @@ function KubernetesResourceView({ | |
}) { | ||
const { kind, name, namespace, verbs } = value; | ||
const theme = useTheme(); | ||
console.log('ROLE VERSION', value.roleVersion); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove console |
||
return ( | ||
<Box | ||
border={1} | ||
|
@@ -378,6 +383,7 @@ function KubernetesResourceView({ | |
isDisabled={isProcessing} | ||
options={kubernetesResourceKindOptions} | ||
value={kind} | ||
rule={precomputed(validation.kind)} | ||
onChange={k => onChange?.({ ...value, kind: k })} | ||
/> | ||
<FieldInput | ||
|
@@ -412,6 +418,7 @@ function KubernetesResourceView({ | |
isDisabled={isProcessing} | ||
options={kubernetesVerbOptions} | ||
value={verbs} | ||
rule={precomputed(validation.verbs)} | ||
onChange={v => onChange?.({ ...value, verbs: v })} | ||
mb={0} | ||
/> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -138,8 +138,10 @@ test('edits metadata', async () => { | |
const onSave = (r: Role) => (role = r); | ||
render(<TestStandardEditor onSave={onSave} />); | ||
await user.type(screen.getByLabelText('Description'), 'foo'); | ||
await selectEvent.select(screen.getByLabelText('Version'), 'v6'); | ||
await user.click(screen.getByRole('button', { name: 'Create Role' })); | ||
expect(role.metadata.description).toBe('foo'); | ||
expect(role.version).toBe('v6'); | ||
}); | ||
|
||
test('edits resource access', async () => { | ||
|
@@ -159,6 +161,24 @@ test('edits resource access', async () => { | |
expect(role.spec.allow.logins).toEqual(['{{internal.logins}}', 'ec2-user']); | ||
}); | ||
|
||
test('propagates version info to Kubernetes resource access', async () => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe rename this test to "triggers v6 validation for kubernetes resource." I initially got confused otherwise since the test only says propagates version info but we are interested in validation triggered at the end. |
||
const user = userEvent.setup(); | ||
const onSave = jest.fn(); | ||
render(<TestStandardEditor onSave={onSave} />); | ||
await selectEvent.select(screen.getByLabelText('Version'), 'v6'); | ||
await user.click(screen.getByRole('tab', { name: 'Resources' })); | ||
await user.click( | ||
screen.getByRole('button', { name: 'Add New Resource Access' }) | ||
); | ||
await user.click(screen.getByRole('menuitem', { name: 'Kubernetes' })); | ||
await user.click(screen.getByRole('button', { name: 'Add a Resource' })); | ||
await selectEvent.select(screen.getByLabelText('Kind'), 'Job'); | ||
await user.click(screen.getByRole('button', { name: 'Create Role' })); | ||
|
||
// Validation should have failed on a Job resource and role v6. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we assert that some validation error message appears on the screen? |
||
expect(onSave).not.toHaveBeenCalled(); | ||
}); | ||
|
||
const getAllMenuItemNames = () => | ||
screen.queryAllByRole('menuitem').map(m => m.textContent); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the PR description, can you also explain a bit more on why we chose "immer" over other alternatives please?
That information will be valuable for anyone looking for origin of immer as dependency.