From 3f31ff60f34ee50faced2f85642511c3d8f5ca92 Mon Sep 17 00:00:00 2001 From: Vault Automation Date: Wed, 1 Jul 2026 15:11:52 -0400 Subject: [PATCH] feat(automation-snippets): add new tfSnippet arg to component and tests (#16026) (#16027) Co-authored-by: Nina Bucholtz --- .../code-generator/automation-snippets.ts | 37 +++++++---- .../automation-snippets-test.js | 65 ++++++++++++++++++- 2 files changed, 89 insertions(+), 13 deletions(-) diff --git a/ui/lib/core/addon/components/code-generator/automation-snippets.ts b/ui/lib/core/addon/components/code-generator/automation-snippets.ts index e48978801c..91a0689293 100644 --- a/ui/lib/core/addon/components/code-generator/automation-snippets.ts +++ b/ui/lib/core/addon/components/code-generator/automation-snippets.ts @@ -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 { 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 { 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() { diff --git a/ui/tests/integration/components/code-generator/automation-snippets-test.js b/ui/tests/integration/components/code-generator/automation-snippets-test.js index 0acd727520..f55303984d 100644 --- a/ui/tests/integration/components/code-generator/automation-snippets-test.js +++ b/ui/tests/integration/components/code-generator/automation-snippets-test.js @@ -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` `); @@ -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" "" {\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" "" { + 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" "" {\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" "" { + 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 = [ {