diff --git a/README.md b/README.md index 821d1da8..e206a4b1 100644 --- a/README.md +++ b/README.md @@ -233,7 +233,7 @@ For examples: |------------------------------------------------------------------------------|--------------------------------------------| | `examples/` | Root of examples | | `examples/provider/provider<*>.tf` | Provider example config(s) | -| `examples/actions//action.tf` | Action example config | +| `examples/actions//action<*>.tf` | Action example config(s) | | `examples/data-sources//data-source<*>.tf` | Data source example config(s) | | `examples/ephemeral-resources//ephemeral-resource<*>.tf` | Ephemeral resource example config(s) | | `examples/functions//function<*>.tf` | Function example config(s) | @@ -356,8 +356,10 @@ using the following data fields and functions: | `.Name` | string | Name of the action (ex. `examplecloud_do_thing`) | | `.Type` | string | `Action` | | `.Description` | string | Action description | -| `.HasExample` | bool | Is there an example file? | -| `.ExampleFile` | string | Path to the file with the terraform configuration example | +| `.HasExample` | bool | (Legacy) Is there an example file? | +| `.HasExamples` | bool | Are there example files? Always true if HasExample is true. | +| `.ExampleFile` | string | (Legacy) Path to the file with the Terraform configuration example. | +| `.ExampleFiles` | string | Paths to the files with Terraform configuration examples. Includes ExampleFile. | | `.ProviderName` | string | Canonical provider name (ex. `terraform-provider-random`) | | `.ProviderShortName` | string | Short version of the rendered provider name (ex. `random`) | | `.RenderedProviderName` | string | Value provided via argument `--rendered-provider-name`, otherwise same as `.ProviderName` | diff --git a/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_no_templates_multiple_examples.txtar b/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_no_templates_multiple_examples.txtar index 6157b614..993028e6 100644 --- a/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_no_templates_multiple_examples.txtar +++ b/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_no_templates_multiple_examples.txtar @@ -6,6 +6,7 @@ exec tfplugindocs --provider-name=terraform-provider-scaffolding --providers-schema=schema.json --rendered-provider-name=Scaffolding cmp stdout expected-output.txt cmp docs/index.md expected-index.md +cmp docs/actions/example.md expected-action.md cmp docs/data-sources/example.md expected-datasource.md cmp docs/resources/example.md expected-resource.md cmp docs/functions/example.md expected-function.md @@ -27,18 +28,61 @@ generating new template for function "no-variadic" generating missing ephemeral resource content generating new template for "scaffolding_example" generating missing action content +generating new template for "scaffolding_example" generating missing list resource content generating missing provider content generating new template for "terraform-provider-scaffolding" rendering static website cleaning rendered website dir rendering templated website to static markdown +rendering "actions/example.md.tmpl" rendering "data-sources/example.md.tmpl" rendering "ephemeral-resources/example.md.tmpl" rendering "functions/example.md.tmpl" rendering "functions/no-variadic.md.tmpl" rendering "index.md.tmpl" rendering "resources/example.md.tmpl" +-- expected-action.md -- +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "scaffolding_example Action - Scaffolding" +subcategory: "" +description: |- + Example action +--- + +# scaffolding_example (Action) + +Example action + +## Example Usage + +```terraform +action "scaffolding_example" "example" { + config { + required_attr = "some-value-1" + } +} +``` + +```terraform +action "scaffolding_example" "example" { + config { + required_attr = "some-value-2" + } +} +``` + + +## Schema + +### Required + +- `required_attr` (String) Example required attribute + +### Optional + +- `optional_attr` (String) Example optional attribute -- expected-datasource.md -- --- # generated by https://github.com/hashicorp/terraform-plugin-docs @@ -318,6 +362,18 @@ The document generation tool looks for files in the following locations by defau * **provider/provider.tf** example file for the provider index page * **data-sources/`full data source name`/data-source.tf** example file for the named data source page * **resources/`full resource name`/resource.tf** example file for the named data source page +-- examples/actions/scaffolding_example/action.tf -- +action "scaffolding_example" "example" { + config { + required_attr = "some-value-1" + } +} +-- examples/actions/scaffolding_example/action2.tf -- +action "scaffolding_example" "example" { + config { + required_attr = "some-value-2" + } +} -- examples/data-sources/scaffolding_example/data-source.tf -- data "scaffolding_example" "example" { configurable_attribute = "some-value1" @@ -408,6 +464,29 @@ resource "scaffolding_example" "example" { "description_kind": "markdown" } }, + "action_schemas": { + "scaffolding_example": { + "version": 0, + "block": { + "attributes": { + "required_attr": { + "type": "string", + "description": "Example required attribute", + "description_kind": "plain", + "required": true + }, + "optional_attr": { + "type": "string", + "description": "Example optional attribute", + "description_kind": "plain", + "optional": true + } + }, + "description": "Example action", + "description_kind": "plain" + } + } + }, "resource_schemas": { "scaffolding_example": { "version": 0, diff --git a/internal/provider/action_template.go b/internal/provider/action_template.go index 00a0965f..a0ca1eb7 100644 --- a/internal/provider/action_template.go +++ b/internal/provider/action_template.go @@ -14,7 +14,25 @@ const actionSchemaComment = "" type actionTemplate string -func (t actionTemplate) Render(providerDir, name, providerName, renderedProviderName, typeName, exampleFile string, schema *tfjson.ActionSchema) (string, error) { +type ActionTemplateType struct { + Type string + Name string + Description string + + HasExample bool + HasExamples bool + ExampleFile string + ExampleFiles []string + + ProviderName string + ProviderShortName string + + SchemaMarkdown string + + RenderedProviderName string +} + +func (t actionTemplate) Render(providerDir, name, providerName, renderedProviderName, typeName, exampleFile string, exampleFiles []string, schema *tfjson.ActionSchema) (string, error) { schemaBuffer := bytes.NewBuffer(nil) err := schemamd.RenderAction(schema, schemaBuffer) if err != nil { @@ -26,27 +44,15 @@ func (t actionTemplate) Render(providerDir, name, providerName, renderedProvider return "", nil } - return renderStringTemplate(providerDir, "actionTemplate", s, struct { - Type string - Name string - Description string - - HasExample bool - ExampleFile string - - ProviderName string - ProviderShortName string - - SchemaMarkdown string - - RenderedProviderName string - }{ + return renderStringTemplate(providerDir, "actionTemplate", s, ActionTemplateType{ Type: typeName, Name: name, Description: schema.Block.Description, - HasExample: exampleFile != "" && fileExists(exampleFile), - ExampleFile: exampleFile, + HasExample: exampleFile != "" && fileExists(exampleFile), + HasExamples: len(exampleFiles) > 0, + ExampleFile: exampleFile, + ExampleFiles: exampleFiles, ProviderName: providerName, ProviderShortName: providerShortName(renderedProviderName), @@ -69,10 +75,13 @@ description: |- {{ .Description | trimspace }} -{{ if .HasExample -}} +{{ if .HasExamples -}} ## Example Usage -{{tffile .ExampleFile }} +{{- range .ExampleFiles }} + +{{ tffile . }} +{{- end }} {{- end }} {{ .SchemaMarkdown | trimspace }} diff --git a/internal/provider/action_template_test.go b/internal/provider/action_template_test.go index 14ad2e5d..7eb3c7e9 100644 --- a/internal/provider/action_template_test.go +++ b/internal/provider/action_template_test.go @@ -49,7 +49,7 @@ action "scaffolding_example" "example1" { }, } - result, err := tpl.Render("testdata/test-action-dir", "testTemplate", "test-action", "test-action", "action", "action.tf", &schema) + result, err := tpl.Render("testdata/test-action-dir", "testTemplate", "test-action", "test-action", "action", "action.tf", []string{"action.tf"}, &schema) if err != nil { t.Error(err) } diff --git a/internal/provider/generate.go b/internal/provider/generate.go index 1984bbf5..b7b72d8d 100644 --- a/internal/provider/generate.go +++ b/internal/provider/generate.go @@ -868,11 +868,20 @@ func (g *generator) renderStaticWebsite(providerSchema *tfjson.ProviderSchema) e g.warnf("ephemeral resource entitled %q, or %q does not exist", shortName, resName) case "actions/": actionSchema, resName := actionSchema(providerSchema.ActionSchemas, shortName, relFile) - exampleFilePath := filepath.Join(g.ProviderExamplesDir(), "actions", resName, "action.tf") if actionSchema != nil { + exampleFilePath := filepath.Join(g.ProviderExamplesDir(), "actions", resName, "action.tf") + exampleFilesPattern := filepath.Join(g.ProviderExamplesDir(), "actions", resName, "action*.tf") + exampleFiles, err := filepath.Glob(exampleFilesPattern) + + if err != nil { + return fmt.Errorf("unable to glob example files with pattern %q: %w", exampleFilesPattern, err) + } + + slices.Sort(exampleFiles) + tmpl := actionTemplate(tmplData) - render, err := tmpl.Render(g.providerDir, resName, g.providerName, g.renderedProviderName, "Action", exampleFilePath, actionSchema) + render, err := tmpl.Render(g.providerDir, resName, g.providerName, g.renderedProviderName, "Action", exampleFilePath, exampleFiles, actionSchema) if err != nil { return fmt.Errorf("unable to render action template %q: %w", rel, err) }