diff --git a/pkg/tfbridge/info/info.go b/pkg/tfbridge/info/info.go index aeb8689ab..2a4a450b2 100644 --- a/pkg/tfbridge/info/info.go +++ b/pkg/tfbridge/info/info.go @@ -233,6 +233,18 @@ type DocsPath struct { TfToken string } +type EditPhase int + +const ( + // PreCodeTranslation directs an info.DocsEdit to occur before resource example code is translated. + PreCodeTranslation EditPhase = iota + // PostCodeTranslation directs an info.DocsEdit to occur after resource example code is translated. + // It should be used when a docs edit would otherwise affect the code conversion mechanics. + //TODO[https://github.com/pulumi/pulumi-terraform-bridge/issues/2459]: Right now, PostCodeTranslation is only + // called on installation docs. + PostCodeTranslation +) + type DocsEdit struct { // The file name at which this rule applies. File names are matched via filepath.Match. // @@ -252,6 +264,10 @@ type DocsEdit struct { // // Must not be nil. Edit func(path string, content []byte) ([]byte, error) + // Phase determines when the edit rule will run. + // + // The default phase is [PreCodeTranslation]. + Phase EditPhase } // TFProviderLicense is a way to be able to pass a license type for the upstream Terraform provider. diff --git a/pkg/tfgen/docs.go b/pkg/tfgen/docs.go index e4e4e9edf..aa455a069 100644 --- a/pkg/tfgen/docs.go +++ b/pkg/tfgen/docs.go @@ -44,6 +44,7 @@ import ( "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tf2pulumi/convert" "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfbridge" + "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfbridge/info" "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfgen/parse" ) @@ -536,7 +537,7 @@ func (p *tfMarkdownParser) parse(tfMarkdown []byte) (entityDocs, error) { Attributes: make(map[string]string), } var err error - tfMarkdown, err = p.editRules.apply(p.markdownFileName, tfMarkdown) + tfMarkdown, err = p.editRules.apply(p.markdownFileName, tfMarkdown, info.PreCodeTranslation) if err != nil { return entityDocs{}, fmt.Errorf("file %s: %w", p.markdownFileName, err) } diff --git a/pkg/tfgen/edit_rules.go b/pkg/tfgen/edit_rules.go index dab54d3e9..e457676c6 100644 --- a/pkg/tfgen/edit_rules.go +++ b/pkg/tfgen/edit_rules.go @@ -21,6 +21,7 @@ import ( "regexp" "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfbridge" + "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfbridge/info" ) func defaultEditRules() editRules { @@ -29,24 +30,54 @@ func defaultEditRules() editRules { boundedReplace("[tT]erraform [pP]lan", "pulumi preview"), // Replace content such as " Terraform Apply." with " pulumi up." boundedReplace("[tT]erraform [aA]pply", "pulumi up"), - reReplace(`"([mM])ade (by|with) [tT]erraform"`, `"Made $2 Pulumi"`), + reReplace(`"([mM])ade (by|with) [tT]erraform"`, `"Made $2 Pulumi"`, info.PreCodeTranslation), // A markdown link that has terraform in the link component. - reReplace(`\[([^\]]*)\]\([^\)]*terraform([^\)]*)\)`, "$1"), + reReplace(`\[([^\]]*)\]\([^\)]*terraform([^\)]*)\)`, "$1", info.PreCodeTranslation), fixupImports(), // Replace content such as "jdoe@hashicorp.com" with "jdoe@example.com" - reReplace("@hashicorp.com", "@example.com"), + reReplace("@hashicorp.com", "@example.com", info.PreCodeTranslation), + + // The following edit rules may be applied after translating the code sections in a document. + // Their primary use case is for the docs translation approach spearheaded in installation_docs.go. + // These edit rules allow us to safely transform certain strings that we would otherwise need in the + // code translation or nested type discovery process. + // These rules are currently only called when generating installation docs. + //TODO[https://github.com/pulumi/pulumi-terraform-bridge/issues/2459] Call info.PostCodeTranslation rules + // on all docs. + skipSectionHeadersEdit(), + removeTfVersionMentions(), + //Replace "providers.tf" with "Pulumi.yaml" + reReplace(`providers.tf`, `Pulumi.yaml`, info.PostCodeTranslation), + reReplace(`terraform init`, `pulumi up`, info.PostCodeTranslation), + // Replace all " T/terraform" with " P/pulumi" + reReplace(`Terraform`, `Pulumi`, info.PostCodeTranslation), + reReplace(`terraform`, `pulumi`, info.PostCodeTranslation), + // Replace all "H/hashicorp" strings + reReplace(`Hashicorp`, `Pulumi`, info.PostCodeTranslation), + reReplace(`hashicorp`, `pulumi`, info.PostCodeTranslation), + // Reformat certain headers + reReplace(`The following arguments are supported`, + `The following configuration inputs are supported`, info.PostCodeTranslation), + reReplace(`Argument Reference`, + `Configuration Reference`, info.PostCodeTranslation), + reReplace(`Schema`, + `Configuration Reference`, info.PostCodeTranslation), + reReplace("### Optional\n", "", info.PostCodeTranslation), + reReplace(`block contains the following arguments`, + `input has the following nested fields`, info.PostCodeTranslation), + reReplace(`provider block`, `provider configuration`, info.PostCodeTranslation), } } type editRules []tfbridge.DocsEdit -func (rr editRules) apply(fileName string, contents []byte) ([]byte, error) { +func (rr editRules) apply(fileName string, contents []byte, phase info.EditPhase) ([]byte, error) { for _, rule := range rr { match, err := filepath.Match(rule.Path, fileName) if err != nil { return nil, fmt.Errorf("invalid glob: %q: %w", rule.Path, err) } - if !match { + if !match || (rule.Phase != phase) { continue } contents, err = rule.Edit(fileName, contents) @@ -84,7 +115,7 @@ func boundedReplace(from, to string) tfbridge.DocsEdit { } // reReplace creates a regex based replace. -func reReplace(from, to string) tfbridge.DocsEdit { +func reReplace(from, to string, phase info.EditPhase) tfbridge.DocsEdit { r := regexp.MustCompile(from) bTo := []byte(to) return tfbridge.DocsEdit{ @@ -92,6 +123,7 @@ func reReplace(from, to string) tfbridge.DocsEdit { Edit: func(_ string, content []byte) ([]byte, error) { return r.ReplaceAll(content, bTo), nil }, + Phase: phase, } } diff --git a/pkg/tfgen/edit_rules_test.go b/pkg/tfgen/edit_rules_test.go new file mode 100644 index 000000000..e37e6bf20 --- /dev/null +++ b/pkg/tfgen/edit_rules_test.go @@ -0,0 +1,245 @@ +package tfgen + +import ( + "bytes" + "runtime" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfbridge" + "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfbridge/info" +) + +func TestApplyEditRules(t *testing.T) { + t.Parallel() + + type testCase struct { + // The name of the test case. + name string + docFile DocFile + expected []byte + phase info.EditPhase + } + + tests := []testCase{ + { + name: "Replaces t/Terraform plan With pulumi preview", + docFile: DocFile{ + Content: []byte("Any mention of Terraform plan or terraform plan will be Pulumi preview or pulumi preview"), + }, + expected: []byte("Any mention of pulumi preview or pulumi preview will be Pulumi preview or pulumi preview"), + }, + { + name: "Strips Hashicorp links correctly", + docFile: DocFile{ + Content: []byte(readfile(t, "test_data/replace-links/input.md")), + }, + expected: []byte(readfile(t, "test_data/replace-links/expected.md")), + }, + { + name: "Strips Terraform links correctly", + docFile: DocFile{ + Content: []byte("This provider requires at least [Terraform 1.0](https://www.terraform.io/downloads.html)."), + }, + expected: []byte("This provider requires at least Terraform 1.0."), + }, + { + name: "Replaces h/Hashicorp With p/Pulumi", + docFile: DocFile{ + Content: []byte("Any mention of Hashicorp or hashicorp will be Pulumi or pulumi"), + }, + expected: []byte("Any mention of Pulumi or pulumi will be Pulumi or pulumi"), + phase: info.PostCodeTranslation, + }, + { + name: "Replaces t/Terraform With p/Pulumi", + docFile: DocFile{ + Content: []byte("Any mention of Terraform or terraform will be Pulumi or pulumi"), + }, + expected: []byte("Any mention of Pulumi or pulumi will be Pulumi or pulumi"), + phase: info.PostCodeTranslation, + }, + { + name: "Replaces argument headers with input headers", + docFile: DocFile{ + Content: []byte("# Argument Reference\n" + + "The following arguments are supported:\n* `some_argument`\n\n" + + "block contains the following arguments"), + }, + expected: []byte("# Configuration Reference\n" + + "The following configuration inputs are supported:\n* `some_argument`\n\n" + + "input has the following nested fields"), + phase: info.PostCodeTranslation, + }, + { + name: "Skips sections about logging by default", + docFile: DocFile{ + Content: []byte("# I am a provider\n\n### Additional Logging\n This section should be skipped"), + FileName: "filename", + }, + expected: []byte("# I am a provider\n"), + phase: info.PostCodeTranslation, + }, + { + name: "Strips mentions of Terraform version pattern 1", + docFile: DocFile{ + Content: []byte("This is a provider. It requires terraform 0.12 or later."), + }, + expected: []byte("This is a provider."), + phase: info.PostCodeTranslation, + }, + { + name: "Strips mentions of Terraform version pattern 2", + docFile: DocFile{ + Content: []byte("This is a provider. It requires terraform v0.12 or later."), + }, + expected: []byte("This is a provider."), + phase: info.PostCodeTranslation, + }, + { + name: "Strips mentions of Terraform version pattern 3", + docFile: DocFile{ + Content: []byte("This is a provider with an example. For Terraform v1.5 and later:\n Use this code."), + }, + expected: []byte("This is a provider with an example.\nUse this code."), + phase: info.PostCodeTranslation, + }, + { + name: "Strips mentions of Terraform version pattern 4", + docFile: DocFile{ + Content: []byte("This is a provider with an example. Terraform 1.5 and later:\n Use this code."), + }, + expected: []byte("This is a provider with an example.\nUse this code."), + phase: info.PostCodeTranslation, + }, + { + name: "Strips mentions of Terraform version pattern 5", + docFile: DocFile{ + Content: []byte("This is a provider with an example. Terraform 1.5 and earlier:\n Use this code."), + }, + expected: []byte("This is a provider with an example.\nUse this code."), + phase: info.PostCodeTranslation, + }, + { + name: "Strips mentions of Terraform version pattern 6", + docFile: DocFile{ + Content: []byte("This provider requires at least Terraform 1.0."), + }, + expected: []byte(""), + phase: info.PostCodeTranslation, + }, + { + name: "Strips mentions of Terraform version pattern 7", + docFile: DocFile{ + Content: []byte("This provider requires Terraform 1.0."), + }, + expected: []byte(""), + phase: info.PostCodeTranslation, + }, + { + name: "Strips mentions of Terraform version pattern 8", + docFile: DocFile{ + Content: []byte("A minimum of Terraform 1.4.0 is recommended."), + }, + expected: []byte(""), + phase: info.PostCodeTranslation, + }, + { + name: "Strips mentions of Terraform version With Surrounding Text", + docFile: DocFile{ + Content: []byte(readfile(t, "test_data/replace-terraform-version/input.md")), + }, + expected: []byte(readfile(t, "test_data/replace-terraform-version/expected.md")), + phase: info.PostCodeTranslation, + }, + { + // Found in linode + name: "Rewrites providers.tf to Pulumi.yaml", + docFile: DocFile{ + Content: []byte(readfile(t, "test_data/rewrite-providers-tf-to-pulumi-yaml/input.md")), + }, + expected: []byte(readfile(t, "test_data/rewrite-providers-tf-to-pulumi-yaml/expected.md")), + phase: info.PostCodeTranslation, + }, + { + name: "Rewrites terraform init to pulumi up", + docFile: DocFile{ + Content: []byte(readfile(t, "test_data/rewrite-tf-init-to-pulumi-up/input.md")), + }, + expected: []byte(readfile(t, "test_data/rewrite-tf-init-to-pulumi-up/expected.md")), + phase: info.PostCodeTranslation, + }, + { + // Found in linode + name: "Replaces provider block with provider configuration", + docFile: DocFile{ + Content: []byte(readfile(t, "test_data/replace-provider-block/input.md")), + }, + expected: []byte(readfile(t, "test_data/replace-provider-block/expected.md")), + phase: info.PostCodeTranslation, + }, + } + edits := defaultEditRules() + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + if runtime.GOOS == "windows" { + t.Skipf("Skipping on Windows due to a newline handling issue") + } + actual, err := edits.apply("*", tt.docFile.Content, tt.phase) + require.NoError(t, err) + assertEqualHTML(t, string(tt.expected), string(actual)) + }) + } +} + +func TestApplyCustomEditRules(t *testing.T) { + t.Parallel() + + type testCase struct { + // The name of the test case. + name string + docFile DocFile + expected []byte + edits editRules + } + + tests := []testCase{ + { + name: "Replaces specified text pre code translation", + docFile: DocFile{ + Content: []byte("This provider has a hroffic unreadable typo"), + }, + expected: []byte("This provider has a horrific unreadable typo, which is now fixed"), + edits: append( + defaultEditRules(), + tfbridge.DocsEdit{ + Path: "testfile.md", + Edit: func(_ string, content []byte) ([]byte, error) { + return bytes.ReplaceAll( + content, + []byte("hroffic unreadable typo"), + []byte("horrific unreadable typo, which is now fixed"), + ), nil + }, + }, + ), + }, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + if runtime.GOOS == "windows" { + t.Skipf("Skipping on Windows due to a newline handling issue") + } + actual, err := tt.edits.apply("testfile.md", tt.docFile.Content, info.PreCodeTranslation) + require.NoError(t, err) + assertEqualHTML(t, string(tt.expected), string(actual)) + }) + } + +} diff --git a/pkg/tfgen/installation_docs.go b/pkg/tfgen/installation_docs.go index 6a331703f..5282b3591 100644 --- a/pkg/tfgen/installation_docs.go +++ b/pkg/tfgen/installation_docs.go @@ -17,19 +17,29 @@ import ( "golang.org/x/text/language" "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfbridge" + "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfbridge/info" "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfgen/parse" "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfgen/parse/section" ) func plainDocsParser(docFile *DocFile, g *Generator) ([]byte, error) { + + // Apply pre-code translation edit rules. This applies all default edit rules and provider-supplied edit rules in + // the default pre-code translation phase. + contentBytes, err := g.editRules.apply(docFile.FileName, docFile.Content, info.PreCodeTranslation) + if err != nil { + return nil, err + } + // Get file content without front matter - content := trimFrontMatter(docFile.Content) + content := trimFrontMatter(contentBytes) + // Add pulumi-specific front matter // Generate pulumi-specific front matter frontMatter := writeFrontMatter(g.info.Name) // Remove the title. A title gets populated from Hugo frontmatter; we do not want two. - content, err := removeTitle(content) + content, err = removeTitle(content) if err != nil { return nil, err } @@ -40,6 +50,7 @@ func plainDocsParser(docFile *DocFile, g *Generator) ([]byte, error) { // Generate pulumi-specific installation instructions installationInstructions := writeInstallationInstructions(g.info.Golang.ImportBasePath, g.info.Name) + // Determine if we should write an overview header. overviewHeader := getOverviewHeader(content) // Add instructions to top of file @@ -51,8 +62,9 @@ func plainDocsParser(docFile *DocFile, g *Generator) ([]byte, error) { return nil, err } - // Apply edit rules to transform the doc for Pulumi-ready presentation - contentBytes, err := applyEditRules([]byte(contentStr), docFile.FileName, g) + // Apply post-code translation edit rules. This applies all default edit rules and provider-supplied edit rules in + // the post-code translation phase. + contentBytes, err = g.editRules.apply(docFile.FileName, []byte(contentStr), info.PostCodeTranslation) if err != nil { return nil, err } @@ -127,41 +139,6 @@ func stripSchemaGeneratedByTFPluginDocs(content []byte) []byte { content = tfplugindocsComment.ReplaceAll(content, nil) return content } - -func applyEditRules(contentBytes []byte, docFile string, g *Generator) ([]byte, error) { - // Obtain edit rules passed by the provider - edits := g.editRules - // Additional edit rules for installation files - edits = append(edits, - skipSectionHeadersEdit(docFile), - removeTfVersionMentions(docFile), - //Replace "providers.tf" with "Pulumi.yaml" - reReplace(`providers.tf`, `Pulumi.yaml`), - reReplace(`terraform init`, `pulumi up`), - // Replace all "T/terraform" with "P/pulumi" - reReplace(`Terraform`, `Pulumi`), - reReplace(`terraform`, `pulumi`), - // Replace all "H/hashicorp" strings - reReplace(`Hashicorp`, `Pulumi`), - reReplace(`hashicorp`, `pulumi`), - // Reformat certain headers - reReplace(`The following arguments are supported`, - `The following configuration inputs are supported`), - reReplace(`Argument Reference`, - `Configuration Reference`), - reReplace(`Schema`, - `Configuration Reference`), - reReplace("### Optional\n", ""), - reReplace(`block contains the following arguments`, - `input has the following nested fields`), - reReplace(`provider block`, `provider configuration`), - ) - contentBytes, err := edits.apply(docFile, contentBytes) - if err != nil { - return nil, err - } - return contentBytes, nil -} func translateCodeBlocks(contentStr string, g *Generator) (string, error) { var returnContent string // Extract code blocks @@ -397,10 +374,10 @@ func SkipSectionByHeaderContent( } // Edit Rule for skipping headers. -func skipSectionHeadersEdit(docFile string) tfbridge.DocsEdit { +func skipSectionHeadersEdit() tfbridge.DocsEdit { defaultHeaderSkipRegexps := getDefaultHeadersToSkip() return tfbridge.DocsEdit{ - Path: docFile, + Path: "*", Edit: func(_ string, content []byte) ([]byte, error) { return SkipSectionByHeaderContent(content, func(headerText string) bool { for _, header := range defaultHeaderSkipRegexps { @@ -411,6 +388,7 @@ func skipSectionHeadersEdit(docFile string) tfbridge.DocsEdit { return false }) }, + Phase: info.PostCodeTranslation, } } @@ -437,16 +415,17 @@ func getTfVersionsToRemove() []*regexp.Regexp { return tfVersionsToRemove } -func removeTfVersionMentions(docFile string) tfbridge.DocsEdit { +func removeTfVersionMentions() tfbridge.DocsEdit { tfVersionsToRemove := getTfVersionsToRemove() return tfbridge.DocsEdit{ - Path: docFile, + Path: "*", Edit: func(_ string, content []byte) ([]byte, error) { for _, tfVersion := range tfVersionsToRemove { content = tfVersion.ReplaceAll(content, nil) } return content, nil }, + Phase: info.PostCodeTranslation, } } diff --git a/pkg/tfgen/installation_docs_test.go b/pkg/tfgen/installation_docs_test.go index aabc9adda..3e4dc4024 100644 --- a/pkg/tfgen/installation_docs_test.go +++ b/pkg/tfgen/installation_docs_test.go @@ -14,7 +14,6 @@ import ( sdkv2 "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfshim/sdk-v2" ) -//nolint:lll func TestPlainDocsParser(t *testing.T) { t.Parallel() @@ -23,35 +22,86 @@ func TestPlainDocsParser(t *testing.T) { name string docFile DocFile expected []byte + edits editRules + } + // Mock provider for test conversion + p := tfbridge.ProviderInfo{ + Name: "simple", + P: sdkv2.NewProvider(&schema.Provider{ + ResourcesMap: map[string]*schema.Resource{ + "simple_resource": { + Schema: map[string]*schema.Schema{ + "input_one": { + Type: schema.TypeString, + Optional: true, + }, + "input_two": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + }), } + pclsMap := make(map[string]translatedExample) tests := []testCase{ { - name: "Replaces Upstream Front Matter With Pulumi Front Matter", + name: "Converts index.md file into Pulumi installation file", docFile: DocFile{ - Content: []byte("---\nlayout: \"openstack\"\npage_title: \"Provider: OpenStack\"\nsidebar_current: \"docs-openstack-index\"\ndescription: |-\n The OpenStack provider is used to interact with the many resources supported by OpenStack. The provider needs to be configured with the proper credentials before it can be used.\n---\n\n# OpenStack Provider\n\nThe OpenStack provider is used to interact with the\nmany resources supported by OpenStack. The provider needs to be configured\nwith the proper credentials before it can be used.\n\nUse the navigation to the left to read about the available resources."), + Content: []byte(readfile(t, "test_data/convert-index-file/input.md")), }, - expected: []byte("---\ntitle: OpenStack Provider Installation & Configuration\nmeta_desc: Provides an overview on how to configure the Pulumi OpenStack Provider.\nlayout: package\n---\n\nThe OpenStack provider is used to interact with the\nmany resources supported by OpenStack. The provider needs to be configured\nwith the proper credentials before it can be used.\n\nUse the navigation to the left to read about the available resources."), + expected: []byte(readfile(t, "test_data/convert-index-file/expected.md")), + edits: defaultEditRules(), }, { - name: "Writes Pulumi Style Front Matter If Not Present", + // Discovered while generating docs for Libvirt - the test case has an incorrect ```hcl + // on what should be a shell script. The provider's edit rule removes this. + name: "Applies provider supplied edit rules", docFile: DocFile{ - Content: []byte("# Artifactory Provider\n\nThe [Artifactory](https://jfrog.com/artifactory/) provider is used to interact with the resources supported by Artifactory. The provider needs to be configured with the proper credentials before it can be used.\n\nLinks to documentation for specific resources can be found in the table of contents to the left.\n\nThis provider requires access to Artifactory APIs, which are only available in the _licensed_ pro and enterprise editions. You can determine which license you have by accessing the following the URL `${host}/artifactory/api/system/licenses/`.\n\nYou can either access it via API, or web browser - it require admin level credentials."), + Content: []byte(readfile(t, "test_data/convert-index-file-edit-rules/input.md")), }, - expected: []byte("---\ntitle: Artifactory Provider Installation & Configuration\nmeta_desc: Provides an overview on how to configure the Pulumi Artifactory Provider.\nlayout: package\n---\n\nThe [Artifactory](https://jfrog.com/artifactory/) provider is used to interact with the resources supported by Artifactory. The provider needs to be configured with the proper credentials before it can be used.\n\nLinks to documentation for specific resources can be found in the table of contents to the left.\n\nThis provider requires access to Artifactory APIs, which are only available in the _licensed_ pro and enterprise editions. You can determine which license you have by accessing the following the URL `${host}/artifactory/api/system/licenses/`.\n\nYou can either access it via API, or web browser - it require admin level credentials."), + expected: []byte(readfile(t, "test_data/convert-index-file-edit-rules/expected.md")), + edits: append( + defaultEditRules(), + tfbridge.DocsEdit{ + Edit: func(_ string, content []byte) ([]byte, error) { + return bytes.ReplaceAll( + content, + []byte("shell environment variable.\n\n```hcl"), + []byte("shell environment variable.\n\n```"), + ), nil + }, + }, + ), }, } for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { - t.Skipf("this function is under development and will receive tests once all parts are completed") t.Parallel() + if runtime.GOOS == "windows" { + t.Skipf("Skipping on Windows due to a newline handling issue") + } g := &Generator{ sink: mockSink{t}, + info: tfbridge.ProviderInfo{ + Golang: &tfbridge.GolangInfo{ + ImportBasePath: "github.com/pulumi/pulumi-libvirt/sdk/go/libvirt", + }, + Name: "libvirt", + }, + cliConverterState: &cliConverter{ + info: p, + pcls: pclsMap, + }, + editRules: tt.edits, + language: RegistryDocs, } actual, err := plainDocsParser(&tt.docFile, g) require.NoError(t, err) - require.Equal(t, string(tt.expected), string(actual)) + assertEqualHTML(t, string(tt.expected), string(actual)) }) } } @@ -236,169 +286,6 @@ func TestWriteFrontMatter(t *testing.T) { }) } -func TestApplyEditRules(t *testing.T) { - t.Parallel() - - type testCase struct { - // The name of the test case. - name string - docFile DocFile - expected []byte - } - - tests := []testCase{ - { - name: "Replaces h/Hashicorp With p/Pulumi", - docFile: DocFile{ - Content: []byte("Any mention of Hashicorp or hashicorp will be Pulumi or pulumi"), - }, - expected: []byte("Any mention of Pulumi or pulumi will be Pulumi or pulumi"), - }, - { - name: "Replaces t/Terraform With p/Pulumi", - docFile: DocFile{ - Content: []byte("Any mention of Terraform or terraform will be Pulumi or pulumi"), - }, - expected: []byte("Any mention of Pulumi or pulumi will be Pulumi or pulumi"), - }, - { - name: "Replaces argument headers with input headers", - docFile: DocFile{ - Content: []byte("# Argument Reference\n" + - "The following arguments are supported:\n* `some_argument`\n\n" + - "block contains the following arguments"), - }, - expected: []byte("# Configuration Reference\n" + - "The following configuration inputs are supported:\n* `some_argument`\n\n" + - "input has the following nested fields"), - }, - { - name: "Replaces terraform plan with pulumi preview", - docFile: DocFile{ - Content: []byte("terraform plan this program"), - }, - expected: []byte("pulumi preview this program"), - }, - { - name: "Skips sections about logging by default", - docFile: DocFile{ - Content: []byte("# I am a provider\n\n### Additional Logging\n This section should be skipped"), - FileName: "filename", - }, - expected: []byte("# I am a provider\n"), - }, - { - name: "Strips Hashicorp links correctly", - docFile: DocFile{ - Content: []byte(readfile(t, "test_data/replace-links/input.md")), - }, - expected: []byte(readfile(t, "test_data/replace-links/actual.md")), - }, - { - name: "Strips mentions of Terraform version pattern 1", - docFile: DocFile{ - Content: []byte("This is a provider. It requires terraform 0.12 or later."), - }, - expected: []byte("This is a provider."), - }, - { - name: "Strips mentions of Terraform version pattern 2", - docFile: DocFile{ - Content: []byte("This is a provider. It requires terraform v0.12 or later."), - }, - expected: []byte("This is a provider."), - }, - { - name: "Strips mentions of Terraform version pattern 3", - docFile: DocFile{ - Content: []byte("This is a provider with an example. For Terraform v1.5 and later:\n Use this code."), - }, - expected: []byte("This is a provider with an example.\nUse this code."), - }, - { - name: "Strips mentions of Terraform version pattern 4", - docFile: DocFile{ - Content: []byte("This is a provider with an example. Terraform 1.5 and later:\n Use this code."), - }, - expected: []byte("This is a provider with an example.\nUse this code."), - }, - { - name: "Strips mentions of Terraform version pattern 5", - docFile: DocFile{ - Content: []byte("This is a provider with an example. Terraform 1.5 and earlier:\n Use this code."), - }, - expected: []byte("This is a provider with an example.\nUse this code."), - }, - { - name: "Strips mentions of Terraform version pattern 6", - docFile: DocFile{ - Content: []byte("This provider requires at least Terraform 1.0."), - }, - expected: []byte(""), - }, - { - name: "Strips mentions of Terraform version pattern 7", - docFile: DocFile{ - Content: []byte("This provider requires Terraform 1.0."), - }, - expected: []byte(""), - }, - { - name: "Strips mentions of Terraform version pattern 8", - docFile: DocFile{ - Content: []byte("A minimum of Terraform 1.4.0 is recommended."), - }, - expected: []byte(""), - }, - { - name: "Strips mentions of Terraform version With Surrounding Text", - docFile: DocFile{ - Content: []byte(readfile(t, "test_data/replace-terraform-version/input.md")), - }, - expected: []byte(readfile(t, "test_data/replace-terraform-version/expected.md")), - }, - { - // Found in linode - name: "Rewrites providers.tf to Pulumi.yaml", - docFile: DocFile{ - Content: []byte(readfile(t, "test_data/rewrite-providers-tf-to-pulumi-yaml/input.md")), - }, - expected: []byte(readfile(t, "test_data/rewrite-providers-tf-to-pulumi-yaml/expected.md")), - }, - { - name: "Rewrites terraform init to pulumi up", - docFile: DocFile{ - Content: []byte(readfile(t, "test_data/rewrite-tf-init-to-pulumi-up/input.md")), - }, - expected: []byte(readfile(t, "test_data/rewrite-tf-init-to-pulumi-up/expected.md")), - }, - { - // Found in linode - name: "Replaces provider block with provider configuration", - docFile: DocFile{ - Content: []byte(readfile(t, "test_data/replace-provider-block/input.md")), - }, - expected: []byte(readfile(t, "test_data/replace-provider-block/expected.md")), - }, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - if runtime.GOOS == "windows" { - t.Skipf("Skipping on Windows due to a newline handling issue") - } - g := &Generator{ - sink: mockSink{t}, - editRules: defaultEditRules(), - } - actual, err := applyEditRules(tt.docFile.Content, "testfile.md", g) - require.NoError(t, err) - assertEqualHTML(t, string(tt.expected), string(actual)) - }) - } -} - func TestTranslateCodeBlocks(t *testing.T) { type testCase struct { @@ -491,7 +378,7 @@ func TestSkipSectionHeadersByContent(t *testing.T) { name: "Skips Sections With Unwanted Headers", headersToSkip: []string{"Debugging Provider Output Using Logs", "Testing and Development"}, input: readTestFile(t, "skip-sections-by-header/input.md"), - expected: readTestFile(t, "skip-sections-by-header/actual.md"), + expected: readTestFile(t, "skip-sections-by-header/expected.md"), } t.Run(tc.name, func(t *testing.T) { diff --git a/pkg/tfgen/test_data/convert-index-file-edit-rules/expected.md b/pkg/tfgen/test_data/convert-index-file-edit-rules/expected.md new file mode 100644 index 000000000..d45fdf7a0 --- /dev/null +++ b/pkg/tfgen/test_data/convert-index-file-edit-rules/expected.md @@ -0,0 +1,271 @@ +--- +title: Libvirt Provider +meta_desc: Provides an overview on how to configure the Pulumi Libvirt provider. +layout: package +--- +## Installation + +The libvirt provider is available as a package in all Pulumi languages: + +* JavaScript/TypeScript: [`@pulumi/libvirt`](https://www.npmjs.com/package/@pulumi/libvirt) +* Python: [`pulumi-libvirt`](https://pypi.org/project/pulumi-libvirt/) +* Go: [`github.com/pulumi/pulumi-libvirt/sdk/go/libvirt`](https://github.com/pulumi/pulumi-libvirt) +* .NET: [`Pulumi.Libvirt`](https://www.nuget.org/packages/Pulumi.Libvirt) +* Java: [`com.pulumi/libvirt`](https://central.sonatype.com/artifact/com.pulumi/libvirt) +## Overview + +The Libvirt provider is used to interact with Linux +[libvirt](https://libvirt.org) hypervisors. + +The provider needs to be configured with the proper connection information +before it can be used. + +> **Note:** while libvirt can be used with several types of hypervisors, this +provider focuses on [KVM](http://libvirt.org/drvqemu.html). Other drivers may not be +working and haven't been tested. +## The connection URI + +The provider understands [connection URIs](https://libvirt.org/uri.html). The supported transports are: + +* `tcp` (non-encrypted connection) +* `unix` (UNIX domain socket) +* `tls` (See [here](https://libvirt.org/kbase/tlscerts.html) for information how to setup certificates) +* `ssh` (Secure shell) + +Unlike the original libvirt, the `ssh` transport is not implemented using the ssh command and therefore does not require `nc` (netcat) on the server side. + +Additionally, the `ssh` URI supports passwords using the `driver+ssh://[username:PASSWORD@][hostname][:port]/[path]?sshauth=ssh-password` syntax. + +As the provider does not use libvirt on the client side, not all connection URI options are supported or apply. +## Example Usage + +{{< chooser language "typescript,python,go,csharp,java,yaml" >}} +{{% choosable language typescript %}} +```yaml +# Pulumi.yaml provider configuration file +name: configuration-example +runtime: nodejs +config: + simple-provider:authUrl: + value: http://myauthurl:5000/v3 + simple-provider:password: + value: pwd + simple-provider:region: + value: RegionOne + simple-provider:tenantName: + value: admin + simple-provider:userName: + value: admin + +``` +```typescript +import * as pulumi from "@pulumi/pulumi"; +import * as simple from "@pulumi/simple"; + +//# Define a resource +const aResource = new simple.index.Resource("a_resource", { + inputOne: "hello", + inputTwo: true, +}); +``` +{{% /choosable %}} +{{% choosable language python %}} +```yaml +# Pulumi.yaml provider configuration file +name: configuration-example +runtime: python +config: + simple-provider:authUrl: + value: http://myauthurl:5000/v3 + simple-provider:password: + value: pwd + simple-provider:region: + value: RegionOne + simple-provider:tenantName: + value: admin + simple-provider:userName: + value: admin + +``` +```python +import pulumi +import pulumi_simple as simple + +## Define a resource +a_resource = simple.index.Resource("a_resource", + input_one=hello, + input_two=True) +``` +{{% /choosable %}} +{{% choosable language csharp %}} +```yaml +# Pulumi.yaml provider configuration file +name: configuration-example +runtime: dotnet +config: + simple-provider:authUrl: + value: http://myauthurl:5000/v3 + simple-provider:password: + value: pwd + simple-provider:region: + value: RegionOne + simple-provider:tenantName: + value: admin + simple-provider:userName: + value: admin + +``` +```csharp +using System.Collections.Generic; +using System.Linq; +using Pulumi; +using Simple = Pulumi.Simple; + +return await Deployment.RunAsync(() => +{ + //# Define a resource + var aResource = new Simple.Index.Resource("a_resource", new() + { + InputOne = "hello", + InputTwo = true, + }); + +}); + +``` +{{% /choosable %}} +{{% choosable language go %}} +```yaml +# Pulumi.yaml provider configuration file +name: configuration-example +runtime: go +config: + simple-provider:authUrl: + value: http://myauthurl:5000/v3 + simple-provider:password: + value: pwd + simple-provider:region: + value: RegionOne + simple-provider:tenantName: + value: admin + simple-provider:userName: + value: admin + +``` +```go +package main + +import ( + "github.com/pulumi/pulumi-simple/sdk/go/simple" + "github.com/pulumi/pulumi/sdk/v3/go/pulumi" +) + +func main() { + pulumi.Run(func(ctx *pulumi.Context) error { + // # Define a resource + _, err := simple.NewResource(ctx, "a_resource", &simple.ResourceArgs{ + InputOne: "hello", + InputTwo: true, + }) + if err != nil { + return err + } + return nil + }) +} +``` +{{% /choosable %}} +{{% choosable language yaml %}} +```yaml +# Pulumi.yaml provider configuration file +name: configuration-example +runtime: yaml +config: + simple-provider:authUrl: + value: http://myauthurl:5000/v3 + simple-provider:password: + value: pwd + simple-provider:region: + value: RegionOne + simple-provider:tenantName: + value: admin + simple-provider:userName: + value: admin + +``` +```yaml +resources: + ## Define a resource + aResource: + type: simple:resource + name: a_resource + properties: + inputOne: hello + inputTwo: true +``` +{{% /choosable %}} +{{% choosable language java %}} +```yaml +# Pulumi.yaml provider configuration file +name: configuration-example +runtime: java +config: + simple-provider:authUrl: + value: http://myauthurl:5000/v3 + simple-provider:password: + value: pwd + simple-provider:region: + value: RegionOne + simple-provider:tenantName: + value: admin + simple-provider:userName: + value: admin + +``` +```java +package generated_program; + +import com.pulumi.Context; +import com.pulumi.Pulumi; +import com.pulumi.core.Output; +import com.pulumi.simple.resource; +import com.pulumi.simple.ResourceArgs; +import java.util.List; +import java.util.ArrayList; +import java.util.Map; +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Paths; + +public class App { + public static void main(String[] args) { + Pulumi.run(App::stack); + } + + public static void stack(Context ctx) { + //# Define a resource + var aResource = new Resource("aResource", ResourceArgs.builder() + .inputOne("hello") + .inputTwo(true) + .build()); + + } +} +``` +{{% /choosable %}} +{{< /chooser >}} +## Configuration Reference + +The following keys can be used to configure the provider. + +* `uri` - (Required) The [connection URI](https://libvirt.org/uri.html) used + to connect to the libvirt host. +## Environment variables + +The libvirt connection URI can also be specified with the `LIBVIRT_DEFAULT_URI` +shell environment variable. + +``` +$ export LIBVIRT_DEFAULT_URI="qemu+ssh://root@192.168.1.100/system" +$ pulumi preview +``` \ No newline at end of file diff --git a/pkg/tfgen/test_data/convert-index-file-edit-rules/input.md b/pkg/tfgen/test_data/convert-index-file-edit-rules/input.md new file mode 100644 index 000000000..d9c74a479 --- /dev/null +++ b/pkg/tfgen/test_data/convert-index-file-edit-rules/input.md @@ -0,0 +1,69 @@ +--- +layout: "libvirt" +page_title: "Provider: libvirt" +sidebar_current: "docs-libvirt-index" +description: |- + The Libvirt provider is used to interact with Linux KVM/libvirt hypervisors. The provider needs to be configured with the proper connection information before it can be used. +--- + +# Libvirt Provider + +The Libvirt provider is used to interact with Linux +[libvirt](https://libvirt.org) hypervisors. + +The provider needs to be configured with the proper connection information +before it can be used. + +~> **Note:** while libvirt can be used with several types of hypervisors, this +provider focuses on [KVM](http://libvirt.org/drvqemu.html). Other drivers may not be +working and haven't been tested. + +## The connection URI + +The provider understands [connection URIs](https://libvirt.org/uri.html). The supported transports are: + +* `tcp` (non-encrypted connection) +* `unix` (UNIX domain socket) +* `tls` (See [here](https://libvirt.org/kbase/tlscerts.html) for information how to setup certificates) +* `ssh` (Secure shell) + +Unlike the original libvirt, the `ssh` transport is not implemented using the ssh command and therefore does not require `nc` (netcat) on the server side. + +Additionally, the `ssh` URI supports passwords using the `driver+ssh://[username:PASSWORD@][hostname][:port]/[path]?sshauth=ssh-password` syntax. + +As the provider does not use libvirt on the client side, not all connection URI options are supported or apply. + +## Example Usage + +```hcl +# Configure the OpenStack Provider +provider "simple-provider" { + user_name = "admin" + tenant_name = "admin" + password = "pwd" + auth_url = "http://myauthurl:5000/v3" + region = "RegionOne" +} +## Define a resource +resource "simple_resource" "a_resource" { + input_one = "hello" + input_two = true +} +``` + +## Configuration Reference + +The following keys can be used to configure the provider. + +* `uri` - (Required) The [connection URI](https://libvirt.org/uri.html) used + to connect to the libvirt host. + +## Environment variables + +The libvirt connection URI can also be specified with the `LIBVIRT_DEFAULT_URI` +shell environment variable. + +```hcl +$ export LIBVIRT_DEFAULT_URI="qemu+ssh://root@192.168.1.100/system" +$ terraform plan +``` \ No newline at end of file diff --git a/pkg/tfgen/test_data/convert-index-file/expected.md b/pkg/tfgen/test_data/convert-index-file/expected.md new file mode 100644 index 000000000..d45fdf7a0 --- /dev/null +++ b/pkg/tfgen/test_data/convert-index-file/expected.md @@ -0,0 +1,271 @@ +--- +title: Libvirt Provider +meta_desc: Provides an overview on how to configure the Pulumi Libvirt provider. +layout: package +--- +## Installation + +The libvirt provider is available as a package in all Pulumi languages: + +* JavaScript/TypeScript: [`@pulumi/libvirt`](https://www.npmjs.com/package/@pulumi/libvirt) +* Python: [`pulumi-libvirt`](https://pypi.org/project/pulumi-libvirt/) +* Go: [`github.com/pulumi/pulumi-libvirt/sdk/go/libvirt`](https://github.com/pulumi/pulumi-libvirt) +* .NET: [`Pulumi.Libvirt`](https://www.nuget.org/packages/Pulumi.Libvirt) +* Java: [`com.pulumi/libvirt`](https://central.sonatype.com/artifact/com.pulumi/libvirt) +## Overview + +The Libvirt provider is used to interact with Linux +[libvirt](https://libvirt.org) hypervisors. + +The provider needs to be configured with the proper connection information +before it can be used. + +> **Note:** while libvirt can be used with several types of hypervisors, this +provider focuses on [KVM](http://libvirt.org/drvqemu.html). Other drivers may not be +working and haven't been tested. +## The connection URI + +The provider understands [connection URIs](https://libvirt.org/uri.html). The supported transports are: + +* `tcp` (non-encrypted connection) +* `unix` (UNIX domain socket) +* `tls` (See [here](https://libvirt.org/kbase/tlscerts.html) for information how to setup certificates) +* `ssh` (Secure shell) + +Unlike the original libvirt, the `ssh` transport is not implemented using the ssh command and therefore does not require `nc` (netcat) on the server side. + +Additionally, the `ssh` URI supports passwords using the `driver+ssh://[username:PASSWORD@][hostname][:port]/[path]?sshauth=ssh-password` syntax. + +As the provider does not use libvirt on the client side, not all connection URI options are supported or apply. +## Example Usage + +{{< chooser language "typescript,python,go,csharp,java,yaml" >}} +{{% choosable language typescript %}} +```yaml +# Pulumi.yaml provider configuration file +name: configuration-example +runtime: nodejs +config: + simple-provider:authUrl: + value: http://myauthurl:5000/v3 + simple-provider:password: + value: pwd + simple-provider:region: + value: RegionOne + simple-provider:tenantName: + value: admin + simple-provider:userName: + value: admin + +``` +```typescript +import * as pulumi from "@pulumi/pulumi"; +import * as simple from "@pulumi/simple"; + +//# Define a resource +const aResource = new simple.index.Resource("a_resource", { + inputOne: "hello", + inputTwo: true, +}); +``` +{{% /choosable %}} +{{% choosable language python %}} +```yaml +# Pulumi.yaml provider configuration file +name: configuration-example +runtime: python +config: + simple-provider:authUrl: + value: http://myauthurl:5000/v3 + simple-provider:password: + value: pwd + simple-provider:region: + value: RegionOne + simple-provider:tenantName: + value: admin + simple-provider:userName: + value: admin + +``` +```python +import pulumi +import pulumi_simple as simple + +## Define a resource +a_resource = simple.index.Resource("a_resource", + input_one=hello, + input_two=True) +``` +{{% /choosable %}} +{{% choosable language csharp %}} +```yaml +# Pulumi.yaml provider configuration file +name: configuration-example +runtime: dotnet +config: + simple-provider:authUrl: + value: http://myauthurl:5000/v3 + simple-provider:password: + value: pwd + simple-provider:region: + value: RegionOne + simple-provider:tenantName: + value: admin + simple-provider:userName: + value: admin + +``` +```csharp +using System.Collections.Generic; +using System.Linq; +using Pulumi; +using Simple = Pulumi.Simple; + +return await Deployment.RunAsync(() => +{ + //# Define a resource + var aResource = new Simple.Index.Resource("a_resource", new() + { + InputOne = "hello", + InputTwo = true, + }); + +}); + +``` +{{% /choosable %}} +{{% choosable language go %}} +```yaml +# Pulumi.yaml provider configuration file +name: configuration-example +runtime: go +config: + simple-provider:authUrl: + value: http://myauthurl:5000/v3 + simple-provider:password: + value: pwd + simple-provider:region: + value: RegionOne + simple-provider:tenantName: + value: admin + simple-provider:userName: + value: admin + +``` +```go +package main + +import ( + "github.com/pulumi/pulumi-simple/sdk/go/simple" + "github.com/pulumi/pulumi/sdk/v3/go/pulumi" +) + +func main() { + pulumi.Run(func(ctx *pulumi.Context) error { + // # Define a resource + _, err := simple.NewResource(ctx, "a_resource", &simple.ResourceArgs{ + InputOne: "hello", + InputTwo: true, + }) + if err != nil { + return err + } + return nil + }) +} +``` +{{% /choosable %}} +{{% choosable language yaml %}} +```yaml +# Pulumi.yaml provider configuration file +name: configuration-example +runtime: yaml +config: + simple-provider:authUrl: + value: http://myauthurl:5000/v3 + simple-provider:password: + value: pwd + simple-provider:region: + value: RegionOne + simple-provider:tenantName: + value: admin + simple-provider:userName: + value: admin + +``` +```yaml +resources: + ## Define a resource + aResource: + type: simple:resource + name: a_resource + properties: + inputOne: hello + inputTwo: true +``` +{{% /choosable %}} +{{% choosable language java %}} +```yaml +# Pulumi.yaml provider configuration file +name: configuration-example +runtime: java +config: + simple-provider:authUrl: + value: http://myauthurl:5000/v3 + simple-provider:password: + value: pwd + simple-provider:region: + value: RegionOne + simple-provider:tenantName: + value: admin + simple-provider:userName: + value: admin + +``` +```java +package generated_program; + +import com.pulumi.Context; +import com.pulumi.Pulumi; +import com.pulumi.core.Output; +import com.pulumi.simple.resource; +import com.pulumi.simple.ResourceArgs; +import java.util.List; +import java.util.ArrayList; +import java.util.Map; +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Paths; + +public class App { + public static void main(String[] args) { + Pulumi.run(App::stack); + } + + public static void stack(Context ctx) { + //# Define a resource + var aResource = new Resource("aResource", ResourceArgs.builder() + .inputOne("hello") + .inputTwo(true) + .build()); + + } +} +``` +{{% /choosable %}} +{{< /chooser >}} +## Configuration Reference + +The following keys can be used to configure the provider. + +* `uri` - (Required) The [connection URI](https://libvirt.org/uri.html) used + to connect to the libvirt host. +## Environment variables + +The libvirt connection URI can also be specified with the `LIBVIRT_DEFAULT_URI` +shell environment variable. + +``` +$ export LIBVIRT_DEFAULT_URI="qemu+ssh://root@192.168.1.100/system" +$ pulumi preview +``` \ No newline at end of file diff --git a/pkg/tfgen/test_data/convert-index-file/input.md b/pkg/tfgen/test_data/convert-index-file/input.md new file mode 100644 index 000000000..1be3a5d0e --- /dev/null +++ b/pkg/tfgen/test_data/convert-index-file/input.md @@ -0,0 +1,69 @@ +--- +layout: "libvirt" +page_title: "Provider: libvirt" +sidebar_current: "docs-libvirt-index" +description: |- + The Libvirt provider is used to interact with Linux KVM/libvirt hypervisors. The provider needs to be configured with the proper connection information before it can be used. +--- + +# Libvirt Provider + +The Libvirt provider is used to interact with Linux +[libvirt](https://libvirt.org) hypervisors. + +The provider needs to be configured with the proper connection information +before it can be used. + +~> **Note:** while libvirt can be used with several types of hypervisors, this +provider focuses on [KVM](http://libvirt.org/drvqemu.html). Other drivers may not be +working and haven't been tested. + +## The connection URI + +The provider understands [connection URIs](https://libvirt.org/uri.html). The supported transports are: + +* `tcp` (non-encrypted connection) +* `unix` (UNIX domain socket) +* `tls` (See [here](https://libvirt.org/kbase/tlscerts.html) for information how to setup certificates) +* `ssh` (Secure shell) + +Unlike the original libvirt, the `ssh` transport is not implemented using the ssh command and therefore does not require `nc` (netcat) on the server side. + +Additionally, the `ssh` URI supports passwords using the `driver+ssh://[username:PASSWORD@][hostname][:port]/[path]?sshauth=ssh-password` syntax. + +As the provider does not use libvirt on the client side, not all connection URI options are supported or apply. + +## Example Usage + +```hcl +# Configure the OpenStack Provider +provider "simple-provider" { + user_name = "admin" + tenant_name = "admin" + password = "pwd" + auth_url = "http://myauthurl:5000/v3" + region = "RegionOne" +} +## Define a resource +resource "simple_resource" "a_resource" { + input_one = "hello" + input_two = true +} +``` + +## Configuration Reference + +The following keys can be used to configure the provider. + +* `uri` - (Required) The [connection URI](https://libvirt.org/uri.html) used + to connect to the libvirt host. + +## Environment variables + +The libvirt connection URI can also be specified with the `LIBVIRT_DEFAULT_URI` +shell environment variable. + +``` +$ export LIBVIRT_DEFAULT_URI="qemu+ssh://root@192.168.1.100/system" +$ terraform plan +``` \ No newline at end of file diff --git a/pkg/tfgen/test_data/replace-links/actual.md b/pkg/tfgen/test_data/replace-links/expected.md similarity index 100% rename from pkg/tfgen/test_data/replace-links/actual.md rename to pkg/tfgen/test_data/replace-links/expected.md diff --git a/pkg/tfgen/test_data/replace-terraform-version/input.md b/pkg/tfgen/test_data/replace-terraform-version/input.md index f96aef06a..07df35c9d 100644 --- a/pkg/tfgen/test_data/replace-terraform-version/input.md +++ b/pkg/tfgen/test_data/replace-terraform-version/input.md @@ -12,5 +12,5 @@ which may be consumed to better understand the behavior of the API. Use the navigation to the left to read about the valid data sources and resources. -This provider requires at least [Terraform 1.0](https://www.terraform.io/downloads.html). +This provider requires at least Terraform 1.0. A minimum of Terraform 1.4.0 is recommended. diff --git a/pkg/tfgen/test_data/skip-sections-by-header/actual.md b/pkg/tfgen/test_data/skip-sections-by-header/expected.md similarity index 100% rename from pkg/tfgen/test_data/skip-sections-by-header/actual.md rename to pkg/tfgen/test_data/skip-sections-by-header/expected.md