From e020b07f816530ae333ce89e09ed807b1e77c5cb Mon Sep 17 00:00:00 2001 From: Andrzej Ressel Date: Sun, 1 Sep 2024 16:32:55 +0200 Subject: [PATCH] Handle code blocks in import section --- pkg/tfgen/docs.go | 127 ++++++++++++------ pkg/tfgen/docs_test.go | 7 +- .../convertExamples/docker_container.md | 38 ++++++ .../docker_container-expected.md | 39 ++++++ .../parse-imports/docker_container.md | 38 ++++++ 5 files changed, 204 insertions(+), 45 deletions(-) create mode 100644 pkg/tfgen/test_data/convertExamples/docker_container.md create mode 100644 pkg/tfgen/test_data/parse-imports/docker_container-expected.md create mode 100644 pkg/tfgen/test_data/parse-imports/docker_container.md diff --git a/pkg/tfgen/docs.go b/pkg/tfgen/docs.go index e4e4e9edf..6ac96c851 100644 --- a/pkg/tfgen/docs.go +++ b/pkg/tfgen/docs.go @@ -1166,6 +1166,42 @@ func flattenListAttributeKey(attribute string) string { return strings.ReplaceAll(attribute, ".0", "") } +func parseImportShellLine(section, token string) string { + if strings.Contains(section, "terraform import") { + // First, remove the `$` + section := strings.Replace(section, "$ ", "", -1) + // Next, remove `terraform import` from the codeblock + section = strings.Replace(section, "terraform import ", "", -1) + importString := "" + parts := strings.Split(section, " ") + for i, p := range parts { + switch i { + case 0: + if !isBlank(p) { + // split the string on . and take the last item + // this gets the identifier broken from the tf resource + ids := strings.Split(p, ".") + name := ids[len(ids)-1] + importString = fmt.Sprintf("%s %s", importString, name) + } + default: + if !isBlank(p) { + importString = fmt.Sprintf("%s %s", importString, p) + } + } + } + var tok string + if token != "" { + tok = token + } else { + tok = "MISSING_TOK" + } + importCommand := fmt.Sprintf("$ pulumi import %s%s", tok, importString) + return importCommand + } + return section +} + func (p *tfMarkdownParser) parseImports(subsection []string) { var token string if p.info != nil && p.info.GetTok() != "" { @@ -1206,65 +1242,68 @@ func (p *tfMarkdownParser) parseImports(subsection []string) { } var importDocString string - for _, section := range subsection { + var i = 0 + + for i < len(subsection) { + section := subsection[i] + trimmedSection := strings.TrimSpace(section) if strings.Contains(section, "**NOTE:") || strings.Contains(section, "**Please Note:") || strings.Contains(section, "**Note:**") { // This is a Terraform import specific comment that we don't need to parse or include in our docs + i++ continue } // Skip another redundant comment if strings.Contains(section, "Import is supported using the following syntax") { + i++ continue } - // Remove the shell comment characters to avoid writing this line as a Markdown H1: - section = strings.TrimPrefix(section, "# ") - - // There are multiple variations of codeblocks for import syntax - section = strings.Replace(section, "```shell", "", -1) - section = strings.Replace(section, "```sh", "", -1) - section = strings.Replace(section, "```", "", -1) - - if strings.Contains(section, "terraform import") { - // First, remove the `$` - section := strings.Replace(section, "$ ", "", -1) - // Next, remove `terraform import` from the codeblock - section = strings.Replace(section, "terraform import ", "", -1) - importString := "" - parts := strings.Split(section, " ") - for i, p := range parts { - switch i { - case 0: - if !isBlank(p) { - // split the string on . and take the last item - // this gets the identifier broken from the tf resource - ids := strings.Split(p, ".") - name := ids[len(ids)-1] - importString = fmt.Sprintf("%s %s", importString, name) - } - default: - if !isBlank(p) { - importString = fmt.Sprintf("%s %s", importString, p) - } + // Handle terraform blocks - pass them whole without changes + if trimmedSection == "```terraform" || trimmedSection == "```hcl" { + for { + section = subsection[i] + trimmedSection := strings.TrimSpace(section) + importDocString = importDocString + section + "\n" + i++ + if trimmedSection == "```" { + break } } - var tok string - if token != "" { - tok = token - } else { - tok = "MISSING_TOK" - } - importCommand := fmt.Sprintf("$ pulumi import %s%s\n", tok, importString) - importDetails := "```sh\n" + importCommand + "```\n\n" - importDocString = importDocString + importDetails - } else { - if !isBlank(section) { - // Ensure every section receives a line break. - section = section + "\n\n" - importDocString = importDocString + section + importDocString = importDocString + "\n" + continue + } + + // Handle script blocks - replace terraform import with pulumi import + if trimmedSection == "```" || trimmedSection == "```sh" || trimmedSection == "```shell" { + initial := true + for { + section = subsection[i] + trimmedSection := strings.TrimSpace(section) + if initial { + // ``` and ```shell are removed when converting to programming language comment + importDocString = importDocString + "```sh" + "\n" + } else { + importDocString = importDocString + parseImportShellLine(section, token) + "\n" + } + i++ + if trimmedSection == "```" && !initial { + break + } + initial = false } + importDocString = importDocString + "\n" + continue } + + if !isBlank(section) { + // Ensure every section receives a line break. + section = section + "\n\n" + importDocString = importDocString + section + } + + i++ } if len(importDocString) > 0 { diff --git a/pkg/tfgen/docs_test.go b/pkg/tfgen/docs_test.go index 720e33e40..08e083a9e 100644 --- a/pkg/tfgen/docs_test.go +++ b/pkg/tfgen/docs_test.go @@ -1785,7 +1785,7 @@ func TestParseImports_NoOverrides(t *testing.T) { "", }, token: "snowflake:index/accountGrant:AccountGrant", - expected: "## Import\n\nformat is account name | | | privilege | true/false for with_grant_option\n\n```sh\n$ pulumi import snowflake:index/accountGrant:AccountGrant example 'accountName|||USAGE|true'\n```\n\n", + expected: "## Import\n\n```sh\n# format is account name | | | privilege | true/false for with_grant_option\n$ pulumi import snowflake:index/accountGrant:AccountGrant example 'accountName|||USAGE|true'\n```\n\n", }, { input: []string{ @@ -1830,6 +1830,11 @@ func TestParseImports_NoOverrides(t *testing.T) { token: "aws:lambda/layerVersion:LayerVersion", expectedFile: "test_data/parse-imports/lambdalayer-expected.md", }, + { + input: readlines(t, "test_data/parse-imports/docker_container.md"), + token: "docker:index/container:Container", + expectedFile: "test_data/parse-imports/docker_container-expected.md", + }, } for _, tt := range tests { diff --git a/pkg/tfgen/test_data/convertExamples/docker_container.md b/pkg/tfgen/test_data/convertExamples/docker_container.md new file mode 100644 index 000000000..9f1109005 --- /dev/null +++ b/pkg/tfgen/test_data/convertExamples/docker_container.md @@ -0,0 +1,38 @@ +Import is supported using the following syntax by providing the `id`: + +```shell +#!/bin/bash +terraform import docker_container.foo id +``` + +### Example + +Assuming you created a `container` as follows + +```shell +#!/bin/bash +docker run --name foo -p8080:80 -d nginx +# prints the container ID +9a550c0f0163d39d77222d3efd58701b625d47676c25c686c95b5b92d1cba6fd +``` + +you provide the definition for the resource as follows + +```terraform +resource "docker_container" "foo" { + name = "foo" + image = "nginx" + + ports { + internal = "80" + external = "8080" + } +} +``` + +then the import command is as follows + +```shell +#!/bin/bash +terraform import docker_container.foo 9a550c0f0163d39d77222d3efd58701b625d47676c25c686c95b5b92d1cba6fd +``` \ No newline at end of file diff --git a/pkg/tfgen/test_data/parse-imports/docker_container-expected.md b/pkg/tfgen/test_data/parse-imports/docker_container-expected.md new file mode 100644 index 000000000..4b98313aa --- /dev/null +++ b/pkg/tfgen/test_data/parse-imports/docker_container-expected.md @@ -0,0 +1,39 @@ +## Import + +```sh +#!/bin/bash +$ pulumi import docker:index/container:Container foo id +``` + +### Example + +Assuming you created a `container` as follows + +```sh +#!/bin/bash +docker run --name foo -p8080:80 -d nginx +# prints the container ID +9a550c0f0163d39d77222d3efd58701b625d47676c25c686c95b5b92d1cba6fd +``` + +you provide the definition for the resource as follows + +```terraform +resource "docker_container" "foo" { + name = "foo" + image = "nginx" + + ports { + internal = "80" + external = "8080" + } +} +``` + +then the import command is as follows + +```sh +#!/bin/bash +$ pulumi import docker:index/container:Container foo 9a550c0f0163d39d77222d3efd58701b625d47676c25c686c95b5b92d1cba6fd +``` + diff --git a/pkg/tfgen/test_data/parse-imports/docker_container.md b/pkg/tfgen/test_data/parse-imports/docker_container.md new file mode 100644 index 000000000..9f1109005 --- /dev/null +++ b/pkg/tfgen/test_data/parse-imports/docker_container.md @@ -0,0 +1,38 @@ +Import is supported using the following syntax by providing the `id`: + +```shell +#!/bin/bash +terraform import docker_container.foo id +``` + +### Example + +Assuming you created a `container` as follows + +```shell +#!/bin/bash +docker run --name foo -p8080:80 -d nginx +# prints the container ID +9a550c0f0163d39d77222d3efd58701b625d47676c25c686c95b5b92d1cba6fd +``` + +you provide the definition for the resource as follows + +```terraform +resource "docker_container" "foo" { + name = "foo" + image = "nginx" + + ports { + internal = "80" + external = "8080" + } +} +``` + +then the import command is as follows + +```shell +#!/bin/bash +terraform import docker_container.foo 9a550c0f0163d39d77222d3efd58701b625d47676c25c686c95b5b92d1cba6fd +``` \ No newline at end of file