mirror of
https://github.com/terraform-docs/terraform-docs.git
synced 2026-03-27 04:48:33 +07:00
Merge pull request #573 from khos2ow/plugin-in-tree
Move plugin-sdk to in-tree in core repository
This commit is contained in:
80
README.md
80
README.md
@@ -253,6 +253,14 @@ when formatter is set to `markdown table`.
|
||||
Note that sections visibility (i.e. `sections.show` and `sections.hide`) takes
|
||||
precedence over the `content`.
|
||||
|
||||
Additionally there's also one extra special variable avaialble to the `content`:
|
||||
|
||||
- `{{ .Module }}`
|
||||
|
||||
As opposed to the other variables mentioned above, which are generated sections
|
||||
based on a selected formatter, the `{{ .Module }}` variable is just a `struct`
|
||||
representing a [Terraform module].
|
||||
|
||||
````yaml
|
||||
content: |-
|
||||
Any arbitrary text can be placed anywhere in the content
|
||||
@@ -278,6 +286,12 @@ content: |-
|
||||
```hcl
|
||||
{{ include "examples/foo/main.tf" }}
|
||||
```
|
||||
|
||||
## Resources
|
||||
|
||||
{{ range .Module.Resources }}
|
||||
- {{ .GetMode }}.{{ .Spec }} ({{ .Position.Filename }}#{{ .Position.Line }})
|
||||
{{- end }}
|
||||
````
|
||||
|
||||
## Build on top of terraform-docs
|
||||
@@ -320,6 +334,68 @@ func buildTerraformDocs(path string, tmpl string) (string, error) {
|
||||
}
|
||||
```
|
||||
|
||||
## Plugin
|
||||
|
||||
Generated output can be heavily customized with [`content`], but if using that
|
||||
is not enough for your use-case, you can write your own plugin.
|
||||
|
||||
In order to install a plugin the following steps are needed:
|
||||
|
||||
- download the plugin and place it in `~/.tfdocs.d/plugins` (or `./.tfdocs.d/plugins`)
|
||||
- make sure the plugin file name is `tfdocs-format-<NAME>`
|
||||
- modify [`formatter`] of `.terraform-docs.yml` file to be `<NAME>`
|
||||
|
||||
**Important notes:**
|
||||
|
||||
- if the plugin file name is different than the example above, terraform-docs won't
|
||||
be able to to pick it up nor register it properly
|
||||
- you can only use plugin thorough `.terraform-docs.yml` file and it cannot be used
|
||||
with CLI arguments
|
||||
|
||||
To create a new plugin create a new repository called `tfdocs-format-<NAME>` with
|
||||
following `main.go`:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
_ "embed" //nolint
|
||||
|
||||
"github.com/terraform-docs/terraform-docs/plugin"
|
||||
"github.com/terraform-docs/terraform-docs/print"
|
||||
"github.com/terraform-docs/terraform-docs/template"
|
||||
"github.com/terraform-docs/terraform-docs/terraform"
|
||||
)
|
||||
|
||||
func main() {
|
||||
plugin.Serve(&plugin.ServeOpts{
|
||||
Name: "<NAME>",
|
||||
Version: "0.1.0",
|
||||
Printer: printerFunc,
|
||||
})
|
||||
}
|
||||
|
||||
//go:embed sections.tmpl
|
||||
var tplCustom []byte
|
||||
|
||||
// printerFunc the function being executed by the plugin client.
|
||||
func printerFunc(config *print.Config, module *terraform.Module) (string, error) {
|
||||
tpl := template.New(config,
|
||||
&template.Item{Name: "custom", Text: string(tplCustom)},
|
||||
)
|
||||
|
||||
rendered, err := tpl.Render("custom", module)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return rendered, nil
|
||||
}
|
||||
```
|
||||
|
||||
Please refer to [tfdocs-format-template] for more details. You can create a new
|
||||
repository from it by clicking on `Use this template` button.
|
||||
|
||||
## Documentation
|
||||
|
||||
- **Users**
|
||||
@@ -341,8 +417,10 @@ MIT License - Copyright (c) 2021 The terraform-docs Authors.
|
||||
|
||||
[Chocolatey]: https://www.chocolatey.org
|
||||
[Config File Reference]: https://terraform-docs.io/user-guide/configuration/
|
||||
[`content`]: https://terraform-docs.io/user-guide/configuration/content/
|
||||
[Contributing Guide]: CONTRIBUTING.md
|
||||
[Formats Guide]: https://terraform-docs.io/reference/terraform-docs/
|
||||
[`formatter`]: https://terraform-docs.io/user-guide/configuration/formatter/
|
||||
[here]: https://golang.org/doc/code.html#GOPATH
|
||||
[Homebrew]: https://brew.sh
|
||||
[install pre-commit]: https://pre-commit.com/#install
|
||||
@@ -351,5 +429,7 @@ MIT License - Copyright (c) 2021 The terraform-docs Authors.
|
||||
[Scoop]: https://scoop.sh/
|
||||
[Slack]: https://slack.terraform-docs.io/
|
||||
[terraform-docs GitHub Action]: https://github.com/terraform-docs/gh-actions
|
||||
[Terraform module]: https://pkg.go.dev/github.com/terraform-docs/terraform-docs/terraform#Module
|
||||
[tfdocs-format-template]: https://github.com/terraform-docs/tfdocs-format-template
|
||||
[our website]: https://terraform-docs.io/
|
||||
[User Guide]: https://terraform-docs.io/user-guide/introduction/
|
||||
|
||||
@@ -8,13 +8,66 @@ weight: 310
|
||||
toc: false
|
||||
---
|
||||
|
||||
If you want to add or change formatter, you need to write plugins. When changing
|
||||
plugins, refer to the repository of each plugin and refer to how to build and
|
||||
install.
|
||||
Generated output can be heavily customized with [`content`], but if using that
|
||||
is not enough for your use-case, you can write your own plugin.
|
||||
|
||||
If you want to create a new plugin, please refer to [tfdocs-format-template]. The
|
||||
plugin can use [plugin-sdk] to communicate with the host process. You can create a
|
||||
new repository from `Use this template`.
|
||||
In order to install a plugin the following steps are needed:
|
||||
|
||||
[plugin-sdk]: https://github.com/terraform-docs/plugin-sdk
|
||||
- download the plugin and place it in `~/.tfdocs.d/plugins` (or `./.tfdocs.d/plugins`)
|
||||
- make sure the plugin file name is `tfdocs-format-<NAME>`
|
||||
- modify [`formatter`] of `.terraform-docs.yml` file to be `<NAME>`
|
||||
|
||||
**Important notes:**
|
||||
|
||||
- if the plugin file name is different than the example above, terraform-docs won't
|
||||
be able to to pick it up nor register it properly
|
||||
- you can only use plugin thorough `.terraform-docs.yml` file and it cannot be used
|
||||
with CLI arguments
|
||||
|
||||
To create a new plugin create a new repository called `tfdocs-format-<NAME>` with
|
||||
following `main.go`:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
_ "embed" //nolint
|
||||
|
||||
"github.com/terraform-docs/terraform-docs/plugin"
|
||||
"github.com/terraform-docs/terraform-docs/print"
|
||||
"github.com/terraform-docs/terraform-docs/template"
|
||||
"github.com/terraform-docs/terraform-docs/terraform"
|
||||
)
|
||||
|
||||
func main() {
|
||||
plugin.Serve(&plugin.ServeOpts{
|
||||
Name: "<NAME>",
|
||||
Version: "0.1.0",
|
||||
Printer: printerFunc,
|
||||
})
|
||||
}
|
||||
|
||||
//go:embed sections.tmpl
|
||||
var tplCustom []byte
|
||||
|
||||
// printerFunc the function being executed by the plugin client.
|
||||
func printerFunc(config *print.Config, module *terraform.Module) (string, error) {
|
||||
tpl := template.New(config,
|
||||
&template.Item{Name: "custom", Text: string(tplCustom)},
|
||||
)
|
||||
|
||||
rendered, err := tpl.Render("custom", module)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return rendered, nil
|
||||
}
|
||||
```
|
||||
|
||||
Please refer to [tfdocs-format-template] for more details. You can create a new
|
||||
repository from it by clicking on `Use this template` button.
|
||||
|
||||
[`content`]: {{< ref "content" >}}
|
||||
[`formatter`]: {{< ref "formatter" >}}
|
||||
[tfdocs-format-template]: https://github.com/terraform-docs/tfdocs-format-template
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
# version: ">= 0.10, < 0.12"
|
||||
|
||||
# see: https://terraform-docs.io/user-guide/configuration/formatter
|
||||
formatter: markdown table
|
||||
# formatter: markdown table
|
||||
formatter: template
|
||||
|
||||
# see: https://terraform-docs.io/user-guide/configuration/header-from
|
||||
header-from: doc.txt
|
||||
|
||||
2
go.mod
2
go.mod
@@ -5,6 +5,7 @@ go 1.16
|
||||
require (
|
||||
github.com/BurntSushi/toml v0.3.1
|
||||
github.com/Masterminds/sprig/v3 v3.2.2
|
||||
github.com/hashicorp/go-hclog v0.15.0
|
||||
github.com/hashicorp/go-plugin v1.4.2
|
||||
github.com/hashicorp/go-version v1.3.0
|
||||
github.com/hashicorp/hcl/v2 v2.10.1
|
||||
@@ -15,7 +16,6 @@ require (
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/spf13/viper v1.8.1
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/terraform-docs/plugin-sdk v0.3.1-0.20210825180722-c52e9860f575
|
||||
github.com/terraform-docs/terraform-config-inspect v0.0.0-20210728164355-9c1f178932fa
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||
honnef.co/go/tools v0.2.0
|
||||
|
||||
4
go.sum
4
go.sum
@@ -172,7 +172,6 @@ github.com/hashicorp/go-hclog v0.15.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/hashicorp/go-plugin v1.4.0/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ38b18Udy6vYQ=
|
||||
github.com/hashicorp/go-plugin v1.4.2 h1:yFvG3ufXXpqiMiZx9HLcaK3XbIqQ1WJFR/F1a2CuVw0=
|
||||
github.com/hashicorp/go-plugin v1.4.2/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ38b18Udy6vYQ=
|
||||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||
@@ -310,8 +309,6 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/terraform-docs/plugin-sdk v0.3.1-0.20210825180722-c52e9860f575 h1:pwOvvonyymFBE2YE5Yx1M236lH4WT9i8sgVYC4KMsgE=
|
||||
github.com/terraform-docs/plugin-sdk v0.3.1-0.20210825180722-c52e9860f575/go.mod h1:3G+0nZTeaMF1c5CZh8cOEYeNq0kUL6+DlQOVcxK7eCQ=
|
||||
github.com/terraform-docs/terraform-config-inspect v0.0.0-20210728164355-9c1f178932fa h1:wdyf3TobwYFwsqnUGJcjdNHxKfwHPFbaOknBJehnF1M=
|
||||
github.com/terraform-docs/terraform-config-inspect v0.0.0-20210728164355-9c1f178932fa/go.mod h1:GtanFwTsRRXScYHOMb5h4K18XQBFeS2tXat9/LrPtPc=
|
||||
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
|
||||
@@ -691,7 +688,6 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.1.2/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
|
||||
honnef.co/go/tools v0.2.0 h1:ws8AfbgTX3oIczLPNPCu5166oBg9ST2vNs0rcht+mDE=
|
||||
honnef.co/go/tools v0.2.0/go.mod h1:lPVVZ2BS5TfnjLyizF7o7hv7j9/L+8cZY2hLyjP9cGY=
|
||||
mvdan.cc/xurls/v2 v2.3.0 h1:59Olnbt67UKpxF1EwVBopJvkSUBmgtb468E4GVWIZ1I=
|
||||
|
||||
@@ -22,10 +22,10 @@ import (
|
||||
"github.com/spf13/pflag"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
pluginsdk "github.com/terraform-docs/plugin-sdk/plugin"
|
||||
"github.com/terraform-docs/terraform-docs/format"
|
||||
"github.com/terraform-docs/terraform-docs/internal/plugin"
|
||||
"github.com/terraform-docs/terraform-docs/internal/version"
|
||||
pluginsdk "github.com/terraform-docs/terraform-docs/plugin"
|
||||
"github.com/terraform-docs/terraform-docs/print"
|
||||
"github.com/terraform-docs/terraform-docs/terraform"
|
||||
)
|
||||
@@ -344,9 +344,9 @@ func generateContent(config *print.Config) error {
|
||||
return fmt.Errorf("formatter '%s' not found", config.Formatter)
|
||||
}
|
||||
|
||||
content, cerr := client.Execute(pluginsdk.ExecuteArgs{
|
||||
Module: module.Convert(),
|
||||
Settings: nil, // TODO settings.Convert(),
|
||||
content, cerr := client.Execute(&pluginsdk.ExecuteArgs{
|
||||
Module: module,
|
||||
Config: config,
|
||||
})
|
||||
if cerr != nil {
|
||||
return cerr
|
||||
|
||||
@@ -22,7 +22,7 @@ import (
|
||||
goplugin "github.com/hashicorp/go-plugin"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
|
||||
pluginsdk "github.com/terraform-docs/plugin-sdk/plugin"
|
||||
pluginsdk "github.com/terraform-docs/terraform-docs/plugin"
|
||||
)
|
||||
|
||||
// Discover plugins and registers them. The lookup priority of plugins is as
|
||||
|
||||
@@ -13,7 +13,7 @@ package plugin
|
||||
import (
|
||||
goplugin "github.com/hashicorp/go-plugin"
|
||||
|
||||
pluginsdk "github.com/terraform-docs/plugin-sdk/plugin"
|
||||
pluginsdk "github.com/terraform-docs/terraform-docs/plugin"
|
||||
)
|
||||
|
||||
// namePrefix is the mandatory prefix for name of the plugin file. What
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"go/types"
|
||||
"reflect"
|
||||
"sort"
|
||||
)
|
||||
@@ -94,7 +93,7 @@ func TypeOf(t string, v interface{}) String {
|
||||
}
|
||||
|
||||
// Nil represents a 'nil' value which is marshaled to `null` when empty for JSON and YAML
|
||||
type Nil types.Nil
|
||||
type Nil struct{}
|
||||
|
||||
// HasDefault return false for Nil, because there's no value set for the variable
|
||||
func (n Nil) HasDefault() bool {
|
||||
|
||||
84
plugin/client.go
Normal file
84
plugin/client.go
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
Copyright 2021 The terraform-docs Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"net/rpc"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/hashicorp/go-hclog"
|
||||
goplugin "github.com/hashicorp/go-plugin"
|
||||
|
||||
"github.com/terraform-docs/terraform-docs/print"
|
||||
"github.com/terraform-docs/terraform-docs/terraform"
|
||||
)
|
||||
|
||||
// Client is an RPC Client for the host.
|
||||
type Client struct {
|
||||
rpcClient *rpc.Client
|
||||
broker *goplugin.MuxBroker
|
||||
}
|
||||
|
||||
// ClientOpts is an option for initializing a Client.
|
||||
type ClientOpts struct {
|
||||
Cmd *exec.Cmd
|
||||
}
|
||||
|
||||
// ExecuteArgs is the collection of arguments being sent by terraform-docs
|
||||
// core while executing the plugin command.
|
||||
type ExecuteArgs struct {
|
||||
Module *terraform.Module
|
||||
Config *print.Config
|
||||
}
|
||||
|
||||
// NewClient is a wrapper of plugin.NewClient.
|
||||
func NewClient(opts *ClientOpts) *goplugin.Client {
|
||||
return goplugin.NewClient(&goplugin.ClientConfig{
|
||||
HandshakeConfig: handshakeConfig,
|
||||
Plugins: map[string]goplugin.Plugin{
|
||||
"formatter": &formatter{},
|
||||
},
|
||||
Cmd: opts.Cmd,
|
||||
Logger: hclog.New(&hclog.LoggerOptions{
|
||||
Name: "plugin",
|
||||
Output: os.Stderr,
|
||||
Level: hclog.LevelFromString(os.Getenv("TFDOCS_LOG")),
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
// Name calls the server-side Name method and returns its version.
|
||||
func (c *Client) Name() (string, error) {
|
||||
var resp string
|
||||
err := c.rpcClient.Call("Plugin.Name", new(interface{}), &resp)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// Version calls the server-side Version method and returns its version.
|
||||
func (c *Client) Version() (string, error) {
|
||||
var resp string
|
||||
err := c.rpcClient.Call("Plugin.Version", new(interface{}), &resp)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// Execute calls the server-side Execute method and returns generated output.
|
||||
func (c *Client) Execute(args *ExecuteArgs) (string, error) {
|
||||
var resp string
|
||||
err := c.rpcClient.Call("Plugin.Execute", args, &resp)
|
||||
return resp, err
|
||||
}
|
||||
68
plugin/doc.go
Normal file
68
plugin/doc.go
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
Copyright 2021 The terraform-docs Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package plugin contains the implementations needed to make
|
||||
// the built binary act as a plugin.
|
||||
//
|
||||
// A plugin is implemented as an RPC server and the host acts
|
||||
// as the client, sending analysis requests to the plugin.
|
||||
// Note that the server-client relationship here is the opposite of
|
||||
// the communication that takes place during the checking phase.
|
||||
//
|
||||
// Implementation details are hidden in go-plugin. This package is
|
||||
// essentially a wrapper for go-plugin.
|
||||
//
|
||||
// Usage
|
||||
//
|
||||
// A simple plugin can look like this:
|
||||
//
|
||||
// package main
|
||||
//
|
||||
// import (
|
||||
// _ "embed" //nolint
|
||||
//
|
||||
// "github.com/terraform-docs/terraform-docs/plugin"
|
||||
// "github.com/terraform-docs/terraform-docs/print"
|
||||
// "github.com/terraform-docs/terraform-docs/template"
|
||||
// "github.com/terraform-docs/terraform-docs/terraform"
|
||||
// )
|
||||
//
|
||||
// func main() {
|
||||
// plugin.Serve(&plugin.ServeOpts{
|
||||
// Name: "template",
|
||||
// Version: "0.1.0",
|
||||
// Printer: printerFunc,
|
||||
// })
|
||||
// }
|
||||
//
|
||||
// //go:embed sections.tmpl
|
||||
// var tplCustom []byte
|
||||
//
|
||||
// // printerFunc the function being executed by the plugin client.
|
||||
// func printerFunc(config *print.Config, module *terraform.Module) (string, error) {
|
||||
// tpl := template.New(config,
|
||||
// &template.Item{Name: "custom", Text: string(tplCustom)},
|
||||
// )
|
||||
//
|
||||
// rendered, err := tpl.Render("custom", module)
|
||||
// if err != nil {
|
||||
// return "", err
|
||||
// }
|
||||
//
|
||||
// return rendered, nil
|
||||
// }
|
||||
//
|
||||
package plugin
|
||||
80
plugin/plugin.go
Normal file
80
plugin/plugin.go
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
Copyright 2021 The terraform-docs Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"encoding/gob"
|
||||
"net/rpc"
|
||||
|
||||
goplugin "github.com/hashicorp/go-plugin"
|
||||
|
||||
"github.com/terraform-docs/terraform-docs/internal/types"
|
||||
)
|
||||
|
||||
// handshakeConfig is used for UX. ProcotolVersion will be updated by incompatible changes.
|
||||
var handshakeConfig = goplugin.HandshakeConfig{
|
||||
ProtocolVersion: 7,
|
||||
MagicCookieKey: "TFDOCS_PLUGIN",
|
||||
MagicCookieValue: "A7U5oTDDJwdL6UKOw6RXATDa86NEo4xLK3rz7QqegT1N4EY66qb6UeAJDSxLwtXH",
|
||||
}
|
||||
|
||||
// formatter is a wrapper to satisfy the interface of go-plugin.
|
||||
type formatter struct {
|
||||
name string
|
||||
version string
|
||||
printer printFunc
|
||||
}
|
||||
|
||||
func newFormatter(name string, version string, printer printFunc) *formatter {
|
||||
return &formatter{
|
||||
name: name,
|
||||
version: version,
|
||||
printer: printer,
|
||||
}
|
||||
}
|
||||
|
||||
func (f *formatter) Name() string {
|
||||
return f.name
|
||||
}
|
||||
|
||||
func (f *formatter) Version() string {
|
||||
return f.version
|
||||
}
|
||||
|
||||
func (f *formatter) Execute(args *ExecuteArgs) (string, error) {
|
||||
return f.printer(args.Config, args.Module)
|
||||
}
|
||||
|
||||
// Server returns an RPC server acting as a plugin.
|
||||
func (f *formatter) Server(b *goplugin.MuxBroker) (interface{}, error) {
|
||||
return &Server{impl: f, broker: b}, nil
|
||||
}
|
||||
|
||||
// Client returns an RPC client for the host.
|
||||
func (formatter) Client(b *goplugin.MuxBroker, c *rpc.Client) (interface{}, error) {
|
||||
return &Client{rpcClient: c, broker: b}, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
gob.Register(new(types.Bool))
|
||||
gob.Register(new(types.Empty))
|
||||
gob.Register(new(types.List))
|
||||
gob.Register(new(types.Map))
|
||||
gob.Register(new(types.Nil))
|
||||
gob.Register(new(types.Number))
|
||||
gob.Register(new(types.String))
|
||||
}
|
||||
68
plugin/server.go
Normal file
68
plugin/server.go
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
Copyright 2021 The terraform-docs Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package plugin
|
||||
|
||||
import (
|
||||
goplugin "github.com/hashicorp/go-plugin"
|
||||
|
||||
"github.com/terraform-docs/terraform-docs/print"
|
||||
"github.com/terraform-docs/terraform-docs/terraform"
|
||||
)
|
||||
|
||||
// Server is an RPC Server acting as a plugin.
|
||||
type Server struct {
|
||||
impl *formatter
|
||||
broker *goplugin.MuxBroker
|
||||
}
|
||||
|
||||
type printFunc func(*print.Config, *terraform.Module) (string, error)
|
||||
|
||||
// ServeOpts is an option for serving a plugin.
|
||||
type ServeOpts struct {
|
||||
Name string
|
||||
Version string
|
||||
Printer printFunc
|
||||
}
|
||||
|
||||
// Serve is a wrapper of plugin.Serve. This is entrypoint of all plugins.
|
||||
func Serve(opts *ServeOpts) {
|
||||
goplugin.Serve(&goplugin.ServeConfig{
|
||||
HandshakeConfig: handshakeConfig,
|
||||
Plugins: goplugin.PluginSet{
|
||||
"formatter": newFormatter(opts.Name, opts.Version, opts.Printer),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Name returns the version of the plugin.
|
||||
func (s *Server) Name(args interface{}, resp *string) error {
|
||||
*resp = s.impl.Name()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Version returns the version of the plugin.
|
||||
func (s *Server) Version(args interface{}, resp *string) error {
|
||||
*resp = s.impl.Version()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Execute returns the generated output.
|
||||
func (s *Server) Execute(args *ExecuteArgs, resp *string) error {
|
||||
r, err := s.impl.Execute(args)
|
||||
*resp = r
|
||||
return err
|
||||
}
|
||||
@@ -13,11 +13,9 @@ package terraform
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
terraformsdk "github.com/terraform-docs/plugin-sdk/terraform"
|
||||
"github.com/terraform-docs/terraform-docs/internal/types"
|
||||
"github.com/terraform-docs/terraform-docs/print"
|
||||
)
|
||||
@@ -110,21 +108,3 @@ func (ii inputs) sort(enabled bool, by string) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ii inputs) convert() []*terraformsdk.Input {
|
||||
list := []*terraformsdk.Input{}
|
||||
for _, i := range ii {
|
||||
list = append(list, &terraformsdk.Input{
|
||||
Name: i.Name,
|
||||
Type: fmt.Sprintf("%v", i.Type.Raw()),
|
||||
Description: fmt.Sprintf("%v", i.Description.Raw()),
|
||||
Default: i.Default.Raw(),
|
||||
Required: i.Required,
|
||||
Position: terraformsdk.Position{
|
||||
Filename: i.Position.Filename,
|
||||
Line: i.Position.Line,
|
||||
},
|
||||
})
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
@@ -12,8 +12,6 @@ package terraform
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
|
||||
terraformsdk "github.com/terraform-docs/plugin-sdk/terraform"
|
||||
)
|
||||
|
||||
// Module represents a Terraform module. It consists of
|
||||
@@ -72,19 +70,3 @@ func (m *Module) HasRequirements() bool {
|
||||
func (m *Module) HasResources() bool {
|
||||
return len(m.Resources) > 0
|
||||
}
|
||||
|
||||
// Convert internal Module to its equivalent in plugin-sdk
|
||||
func (m *Module) Convert() terraformsdk.Module {
|
||||
return terraformsdk.NewModule(
|
||||
terraformsdk.WithHeader(m.Header),
|
||||
terraformsdk.WithFooter(m.Footer),
|
||||
terraformsdk.WithInputs(inputs(m.Inputs).convert()),
|
||||
terraformsdk.WithModuleCalls(modulecalls(m.ModuleCalls).convert()),
|
||||
terraformsdk.WithOutputs(outputs(m.Outputs).convert()),
|
||||
terraformsdk.WithProviders(providers(m.Providers).convert()),
|
||||
terraformsdk.WithRequirements(requirements(m.Requirements).convert()),
|
||||
terraformsdk.WithResources(resources(m.Resources).convert()),
|
||||
terraformsdk.WithRequiredInputs(inputs(m.RequiredInputs).convert()),
|
||||
terraformsdk.WithOptionalInputs(inputs(m.OptionalInputs).convert()),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
terraformsdk "github.com/terraform-docs/plugin-sdk/terraform"
|
||||
"github.com/terraform-docs/terraform-docs/internal/types"
|
||||
"github.com/terraform-docs/terraform-docs/print"
|
||||
)
|
||||
@@ -73,19 +72,3 @@ func (mm modulecalls) sort(enabled bool, by string) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (mm modulecalls) convert() []*terraformsdk.ModuleCall {
|
||||
list := []*terraformsdk.ModuleCall{}
|
||||
for _, m := range mm {
|
||||
list = append(list, &terraformsdk.ModuleCall{
|
||||
Name: m.Name,
|
||||
Source: m.Source,
|
||||
Version: m.Version,
|
||||
Position: terraformsdk.Position{
|
||||
Filename: m.Position.Filename,
|
||||
Line: m.Position.Line,
|
||||
},
|
||||
})
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
@@ -14,10 +14,8 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
terraformsdk "github.com/terraform-docs/plugin-sdk/terraform"
|
||||
"github.com/terraform-docs/terraform-docs/internal/types"
|
||||
)
|
||||
|
||||
@@ -154,21 +152,3 @@ func (oo outputs) sort(enabled bool, by string) { //nolint:unparam
|
||||
sortOutputsByName(oo)
|
||||
}
|
||||
}
|
||||
|
||||
func (oo outputs) convert() []*terraformsdk.Output {
|
||||
list := []*terraformsdk.Output{}
|
||||
for _, o := range oo {
|
||||
list = append(list, &terraformsdk.Output{
|
||||
Name: o.Name,
|
||||
Description: fmt.Sprintf("%v", o.Description.Raw()),
|
||||
Value: nil,
|
||||
Sensitive: o.Sensitive,
|
||||
Position: terraformsdk.Position{
|
||||
Filename: o.Position.Filename,
|
||||
Line: o.Position.Line,
|
||||
},
|
||||
ShowValue: o.ShowValue,
|
||||
})
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
terraformsdk "github.com/terraform-docs/plugin-sdk/terraform"
|
||||
"github.com/terraform-docs/terraform-docs/internal/types"
|
||||
)
|
||||
|
||||
@@ -62,19 +61,3 @@ func (pp providers) sort(enabled bool, by string) { //nolint:unparam
|
||||
sortProvidersByName(pp)
|
||||
}
|
||||
}
|
||||
|
||||
func (pp providers) convert() []*terraformsdk.Provider {
|
||||
list := []*terraformsdk.Provider{}
|
||||
for _, p := range pp {
|
||||
list = append(list, &terraformsdk.Provider{
|
||||
Name: p.Name,
|
||||
Alias: fmt.Sprintf("%v", p.Alias.Raw()),
|
||||
Version: fmt.Sprintf("%v", p.Version.Raw()),
|
||||
Position: terraformsdk.Position{
|
||||
Filename: p.Position.Filename,
|
||||
Line: p.Position.Line,
|
||||
},
|
||||
})
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
@@ -11,9 +11,6 @@ the root directory of this source tree.
|
||||
package terraform
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
terraformsdk "github.com/terraform-docs/plugin-sdk/terraform"
|
||||
"github.com/terraform-docs/terraform-docs/internal/types"
|
||||
)
|
||||
|
||||
@@ -22,16 +19,3 @@ type Requirement struct {
|
||||
Name string `json:"name" toml:"name" xml:"name" yaml:"name"`
|
||||
Version types.String `json:"version" toml:"version" xml:"version" yaml:"version"`
|
||||
}
|
||||
|
||||
type requirements []*Requirement
|
||||
|
||||
func (rr requirements) convert() []*terraformsdk.Requirement {
|
||||
list := []*terraformsdk.Requirement{}
|
||||
for _, r := range rr {
|
||||
list = append(list, &terraformsdk.Requirement{
|
||||
Name: r.Name,
|
||||
Version: fmt.Sprintf("%v", r.Version.Raw()),
|
||||
})
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
terraformsdk "github.com/terraform-docs/plugin-sdk/terraform"
|
||||
"github.com/terraform-docs/terraform-docs/internal/types"
|
||||
)
|
||||
|
||||
@@ -87,23 +86,3 @@ func (rr resources) sort(enabled bool, by string) { //nolint:unparam
|
||||
// always sort by type
|
||||
sortResourcesByType(rr)
|
||||
}
|
||||
|
||||
func (rr resources) convert() []*terraformsdk.Resource {
|
||||
list := []*terraformsdk.Resource{}
|
||||
for _, r := range rr {
|
||||
list = append(list, &terraformsdk.Resource{
|
||||
Type: r.Type,
|
||||
Name: r.Name,
|
||||
ProviderName: r.ProviderName,
|
||||
ProviderSource: r.ProviderSource,
|
||||
Mode: r.Mode,
|
||||
Version: fmt.Sprintf("%v", r.Version.Raw()),
|
||||
Position: terraformsdk.Position{
|
||||
Filename: r.Position.Filename,
|
||||
Line: r.Position.Line,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
@@ -30,24 +30,6 @@ func TestResourceSpec(t *testing.T) {
|
||||
}
|
||||
assert.Equal("tls_private_key.baz", resource.Spec())
|
||||
}
|
||||
func TestPluginSdkConversion(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
resource := Resource{
|
||||
Type: "private_key",
|
||||
Name: "baz",
|
||||
ProviderName: "tls",
|
||||
ProviderSource: "hashicorp/tls",
|
||||
Mode: "managed",
|
||||
Version: types.String("latest"),
|
||||
}
|
||||
sdkResource := resources{&resource}.convert()[0]
|
||||
assert.Equal(resource.Type, sdkResource.Type)
|
||||
assert.Equal(resource.Name, sdkResource.Name)
|
||||
assert.Equal(resource.ProviderName, sdkResource.ProviderName)
|
||||
assert.Equal(resource.ProviderSource, sdkResource.ProviderSource)
|
||||
assert.Equal(resource.Mode, sdkResource.Mode)
|
||||
assert.Equal(resource.Version, types.String(sdkResource.Version))
|
||||
}
|
||||
|
||||
func TestResourceMode(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
|
||||
Reference in New Issue
Block a user