feat(automation-snippets): add new tfSnippet arg to component and tests (#16026) (#16027)

Co-authored-by: Nina Bucholtz <nina.balachandranmary@gmail.com>
This commit is contained in:
Vault Automation 2026-07-01 15:11:52 -04:00 committed by GitHub
parent 8df0f4b8de
commit 3f31ff60f3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 89 additions and 13 deletions

View file

@ -25,6 +25,7 @@ interface SnippetOption {
interface Args {
customTabs?: SnippetOption[];
tfSnippet?: string;
tfvpArgs?: TerraformResourceTemplateArgs;
cliArgs?: CliTemplateArgs;
apiArgs?: ApiTemplateArgs;
@ -40,23 +41,24 @@ export default class CodeGeneratorAutomationSnippets extends Component<Args> {
get snippetTabs() {
const tabs = [];
if (this.args.tfvpArgs) {
const { tfSnippet, tfvpArgs, cliArgs, apiArgs } = this.args;
if (tfSnippet !== undefined || tfvpArgs) {
tabs.push({
key: 'terraform',
label: 'Terraform Vault Provider',
snippet: terraformResourceTemplate(this.terraformOptions),
snippet: this.terraformSnippet,
language: 'hcl',
});
}
if (this.args.cliArgs) {
if (cliArgs) {
tabs.push({
key: 'cli',
label: 'CLI',
snippet: cliTemplate(this.args.cliArgs),
snippet: cliTemplate(cliArgs),
language: 'shell',
});
}
if (this.args.apiArgs) {
if (apiArgs) {
tabs.push({
key: 'api',
label: 'API',
@ -66,14 +68,25 @@ export default class CodeGeneratorAutomationSnippets extends Component<Args> {
return tabs;
}
get terraformOptions() {
const { tfvpArgs } = this.args || {};
// only add namespace if we're not in root (when namespace is '')
if (tfvpArgs && !this.namespace.inRootNamespace) {
const { resourceArgs } = tfvpArgs;
return { ...tfvpArgs, resourceArgs: { namespace: `"${this.namespace.path}"`, ...resourceArgs } };
get terraformSnippet() {
const { tfSnippet, tfvpArgs } = this.args;
if (tfSnippet !== undefined) {
if (!this.namespace.inRootNamespace) {
const namespaceLine = ` namespace = "${this.namespace.path}"`;
return tfSnippet.replace(/^(resource "[^"]*" "[^"]*" \{)/, `$1\n${namespaceLine}`);
}
return tfSnippet;
}
return tfvpArgs;
// Legacy support for tfvpArgs - used in the event tfSnippet is not provided.
if (tfvpArgs && !this.namespace.inRootNamespace) {
// only add namespace if we're not in root (when namespace is '')
const { resourceArgs } = tfvpArgs;
return terraformResourceTemplate({
...tfvpArgs,
resourceArgs: { namespace: `"${this.namespace.path}"`, ...resourceArgs },
});
}
return terraformResourceTemplate(tfvpArgs);
}
get apiOptions() {

View file

@ -17,12 +17,14 @@ module('Integration | Component | code-generator/automation-snippets', function
this.tfvpArgs = undefined;
this.apiArgs = undefined;
this.customTabs = undefined;
this.tfSnippet = undefined;
this.renderComponent = () => {
return render(hbs`
<CodeGenerator::AutomationSnippets
@cliArgs={{this.cliArgs}}
@tfvpArgs={{this.tfvpArgs}}
@tfSnippet={{this.tfSnippet}}
@apiArgs={{this.apiArgs}}
@customTabs={{this.customTabs}}
/>`);
@ -66,6 +68,39 @@ module('Integration | Component | code-generator/automation-snippets', function
assert.dom(GENERAL.fieldByAttr('api')).hasText(expectedApi, 'it renders API snippet');
});
test('it renders snippets when tfSnippet is provided', async function (assert) {
this.tfSnippet =
'resource "vault_mount" "<local identifier>" {\n path = "my-mount"\n type = "kv-v2"\n}';
this.cliArgs = {
command: 'kv delete ',
content: '-mount=secret creds',
};
this.apiArgs = {
url: 'sys/mounts/{path}',
payload: { path: 'my-mount', type: 'kv-v2' },
};
await this.renderComponent();
const expectedTfSnippet = `resource "vault_mount" "<local identifier>" {
path = "my-mount"
type = "kv-v2"
}`;
const expectedCli = 'vault kv delete -mount=secret creds';
const expectedApi = `curl \\
--header "X-Vault-Token: $VAULT_TOKEN" \\
--request POST \\
--data '{"path":"my-mount","type":"kv-v2"}' \\
$VAULT_ADDR/v1/sys/mounts/my-mount
`;
assert.dom(GENERAL.hdsTab('terraform')).exists();
assert.dom(GENERAL.hdsTab('cli')).exists();
assert.dom(GENERAL.hdsTab('api')).exists();
assert.dom(GENERAL.fieldByAttr('terraform')).hasText(expectedTfSnippet);
assert.dom(GENERAL.fieldByAttr('cli')).hasText(expectedCli);
assert.dom(GENERAL.fieldByAttr('api')).hasText(expectedApi, 'it renders API snippet');
});
test('it selects tabs', async function (assert) {
this.tfvpArgs = { resource: 'vault_mount', resourceArgs: { path: '"my-mount"', type: '"kv-v2"' } };
this.cliArgs = {
@ -144,7 +179,7 @@ module('Integration | Component | code-generator/automation-snippets', function
assert.dom(GENERAL.fieldByAttr('api')).hasText(expectedSnippet, 'it renders API snippet with namespace');
});
test('it includes namespace in snippet for non-root namespaces', async function (assert) {
test('it includes namespace in snippet for non-root namespaces when tfvpArgs provided', async function (assert) {
this.tfvpArgs = { resource: 'vault_mount', resourceArgs: { path: '"my-mount"', type: '"kv-v2"' } };
const namespace = this.owner.lookup('service:namespace');
namespace.path = 'admin';
@ -159,6 +194,34 @@ module('Integration | Component | code-generator/automation-snippets', function
.hasText(expectedSnippet, 'it renders snippet with namespace');
});
test('it includes namespace in snippet for non-root namespaces when tfSnippet provided', async function (assert) {
this.tfSnippet =
'resource "vault_mount" "<local identifier>" {\n path = "my-mount"\n type = "kv-v2"\n}';
const namespace = this.owner.lookup('service:namespace');
namespace.path = 'admin';
await this.renderComponent();
const expectedSnippet = `resource "vault_mount" "<local identifier>" {
namespace = "admin"
path = "my-mount"
type = "kv-v2"
}`;
assert
.dom(GENERAL.fieldByAttr('terraform'))
.hasText(expectedSnippet, 'it renders snippet with namespace');
});
test('tfSnippet takes precedence over tfvpArgs when both are provided', async function (assert) {
this.tfSnippet = 'resource "vault_policy" "example" {\n name = "my-policy"\n}';
this.tfvpArgs = { resource: 'vault_mount', resourceArgs: { path: '"my-mount"' } };
await this.renderComponent();
assert
.dom(GENERAL.fieldByAttr('terraform'))
.hasText(
'resource "vault_policy" "example" { name = "my-policy" }',
'tfSnippet output is rendered, not tfvpArgs'
);
});
test('it renders custom tabs', async function (assert) {
this.customTabs = [
{