Skip to content

Commit 99938e1

Browse files
Add automated install instructions to top of installation-configuration.md. (#2207)
This PR adds an "Installation" section to the configuration docs, generating content dynamically from the package info. Fixes #2206.
2 parents 45e5bcc + 453fc8b commit 99938e1

File tree

4 files changed

+231
-84
lines changed

4 files changed

+231
-84
lines changed

pkg/tfgen/docs.go

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2272,47 +2272,3 @@ var (
22722272
func guessIsHCL(code string) bool {
22732273
return guessIsHCLPattern.MatchString(code)
22742274
}
2275-
2276-
func plainDocsParser(docFile *DocFile, g *Generator) ([]byte, error) {
2277-
// Get file content without front matter, and split title
2278-
contentStr, title := getBodyAndTitle(string(docFile.Content))
2279-
// Add pulumi-specific front matter
2280-
contentStr = writeFrontMatter(title) + contentStr
2281-
2282-
//TODO: See https://github.com/pulumi/pulumi-terraform-bridge/issues/2078
2283-
// - translate code blocks with code choosers
2284-
// - apply default edit rules
2285-
// - reformat TF names
2286-
// - Translation for certain headers such as "Arguments Reference" or "Configuration block"
2287-
// - Ability to omit irrelevant sections
2288-
return []byte(contentStr), nil
2289-
}
2290-
2291-
func writeFrontMatter(title string) string {
2292-
return fmt.Sprintf(delimiter+
2293-
"title: %s Installation & Configuration\n"+
2294-
"meta_desc: Provides an overview on how to configure the Pulumi %s.\n"+
2295-
"layout: package\n"+
2296-
delimiter,
2297-
title, title)
2298-
}
2299-
2300-
func writeIndexFrontMatter(displayName string) string {
2301-
return fmt.Sprintf(delimiter+
2302-
"title: %s\n"+
2303-
"meta_desc: The %s provider for Pulumi can be used to provision any of the cloud resources available in %s.\n"+
2304-
"layout: package\n"+
2305-
delimiter,
2306-
displayName, displayName, displayName)
2307-
}
2308-
2309-
func getBodyAndTitle(content string) (string, string) {
2310-
// The first header in `index.md` is the package name, of the format `# Foo Provider`.
2311-
titleIndex := strings.Index(content, "# ")
2312-
// Get the location fo the next newline
2313-
nextNewLine := strings.Index(content[titleIndex:], "\n") + titleIndex
2314-
// Get the title line, without the h1 anchor
2315-
title := content[titleIndex+2 : nextNewLine]
2316-
// strip the title and any front matter
2317-
return content[nextNewLine+1:], title
2318-
}

pkg/tfgen/docs_test.go

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1934,43 +1934,3 @@ resource "aws_ami" "example" {
19341934
})
19351935
}
19361936
}
1937-
1938-
func TestPlainDocsParser(t *testing.T) {
1939-
t.Parallel()
1940-
1941-
type testCase struct {
1942-
// The name of the test case.
1943-
name string
1944-
docFile DocFile
1945-
expected []byte
1946-
}
1947-
1948-
tests := []testCase{
1949-
{
1950-
name: "Replaces Upstream Front Matter With Pulumi Front Matter",
1951-
docFile: DocFile{
1952-
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."),
1953-
},
1954-
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."),
1955-
},
1956-
{
1957-
name: "Writes Pulumi Style Front Matter If Not Present",
1958-
docFile: DocFile{
1959-
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."),
1960-
},
1961-
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."),
1962-
},
1963-
}
1964-
for _, tt := range tests {
1965-
tt := tt
1966-
t.Run(tt.name, func(t *testing.T) {
1967-
t.Parallel()
1968-
g := &Generator{
1969-
sink: mockSink{t},
1970-
}
1971-
actual, err := plainDocsParser(&tt.docFile, g)
1972-
require.NoError(t, err)
1973-
require.Equal(t, string(tt.expected), string(actual))
1974-
})
1975-
}
1976-
}

