Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[any-tf-provider] Switch args parsing to cobra #2742

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion dynamic/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,28 @@ func ReadResourceRequest(i *tfprotov6.ReadResourceRequest) *tfplugin6.ReadResour
}
}
```

### `package parameterize`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for documenting! Docs are very good to have.

We're still figuring out what's our style for docs - so happy to discuss alternatives. One pattern I've used before in this repo is package.go with doc comment describing what each package does. This seems to be some support for this in e.g. https://tip.golang.org/doc/comment#package - this also gets copied into auto-generated Go docs.

The README is also very important. There's "how do I use this" and "what can it do" concerns that go in a README. Not sure what's the right balance for us is here but my 2c so you're aware of the package.go option for the package-level detail.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a good call-out. The bridge also has 1 doc.go, and I've seen more in the wild.

For this PR, I'm going to keep using the README.md, since that's what the module already does. It might be worth standardizing at some point.

Autogenerated Go docs also include the README: https://pkg.go.dev/github.com/pulumi/pulumi-terraform-bridge/dynamic.


`package parameterize` is responsible for reading and writing the values passed in the [Parameterize](https://pulumi-developer-docs.readthedocs.io/latest/docs/_generated/proto/provider.html#parameterize) gRPC
call. `args.go` is responsible for handling the CLI args (`ParametersArgs)` version of Parameterize, while
`value.go` is responsible for handling the `ParametersValue` version of `Parameterize`.

#### Args

Arg values are parsed with [`cobra`](https://github.com/spf13/cobra).

For maintainers: there are two hidden flags (use `PULUMI_DEV=true` to display) used in example generation:

| Flag | Description |
|----------------------|------------------------------------------------------------------------------|
| `--fullDocs` | Attempt to generate full docs with documentation. |
| `--upstreamRepoPath` | The local path to the repository root where the upstream provider docs live. |

These flags are hidden because they are expected to be used by other Pulumi processes, not by end users.

#### Value

## Releasing & [`pulumi/pulumi-terraform-provider`](https://github.com/pulumi/pulumi-terraform-provider)

The `pulumi-terraform-provider` codebase is located in
Expand Down Expand Up @@ -283,4 +305,4 @@ Dynamically bridged providers allow the Terraform provider interactions to be re
1. To reproduce the behaviour, maintainers should use the `tf-logs.json` like in `dynamic/log_replay_provider.go:TestLogReplayProviderWithProgram`:
1. Dump the sanitized log file under `testadata`.
1. Use `NewLogReplayProvider` to create a provider which will replay the calls encountered by the user.
2. Use the `pulcheck` utility to mimic the user actions which triggered the behaviour, like `Preview` and `Up`
2. Use the `pulcheck` utility to mimic the user actions which triggered the behaviour, like `Preview` and `Up`
24 changes: 23 additions & 1 deletion dynamic/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,37 @@ require (
)

require (
cloud.google.com/go/logging v1.9.0 // indirect
cloud.google.com/go/longrunning v0.5.5 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/gofrs/uuid v4.2.0+incompatible // indirect
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/wire v0.6.0 // indirect
github.com/gorilla/mux v1.8.0 // indirect
github.com/hashicorp/logutils v1.0.0 // indirect
github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0 // indirect
github.com/hashicorp/vault/api v1.12.0 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/nxadm/tail v1.4.11 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/pulumi/terraform-diff-reader v0.0.2 // indirect
github.com/teekennedy/goldmark-markdown v0.3.0 // indirect
github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
github.com/yuin/goldmark v1.7.4 // indirect
gocloud.dev v0.37.0 // indirect
gocloud.dev/secrets/hashivault v0.37.0 // indirect
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
google.golang.org/appengine v1.6.8 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gotest.tools v2.2.0+incompatible // indirect
Expand Down Expand Up @@ -214,7 +236,7 @@ require (
github.com/skeema/knownhosts v1.2.2 // indirect
github.com/spf13/afero v1.9.5
github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/cobra v1.8.0 // indirect
github.com/spf13/cobra v1.8.0
github.com/spf13/pflag v1.0.5 // indirect
github.com/texttheater/golang-levenshtein v1.0.1 // indirect
github.com/uber/jaeger-client-go v2.30.0+incompatible // indirect
Expand Down
13 changes: 12 additions & 1 deletion dynamic/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1151,7 +1151,6 @@ dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8=
git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc=
github.com/Azure/azure-sdk-for-go v59.2.0+incompatible h1:mbxiZy1K820hQ+dI+YIO/+a0wQDYqOu18BAGe4lXjVk=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 h1:E+OJmp2tPvt1W+amx48v1eqbjDYsgN+RzP4q16yV5eM=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1/go.mod h1:a6xsAQUZg+VsS3TJ05SRp524Hs4pZ/AeFSr5ENf0Yjo=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 h1:tfLQ34V6F7tVSwoTf/4lH5sE0o6eCJuNDTmH09nDpbc=
Expand Down Expand Up @@ -1241,6 +1240,8 @@ github.com/aws/aws-sdk-go-v2/credentials v1.17.11 h1:YuIB1dJNf1Re822rriUOTxopaHH
github.com/aws/aws-sdk-go-v2/credentials v1.17.11/go.mod h1:AQtFPsDH9bI2O+71anW6EKL+NcD7LG3dpKGMV4SShgo=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1 h1:FVJ0r5XTHSmIHJV6KuDmdYhEpvlHpiSd38RQWhut5J4=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1/go.mod h1:zusuAeqezXzAB24LGuzuekqMAEgWkVYukBec3kr3jUg=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.15 h1:7Zwtt/lP3KNRkeZre7soMELMGNoBrutx8nobg1jKWmo=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.15/go.mod h1:436h2adoHb57yd+8W+gYPrrA9U/R/SuAuOO42Ushzhw=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 h1:aw39xVGeRWlWx9EzGVnhOR4yOjQDHPQ6o6NmBlscyQg=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5/go.mod h1:FSaRudD0dXiMPK2UjknVwwTYyZMRsHv3TtkabsZih5I=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 h1:PG1F3OD1szkuQPzDw3CIQsRIrtTlUC3lP84taWzHlq0=
Expand Down Expand Up @@ -1520,6 +1521,10 @@ github.com/google/go-pkcs11 v0.2.0/go.mod h1:6eQoGcuNJpa7jnd5pMGdkSaQpNDYvPlXWMc
github.com/google/go-pkcs11 v0.2.1-0.20230907215043-c6f79328ddf9/go.mod h1:6eQoGcuNJpa7jnd5pMGdkSaQpNDYvPlXWMcjXXThLlY=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/go-replayers/grpcreplay v1.1.0 h1:S5+I3zYyZ+GQz68OfbURDdt/+cSMqCK1wrvNx7WBzTE=
github.com/google/go-replayers/grpcreplay v1.1.0/go.mod h1:qzAvJ8/wi57zq7gWqaE6AwLM6miiXUQwP1S+I9icmhk=
github.com/google/go-replayers/httpreplay v1.2.0 h1:VM1wEyyjaoU53BwrOnaf9VhAyQQEEioJvFYxYcLRKzk=
github.com/google/go-replayers/httpreplay v1.2.0/go.mod h1:WahEFFZZ7a1P4VM1qEeHy+tME4bwyqPcwWbNlUI1Mcg=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
Expand Down Expand Up @@ -1552,6 +1557,7 @@ github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
Expand Down Expand Up @@ -2155,6 +2161,7 @@ golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
Expand Down Expand Up @@ -2302,6 +2309,7 @@ golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
Expand Down Expand Up @@ -2361,6 +2369,7 @@ golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
Expand Down Expand Up @@ -2492,6 +2501,7 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww=
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
Expand Down Expand Up @@ -2600,6 +2610,7 @@ golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM=
golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
Expand Down
2 changes: 1 addition & 1 deletion dynamic/internal/shim/run/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ func NamedProvider(ctx context.Context, key, version string) (Provider, error) {

v, err := getproviders.ParseVersionConstraints(version)
if err != nil {
return nil, err
return nil, fmt.Errorf("could not parse version constraint %q: %w", version, err)
}

return getProviderServer(ctx, p, v, disco.New())
Expand Down
2 changes: 1 addition & 1 deletion dynamic/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ func initialSetup() (info.Provider, pfbridge.ProviderMetadata, func() error) {
args = value.IntoArgs()
case *plugin.ParameterizeArgs:
var err error
args, err = parameterize.ParseArgs(params.Args)
args, err = parameterize.ParseArgs(ctx, params.Args)
if err != nil {
return plugin.ParameterizeResponse{}, err
}
Expand Down
134 changes: 85 additions & 49 deletions dynamic/parameterize/args.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,17 @@
package parameterize

import (
"bytes"
"context"
"errors"
"fmt"
"strings"

"github.com/pulumi/pulumi/sdk/v3/go/common/env"
"github.com/pulumi/pulumi/sdk/v3/go/common/util/contract"
"github.com/spf13/cobra"

"github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfbridge"
)

// Args represents a parsed CLI argument from a parameterize call.
Expand All @@ -31,6 +40,7 @@ type RemoteArgs struct {
Name string
// Version is the (possibly empty) version constraint on the provider.
Version string

// Docs indicates if full schema documentation should be generated.
Docs bool
}
Expand All @@ -39,69 +49,95 @@ type RemoteArgs struct {
type LocalArgs struct {
// Path is the path to the provider binary. It can be relative or absolute.
Path string

// UpstreamRepoPath (if provided) is the local path to the dynamically bridged Terraform provider's repo.
//
// If set, full documentation will be generated for the provider.
// If not set, only documentation from the TF provider's schema will be used.
UpstreamRepoPath string
}

func ParseArgs(args []string) (Args, error) {
// Check for a leading '.' or '/' to indicate a path
if len(args) >= 1 &&
(strings.HasPrefix(args[0], "./") || strings.HasPrefix(args[0], "/")) {
func ParseArgs(ctx context.Context, a []string) (Args, error) {
var args Args
var fullDocs bool
var upstreamRepoPath string
cmd := cobra.Command{
Use: "./local | remote version",
RunE: func(cmd *cobra.Command, a []string) error {
var err error
args, err = parseArgs(cmd.Context(), a, fullDocs, upstreamRepoPath)
return err
},
Args: cobra.RangeArgs(1, 2),
}
cmd.Flags().BoolVar(&fullDocs, "fullDocs", false,
"Generate a schema with full docs, at the expense of speed")
cmd.Flags().StringVar(&upstreamRepoPath, "upstreamRepoPath", "",
"Specify a local file path to the root of the Git repository of the provider being dynamically bridged")

// We hide docs flags since they are not intended for end users, and they may not be stable.
iwahbe marked this conversation as resolved.
Show resolved Hide resolved
if !env.Dev.Value() {
contract.AssertNoErrorf(
errors.Join(
cmd.Flags().MarkHidden("fullDocs"),
cmd.Flags().MarkHidden("upstreamRepoPath"),
),
"impossible - these are static values and should never fail",
)
}

cmd.SetArgs(a)

// We want to show the stdout of this command to the user, if there is
// any. pulumi/pulumi#17943 started hiding unstructured output by default. This
// block writes the output of `cmd` to `out`, and then logs what was written to
// `out` to info, which will be displayed directly to the user (without any
// prefix, warning and error have a prefix).
var out bytes.Buffer
cmd.SetOut(&out)
cmd.SetErr(&out)
defer func() {
if out.Len() == 0 {
return
}
tfbridge.GetLogger(ctx).Info(out.String())
iwahbe marked this conversation as resolved.
Show resolved Hide resolved
}()

return args, cmd.ExecuteContext(ctx)
}

func parseArgs(_ context.Context, args []string, fullDocs bool, upstreamRepoPath string) (Args, error) {
// If we see a local prefix (starts with '.' or '/'), parse args for a local provider
if strings.HasPrefix(args[0], ".") || strings.HasPrefix(args[0], "/") {
if len(args) > 1 {
docsArg := args[1]
upstreamRepoPath, found := strings.CutPrefix(docsArg, "upstreamRepoPath=")
if !found {
return Args{}, fmt.Errorf(
"path based providers are only parameterized by 2 arguments: <path> " +
"[upstreamRepoPath=<path/to/files>]",
)
}
return Args{}, fmt.Errorf("local providers only accept one argument, found %d", len(args))
}
if fullDocs {
msg := "fullDocs only applies to remote providers"
if upstreamRepoPath == "" {
return Args{}, fmt.Errorf(
"upstreamRepoPath must be set to a non-empty value: " +
"upstreamRepoPath=path/to/files",
)
msg += ", consider specifying upstreamRepoPath instead"
}
return Args{Local: &LocalArgs{Path: args[0], UpstreamRepoPath: upstreamRepoPath}}, nil
return Args{}, errors.New(msg)
}
return Args{Local: &LocalArgs{Path: args[0]}}, nil
return Args{Local: &LocalArgs{Path: args[0], UpstreamRepoPath: upstreamRepoPath}}, nil
}

// This is a registry based provider
var remote RemoteArgs
switch len(args) {
// The third argument, if any, is the full docs option for when we need to generate docs
case 3:
docsArg := args[2]
errMsg := "expected third parameterized argument to be 'fullDocs=<true|false>' or be empty"

fullDocs, found := strings.CutPrefix(docsArg, "fullDocs=")
if !found {
return Args{}, fmt.Errorf("%s", errMsg)
}

switch fullDocs {
case "true":
remote.Docs = true
case "false":
// Do nothing
default:
return Args{}, fmt.Errorf("%s", errMsg)
if upstreamRepoPath != "" {
msg := "upstreamRepoPath only applies to local providers"
if upstreamRepoPath == "" {
msg += ", consider specifying fullDocs instead"
}
return Args{}, errors.New(msg)
}

fallthrough
// The second argument, if any is the version
case 2:
remote.Version = args[1]
fallthrough
// The first argument is the provider name
case 1:
remote.Name = args[0]
return Args{Remote: &remote}, nil
default:
return Args{}, fmt.Errorf("expected to be parameterized by 1-3 arguments: <name> [version] [fullDocs=<true|false>]")
var version string
if len(args) > 1 {
version = args[1]
}

return Args{Remote: &RemoteArgs{
Name: args[0],
Version: version,
Docs: fullDocs,
}}, nil
}
Loading
Loading