From f792fea048c26678491b81a2e50cfec2919ddfce Mon Sep 17 00:00:00 2001 From: Marliana Lara Date: Mon, 27 Mar 2023 15:01:35 -0400 Subject: [PATCH] Add more constructed inventory hint examples --- .../shared/ConstructedInventoryHint.js | 317 ++++++++++++++---- .../shared/ConstructedInventoryHint.test.js | 18 +- 2 files changed, 268 insertions(+), 67 deletions(-) diff --git a/awx/ui/src/screens/Inventory/shared/ConstructedInventoryHint.js b/awx/ui/src/screens/Inventory/shared/ConstructedInventoryHint.js index 34a3ca48f1..be22d4ba13 100644 --- a/awx/ui/src/screens/Inventory/shared/ConstructedInventoryHint.js +++ b/awx/ui/src/screens/Inventory/shared/ConstructedInventoryHint.js @@ -3,10 +3,17 @@ import { t } from '@lingui/macro'; import { Alert, AlertActionLink, + ClipboardCopyButton, CodeBlock, CodeBlockAction, CodeBlockCode, - ClipboardCopyButton, + ClipboardCopy, + Form, + FormFieldGroupExpandable, + FormFieldGroupHeader, + FormGroup, + Panel, + CardBody, } from '@patternfly/react-core'; import { TableComposable, @@ -22,25 +29,6 @@ import { useConfig } from 'contexts/Config'; function ConstructedInventoryHint() { const config = useConfig(); - const [copied, setCopied] = React.useState(false); - - const clipboardCopyFunc = (event, text) => { - navigator.clipboard.writeText(text.toString()); - }; - - const onClick = (event, text) => { - clipboardCopyFunc(event, text); - setCopied(true); - }; - - const pluginSample = `plugin: constructed -strict: true -use_vars_plugins: true -groups: - shutdown: resolved_state == "shutdown" - shutdown_in_product_dev: resolved_state == "shutdown" and account_alias == "product_dev" -compose: - resolved_state: state | default("running")`; return ( - {t`View constructed plugin documentation here`}{' '} + {t`View constructed inventory documentation here`}{' '} } > - {t`WIP - More to come...`} + + {t`This table gives a few useful parameters of the constructed + inventory plugin. For the full list of parameters `}{' '} + {t`view the constructed inventory plugin docs here.`} +

{t`required`}

- {t`Token that ensures this is a source file + {t`Token that ensures this is a source file for the ‘constructed’ plugin.`} @@ -95,23 +89,11 @@ compose: {t`If yes make invalid entries a fatal error, otherwise skip and continue.`}{' '}
- {t`If users need feedback about the correctness - of their constructed groups, it is highly recommended + {t`If users need feedback about the correctness + of their constructed groups, it is highly recommended to use strict: true in the plugin configuration.`} - - - use_vars_plugins -

{t`string`}

- - - {t`Normally, for performance reasons, vars plugins get - executed after the inventory sources complete the - base inventory, this option allows for getting vars - related to hosts/groups from those plugins.`} - - groups @@ -127,38 +109,251 @@ compose:

{t`dictionary`}

- {t`Create vars from jinja2 expressions.`} + {t`Create vars from jinja2 expressions. This can be useful + if the constructed groups you define do not contain the expected + hosts. This can be used to add hostvars from expressions so + that you know what the resultant values of those expressions are.`}


- {t`Sample constructed inventory plugin:`} - - onClick(e, pluginSample)} - exitDelay={copied ? 1500 : 600} - maxWidth="110px" - variant="plain" - onTooltipHidden={() => setCopied(false)} - > - {copied - ? t`Successfully copied to clipboard!` - : t`Copy to clipboard`} - - - } - > - {pluginSample} - + + +
+ {t`Constructed inventory examples`} + + + + +
+
); } +function LimitToIntersectionExample() { + const [copied, setCopied] = React.useState(false); + const clipboardCopyFunc = (event, text) => { + navigator.clipboard.writeText(text.toString()); + }; + + const onClick = (event, text) => { + clipboardCopyFunc(event, text); + setCopied(true); + }; + + const limitToIntersectionLimit = `is_shutdown:&product_dev`; + const limitToIntersectionCode = `plugin: constructed +strict: true +groups: + shutdown_in_product_dev: state | default("running") == "shutdown" and account_alias == "product_dev"`; + + return ( + + } + > + + + {limitToIntersectionLimit} + + + + + onClick(e, limitToIntersectionCode)} + exitDelay={copied ? 1500 : 600} + maxWidth="110px" + variant="plain" + onTooltipHidden={() => setCopied(false)} + > + {copied + ? t`Successfully copied to clipboard!` + : t`Copy to clipboard`} + + + } + > + + {limitToIntersectionCode} + + + + + ); +} +function FilterOnNestedGroupExample() { + const [copied, setCopied] = React.useState(false); + const clipboardCopyFunc = (event, text) => { + navigator.clipboard.writeText(text.toString()); + }; + + const onClick = (event, text) => { + clipboardCopyFunc(event, text); + setCopied(true); + }; + + const nestedGroupsInventoryLimit = `groupA`; + const nestedGroupsInventorySourceVars = `plugin: constructed`; + const nestedGroupsInventory = `all: + children: + groupA: + children: + groupB: + hosts: + host1: {} + vars: + filter_var: filter_val + ungrouped: + hosts: + host2: {}`; + + return ( + + } + > + +

{t`Nested groups inventory definition:`}

+ + + {nestedGroupsInventory} + + +
+ + + {nestedGroupsInventoryLimit} + + + + + onClick(e, nestedGroupsInventorySourceVars)} + exitDelay={copied ? 1500 : 600} + maxWidth="110px" + variant="plain" + onTooltipHidden={() => setCopied(false)} + > + {copied + ? t`Successfully copied to clipboard!` + : t`Copy to clipboard`} + + + } + > + + {nestedGroupsInventorySourceVars} + + + +
+ ); +} +function HostsByProcessorTypeExample() { + const [copied, setCopied] = React.useState(false); + const clipboardCopyFunc = (event, text) => { + navigator.clipboard.writeText(text.toString()); + }; + + const onClick = (event, text) => { + clipboardCopyFunc(event, text); + setCopied(true); + }; + + const hostsByProcessorLimit = `intel_hosts`; + const hostsByProcessorSourceVars = `plugin: constructed + strict: true + groups: + intel_hosts: "GenuineIntel" in ansible_processor`; + + return ( + + } + > + + + {hostsByProcessorLimit} + + + + + onClick(e, hostsByProcessorSourceVars)} + exitDelay={copied ? 1500 : 600} + maxWidth="110px" + variant="plain" + onTooltipHidden={() => setCopied(false)} + > + {copied + ? t`Successfully copied to clipboard!` + : t`Copy to clipboard`} + + + } + > + + {hostsByProcessorSourceVars} + + + + + ); +} + export default ConstructedInventoryHint; diff --git a/awx/ui/src/screens/Inventory/shared/ConstructedInventoryHint.test.js b/awx/ui/src/screens/Inventory/shared/ConstructedInventoryHint.test.js index e4745773f4..6132f107a9 100644 --- a/awx/ui/src/screens/Inventory/shared/ConstructedInventoryHint.test.js +++ b/awx/ui/src/screens/Inventory/shared/ConstructedInventoryHint.test.js @@ -1,5 +1,5 @@ import React from 'react'; -import { render, screen, fireEvent } from '@testing-library/react'; +import { render, screen, fireEvent, within } from '@testing-library/react'; import '@testing-library/jest-dom'; import ConstructedInventoryHint from './ConstructedInventoryHint'; @@ -10,7 +10,7 @@ describe('', () => { render(); expect( screen.getByRole('link', { - name: 'View constructed plugin documentation here', + name: 'View constructed inventory documentation here', }) ).toBeInTheDocument(); }); @@ -33,14 +33,20 @@ describe('', () => { }); jest.spyOn(navigator.clipboard, 'writeText'); - const { container } = render(); + render(); fireEvent.click(screen.getByRole('button', { name: 'Info alert details' })); fireEvent.click( - container.querySelector('button[aria-label="Copy to clipboard"]') + screen.getByRole('button', { name: 'Hosts by processor type' }) + ); + fireEvent.click( + screen.getByRole('button', { + name: 'Copy to clipboard', + }) ); - expect(navigator.clipboard.writeText).toHaveBeenCalledWith( - expect.stringContaining('plugin: constructed') + expect.stringContaining( + 'intel_hosts: "GenuineIntel" in ansible_processor' + ) ); }); });