pkg/tfgen/installation_docs.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package tfgen
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
7+
"golang.org/x/text/cases"
8+
"golang.org/x/text/language"
9+
)
10+
11+
func plainDocsParser(docFile *DocFile, g *Generator) ([]byte, error) {
12+
// Get file content without front matter, and split title
13+
contentStr, title := getBodyAndTitle(string(docFile.Content))
14+
// Add pulumi-specific front matter
15+
// Generate pulumi-specific front matter
16+
frontMatter := writeFrontMatter(title)
17+
18+
// Generate pulumi-specific installation instructions
19+
installationInstructions := writeInstallationInstructions(g.info.Golang.ImportBasePath, g.info.Name)
20+
21+
// Add instructions to top of file
22+
contentStr = frontMatter + installationInstructions + contentStr
23+
24+
//TODO: See https://github.com/pulumi/pulumi-terraform-bridge/issues/2078
25+
// - translate code blocks with code choosers
26+
// - apply default edit rules
27+
// - reformat TF names
28+
// - Translation for certain headers such as "Arguments Reference" or "Configuration block"
29+
// - Ability to omit irrelevant sections
30+
return []byte(contentStr), nil
31+
}
32+
33+
func writeFrontMatter(title string) string {
34+
return fmt.Sprintf(delimiter+
35+
"title: %[1]s Installation & Configuration\n"+
36+
"meta_desc: Provides an overview on how to configure the Pulumi %[1]s.\n"+
37+
"layout: package\n"+
38+
delimiter+
39+
"\n",
40+
title)
41+
}
42+
43+
func writeIndexFrontMatter(displayName string) string {
44+
return fmt.Sprintf(delimiter+
45+
"title: %[1]s\n"+
46+
"meta_desc: The %[1]s provider for Pulumi "+
47+
"can be used to provision any of the cloud resources available in %[1]s.\n"+
48+
"layout: package\n"+
49+
delimiter,
50+
displayName)
51+
}
52+
53+
func getBodyAndTitle(content string) (string, string) {
54+
// The first header in `index.md` is the package name, of the format `# Foo Provider`.
55+
titleIndex := strings.Index(content, "# ")
56+
// Get the location fo the next newline
57+
nextNewLine := strings.Index(content[titleIndex:], "\n") + titleIndex
58+
// Get the title line, without the h1 anchor
59+
title := content[titleIndex+2 : nextNewLine]
60+
// strip the title and any front matter
61+
return content[nextNewLine+1:], title
62+
}
63+
64+
// writeInstallationInstructions renders the following for any provider:
65+
// ****
66+
// Installation
67+
// The Foo provider is available as a package in all Pulumi languages:
68+
//
69+
// JavaScript/TypeScript: @pulumi/foo
70+
// Python: pulumi-foo
71+
// Go: github.com/pulumi/pulumi-foo/sdk/v3/go/foo
72+
// .NET: Pulumi.foo
73+
// Java: com.pulumi/foo
74+
// ****
75+
func writeInstallationInstructions(goImportBasePath, providerName string) string {
76+
77+
// Capitalize the package name for C#
78+
capitalize := cases.Title(language.English)
79+
cSharpName := capitalize.String(providerName)
80+
81+
return fmt.Sprintf(
82+
"## Installation\n\n"+
83+
"The %[1]s provider is available as a package in all Pulumi languages:\n\n"+
84+
"* JavaScript/TypeScript: [`@pulumi/%[1]s`](https://www.npmjs.com/package/@pulumi/%[1]s)\n"+
85+
"* Python: [`pulumi-%[1]s`](https://pypi.org/project/pulumi-%[1]s/)\n"+
86+
"* Go: [`%[3]s`](https://github.com/pulumi/pulumi-%[1]s)\n"+
87+
"* .NET: [`Pulumi.%[2]s`](https://www.nuget.org/packages/Pulumi.%[2]s)\n"+
88+
"* Java: [`com.pulumi/%[1]s`](https://central.sonatype.com/artifact/com.pulumi/%[1]s)\n\n",
89+
providerName,
90+
cSharpName,
91+
goImportBasePath,
92+
)
93+
}
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
package tfgen
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/require"
7+
)
8+
9+
//nolint:lll
10+
func TestPlainDocsParser(t *testing.T) {
11+
t.Parallel()
12+
13+
type testCase struct {
14+
// The name of the test case.
15+
name string
16+
docFile DocFile
17+
expected []byte
18+
}
19+
20+
tests := []testCase{
21+
{
22+
name: "Replaces Upstream Front Matter With Pulumi Front Matter",
23+
docFile: DocFile{
24+
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."),
25+
},
26+
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."),
27+
},
28+
{
29+
name: "Writes Pulumi Style Front Matter If Not Present",
30+
docFile: DocFile{
31+
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."),
32+
},
33+
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."),
34+
},
35+
}
36+
for _, tt := range tests {
37+
tt := tt
38+
t.Run(tt.name, func(t *testing.T) {
39+
t.Skipf("this function is under development and will receive tests once all parts are completed")
40+
t.Parallel()
41+
g := &Generator{
42+
sink: mockSink{t},
43+
}
44+
actual, err := plainDocsParser(&tt.docFile, g)
45+
require.NoError(t, err)
46+
require.Equal(t, string(tt.expected), string(actual))
47+
})
48+
}
49+
}
50+
51+
//nolint:lll
52+
func TestWriteInstallationInstructions(t *testing.T) {
53+
t.Parallel()
54+
55+
type testCase struct {
56+
// The name of the test case.
57+
name string
58+
goImportBasePath string
59+
packageName string
60+
expected string
61+
}
62+
63+
tc := testCase{
64+
65+
name: "Generates Install Information From Package Name",
66+
expected: "## Installation\n\n" +
67+
"The testcase provider is available as a package in all Pulumi languages:\n\n" +
68+
"* JavaScript/TypeScript: [`@pulumi/testcase`](https://www.npmjs.com/package/@pulumi/testcase)\n" +
69+
"* Python: [`pulumi-testcase`](https://pypi.org/project/pulumi-testcase/)\n" +
70+
"* Go: [`github.com/pulumi/pulumi-testcase/sdk/v3/go/pulumi-testcase`](https://github.com/pulumi/pulumi-testcase)\n" +
71+
"* .NET: [`Pulumi.Testcase`](https://www.nuget.org/packages/Pulumi.Testcase)\n" +
72+
"* Java: [`com.pulumi/testcase`](https://central.sonatype.com/artifact/com.pulumi/testcase)\n\n",
73+
goImportBasePath: "github.com/pulumi/pulumi-testcase/sdk/v3/go/pulumi-testcase",
74+
packageName: "testcase",
75+
}
76+
77+
t.Run(tc.name, func(t *testing.T) {
78+
t.Parallel()
79+
actual := writeInstallationInstructions(tc.goImportBasePath, tc.packageName)
80+
require.Equal(t, tc.expected, actual)
81+
})
82+
}
83+
84+
func TestWriteFrontMatter(t *testing.T) {
85+
t.Parallel()
86+
87+
type testCase struct {
88+
// The name of the test case.
89+
name string
90+
title string
91+
expected string
92+
}
93+
94+
tc := testCase{
95+
name: "Generates Front Matter for installation-configuration.md",
96+
title: "Testcase Provider",
97+
expected: delimiter +
98+
"title: Testcase Provider Installation & Configuration\n" +
99+
"meta_desc: Provides an overview on how to configure the Pulumi Testcase Provider.\n" +
100+
"layout: package\n" +
101+
delimiter +
102+
"\n",
103+
}
104+
105+
t.Run(tc.name, func(t *testing.T) {
106+
t.Parallel()
107+
actual := writeFrontMatter(tc.title)
108+
require.Equal(t, tc.expected, actual)
109+
})
110+
}
111+
112+
func TestWriteIndexFrontMatter(t *testing.T) {
113+
t.Parallel()
114+
115+
type testCase struct {
116+
// The name of the test case.
117+
name string
118+
displayName string
119+
expected string
120+
}
121+
122+
tc := testCase{
123+
name: "Generates Front Matter for _index.md",
124+
displayName: "Testcase",
125+
expected: delimiter +
126+
"title: Testcase\n" +
127+
"meta_desc: The Testcase provider for Pulumi " +
128+
"can be used to provision any of the cloud resources available in Testcase.\n" +
129+
"layout: package\n" +
130+
delimiter,
131+
}
132+
133+
t.Run(tc.name, func(t *testing.T) {
134+
t.Parallel()
135+
actual := writeIndexFrontMatter(tc.displayName)
136+
require.Equal(t, tc.expected, actual)
137+
})
138+
}

0 commit comments

Comments
 (0)