Skip to content

Commit

Permalink
provider: skip decorating provider descriptions
Browse files Browse the repository at this point in the history
Right now, there isn't a way to do automatic description decoration based on the
schema attributes[1]. This is a problem because to mux two provider types they
must return identical schemas.

To work around this, I've added conditionals to the generator to ignore the
schema fields in the providers where we may experience differences between the
providers but it remains for all resources and data sources. For now, this
strikes the balance of unblocking us and keeping the documentation nicely
decorated.

[1]: hashicorp/terraform-plugin-framework#625
  • Loading branch information
jacobbednarz committed Jan 19, 2023
1 parent 0d7e444 commit 074e217
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 54 deletions.
14 changes: 7 additions & 7 deletions internal/framework/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,13 @@ func (p *CloudflareProvider) Schema(ctx context.Context, req provider.SchemaRequ
Attributes: map[string]schema.Attribute{
consts.EmailSchemaKey: schema.StringAttribute{
Optional: true,
MarkdownDescription: fmt.Sprintf("A registered Cloudflare email address. Alternatively, can be configured using the `%s` environment variable.", consts.EmailEnvVarKey),
MarkdownDescription: fmt.Sprintf("A registered Cloudflare email address. Alternatively, can be configured using the `%s` environment variable. Required when using `api_key`. Conflicts with `api_token`.", consts.EmailEnvVarKey),
Validators: []validator.String{},
},

consts.APIKeySchemaKey: schema.StringAttribute{
Optional: true,
MarkdownDescription: fmt.Sprintf("The API key for operations. Alternatively, can be configured using the `%s` environment variable. API keys are [now considered legacy by Cloudflare](https://developers.cloudflare.com/api/keys/#limitations), API tokens should be used instead.", consts.APIKeyEnvVarKey),
MarkdownDescription: fmt.Sprintf("The API key for operations. Alternatively, can be configured using the `%s` environment variable. API keys are [now considered legacy by Cloudflare](https://developers.cloudflare.com/api/keys/#limitations), API tokens should be used instead. Must provide only one of `api_key`, `api_token`, `api_user_service_key`.", consts.APIKeyEnvVarKey),
Validators: []validator.String{
stringvalidator.RegexMatches(
regexp.MustCompile(`[0-9a-f]{37}`),
Expand All @@ -87,7 +87,7 @@ func (p *CloudflareProvider) Schema(ctx context.Context, req provider.SchemaRequ

consts.APITokenSchemaKey: schema.StringAttribute{
Optional: true,
MarkdownDescription: fmt.Sprintf("The API Token for operations. Alternatively, can be configured using the `%s` environment variable.", consts.APITokenEnvVarKey),
MarkdownDescription: fmt.Sprintf("The API Token for operations. Alternatively, can be configured using the `%s` environment variable. Must provide only one of `api_key`, `api_token`, `api_user_service_key`.", consts.APITokenEnvVarKey),
Validators: []validator.String{
stringvalidator.RegexMatches(
regexp.MustCompile(`[A-Za-z0-9-_]{40}`),
Expand All @@ -103,7 +103,7 @@ func (p *CloudflareProvider) Schema(ctx context.Context, req provider.SchemaRequ

consts.APIUserServiceKeySchemaKey: schema.StringAttribute{
Optional: true,
MarkdownDescription: fmt.Sprintf("A special Cloudflare API key good for a restricted set of endpoints. Alternatively, can be configured using the `%s` environment variable.", consts.APIUserServiceKeyEnvVarKey),
MarkdownDescription: fmt.Sprintf("A special Cloudflare API key good for a restricted set of endpoints. Alternatively, can be configured using the `%s` environment variable. Must provide only one of `api_key`, `api_token`, `api_user_service_key`.", consts.APIUserServiceKeyEnvVarKey),
Validators: []validator.String{
stringvalidator.ExactlyOneOf(path.Expressions{
path.MatchRoot(consts.APIKeySchemaKey),
Expand Down Expand Up @@ -340,7 +340,7 @@ var TestAccProtoV6ProviderFactories = map[string]func() (tfprotov6.ProviderServe
}

func TestAccPreCheck(t *testing.T) {
// // You can add code here to run prior to any test case execution, for example assertions
// // about the appropriate environment variables being set are common to see in a pre-check
// // function.
// You can add code here to run prior to any test case execution, for example assertions
// about the appropriate environment variables being set are common to see in a pre-check
// function.
}
94 changes: 47 additions & 47 deletions internal/sdkv2provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,49 +30,49 @@ func init() {
desc += "."
}

// if s.Default != nil {
// if s.Default == "" {
// desc += " Defaults to `\"\"`."
// } else {
// desc += fmt.Sprintf(" Defaults to `%v`.", s.Default)
// }
// }

// if s.RequiredWith != nil && len(s.RequiredWith) > 0 {
// requiredWith := make([]string, len(s.RequiredWith))
// for i, c := range s.RequiredWith {
// requiredWith[i] = fmt.Sprintf("`%s`", c)
// }
// desc += fmt.Sprintf(" Required when using %s.", strings.Join(requiredWith, ", "))
// }

// if s.ConflictsWith != nil && len(s.ConflictsWith) > 0 {
// conflicts := make([]string, len(s.ConflictsWith))
// for i, c := range s.ConflictsWith {
// conflicts[i] = fmt.Sprintf("`%s`", c)
// }
// desc += fmt.Sprintf(" Conflicts with %s.", strings.Join(conflicts, ", "))
// }

// if s.ExactlyOneOf != nil && len(s.ExactlyOneOf) > 0 {
// exactlyOneOfs := make([]string, len(s.ExactlyOneOf))
// for i, c := range s.ExactlyOneOf {
// exactlyOneOfs[i] = fmt.Sprintf("`%s`", c)
// }
// desc += fmt.Sprintf(" Must provide only one of %s.", strings.Join(exactlyOneOfs, ", "))
// }

// if s.AtLeastOneOf != nil && len(s.AtLeastOneOf) > 0 {
// atLeastOneOfs := make([]string, len(s.AtLeastOneOf))
// for i, c := range s.AtLeastOneOf {
// atLeastOneOfs[i] = fmt.Sprintf("`%s`", c)
// }
// desc += fmt.Sprintf(" Must provide at least one of %s.", strings.Join(atLeastOneOfs, ", "))
// }

// if s.ForceNew {
// desc += " **Modifying this attribute will force creation of a new resource.**"
// }
if s.Default != nil {
if s.Default == "" {
desc += " Defaults to `\"\"`."
} else {
desc += fmt.Sprintf(" Defaults to `%v`.", s.Default)
}
}

if s.RequiredWith != nil && len(s.RequiredWith) > 0 && !contains(s.RequiredWith, consts.APIKeySchemaKey) {
requiredWith := make([]string, len(s.RequiredWith))
for i, c := range s.RequiredWith {
requiredWith[i] = fmt.Sprintf("`%s`", c)
}
desc += fmt.Sprintf(" Required when using %s.", strings.Join(requiredWith, ", "))
}

if s.ConflictsWith != nil && len(s.ConflictsWith) > 0 && !contains(s.ConflictsWith, consts.APITokenSchemaKey) {
conflicts := make([]string, len(s.ConflictsWith))
for i, c := range s.ConflictsWith {
conflicts[i] = fmt.Sprintf("`%s`", c)
}
desc += fmt.Sprintf(" Conflicts with %s.", strings.Join(conflicts, ", "))
}

if s.ExactlyOneOf != nil && len(s.ExactlyOneOf) > 0 && (!contains(s.ExactlyOneOf, consts.APIKeySchemaKey) || !contains(s.ExactlyOneOf, consts.APITokenSchemaKey) || !contains(s.ExactlyOneOf, consts.APIUserServiceKeySchemaKey)) {
exactlyOneOfs := make([]string, len(s.ExactlyOneOf))
for i, c := range s.ExactlyOneOf {
exactlyOneOfs[i] = fmt.Sprintf("`%s`", c)
}
desc += fmt.Sprintf(" Must provide only one of %s.", strings.Join(exactlyOneOfs, ", "))
}

if s.AtLeastOneOf != nil && len(s.AtLeastOneOf) > 0 {
atLeastOneOfs := make([]string, len(s.AtLeastOneOf))
for i, c := range s.AtLeastOneOf {
atLeastOneOfs[i] = fmt.Sprintf("`%s`", c)
}
desc += fmt.Sprintf(" Must provide at least one of %s.", strings.Join(atLeastOneOfs, ", "))
}

if s.ForceNew {
desc += " **Modifying this attribute will force creation of a new resource.**"
}

return strings.TrimSpace(desc)
}
Expand All @@ -85,29 +85,29 @@ func New(version string) func() *schema.Provider {
consts.EmailSchemaKey: {
Type: schema.TypeString,
Optional: true,
Description: fmt.Sprintf("A registered Cloudflare email address. Alternatively, can be configured using the `%s` environment variable.", consts.EmailEnvVarKey),
Description: fmt.Sprintf("A registered Cloudflare email address. Alternatively, can be configured using the `%s` environment variable. Required when using `api_key`. Conflicts with `api_token`.", consts.EmailEnvVarKey),
ConflictsWith: []string{consts.APITokenSchemaKey},
RequiredWith: []string{consts.APIKeySchemaKey},
},

consts.APIKeySchemaKey: {
Type: schema.TypeString,
Optional: true,
Description: fmt.Sprintf("The API key for operations. Alternatively, can be configured using the `%s` environment variable. API keys are [now considered legacy by Cloudflare](https://developers.cloudflare.com/api/keys/#limitations), API tokens should be used instead.", consts.APIKeyEnvVarKey),
Description: fmt.Sprintf("The API key for operations. Alternatively, can be configured using the `%s` environment variable. API keys are [now considered legacy by Cloudflare](https://developers.cloudflare.com/api/keys/#limitations), API tokens should be used instead. Must provide only one of `api_key`, `api_token`, `api_user_service_key`.", consts.APIKeyEnvVarKey),
ValidateFunc: validation.StringMatch(regexp.MustCompile("[0-9a-f]{37}"), "API key must be 37 characters long and only contain characters 0-9 and a-f (all lowercased)"),
},

consts.APITokenSchemaKey: {
Type: schema.TypeString,
Optional: true,
Description: fmt.Sprintf("The API Token for operations. Alternatively, can be configured using the `%s` environment variable.", consts.APITokenEnvVarKey),
Description: fmt.Sprintf("The API Token for operations. Alternatively, can be configured using the `%s` environment variable. Must provide only one of `api_key`, `api_token`, `api_user_service_key`.", consts.APITokenEnvVarKey),
ValidateFunc: validation.StringMatch(regexp.MustCompile("[A-Za-z0-9-_]{40}"), "API tokens must be 40 characters long and only contain characters a-z, A-Z, 0-9, hyphens and underscores"),
},

consts.APIUserServiceKeySchemaKey: {
Type: schema.TypeString,
Optional: true,
Description: fmt.Sprintf("A special Cloudflare API key good for a restricted set of endpoints. Alternatively, can be configured using the `%s` environment variable.", consts.APIUserServiceKeyEnvVarKey),
Description: fmt.Sprintf("A special Cloudflare API key good for a restricted set of endpoints. Alternatively, can be configured using the `%s` environment variable. Must provide only one of `api_key`, `api_token`, `api_user_service_key`.", consts.APIUserServiceKeyEnvVarKey),
},

consts.RPSSchemaKey: {
Expand Down

0 comments on commit 074e217

Please sign in to comment.