Skip to content
This repository has been archived by the owner on Dec 27, 2024. It is now read-only.

Commit

Permalink
feat: string/int64 validator OneOfWithDescriptionIfAttributeIsOneOf
Browse files Browse the repository at this point in the history
  • Loading branch information
azrod committed Dec 20, 2024
1 parent ccc6199 commit 9804aa3
Show file tree
Hide file tree
Showing 19 changed files with 625 additions and 50 deletions.
38 changes: 13 additions & 25 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -1,44 +1,33 @@
# Visit https://golangci-lint.run/ for usage documentation
# and information on other useful linters
issues:
max-per-linter: 0
max-same-issues: 0

linters:
enable:
- asciicheck # Simple linter to check that your code does not contain non-ASCII identifiers [fast: true, auto-fix: false]
- bidichk # Checks for dangerous unicode character sequences [fast: true, auto-fix: false]
- deadcode # Finds unused code [fast: false, auto-fix: false]
- decorder # check declaration order and count of types, constants, variables and functions [fast: true, auto-fix: false]
- dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) [fast: true, auto-fix: false]
- durationcheck # check for two durations multiplied together [fast: false, auto-fix: false]
- errcheck # Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases [fast: false, auto-fix: false]
- errchkjson # Checks types passed to the json encoding functions. Reports unsupported types and optionally reports occasions, where the check for the returned error can be omitted. [fast: false, auto-fix: false]
- errname # Checks that sentinel errors are prefixed with the `Err` and error types are suffixed with the `Error`. [fast: false, auto-fix: false]
- execinquery # execinquery is a linter about query string checker in Query function which reads your Go src files and warning it finds [fast: false, auto-fix: false]
- exportloopref # checks for pointers to enclosing loop variables [fast: false, auto-fix: false]
- copyloopvar # Checks for loop variables that are used in a closure [fast: true, auto-fix: false]
- forbidigo # Forbids identifiers [fast: true, auto-fix: false]
- gci # Gci controls golang package import order and makes it always deterministic. [fast: true, auto-fix: false]
- goconst # Finds repeated strings that could be replaced by a constant [fast: true, auto-fix: false]
- gocritic # Provides diagnostics that check for bugs, performance and style issues. [fast: false, auto-fix: false]
- gocyclo # Computes and checks the cyclomatic complexity of functions [fast: true, auto-fix: false]
- gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification [fast: true, auto-fix: true]
- goheader # Checks is file header matches to pattern [fast: true, auto-fix: false]
- gofumpt # Gofumpt checks whether code was gofumpt-ed. [fast: true, auto-fix: true]
- goimports # In addition to fixing imports, goimports also formats your code in the same style as gofmt. [fast: true, auto-fix: true]
- gomoddirectives # Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod. [fast: true, auto-fix: false]
- gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. [fast: true, auto-fix: false]
- goprintffuncname # Checks that printf-like functions are named with `f` at the end [fast: true, auto-fix: false]
- gosec #(gas): Inspects source code for security problems [fast: false, auto-fix: false]
- gosimple #(megacheck): Linter for Go source code that specializes in simplifying a code [fast: false, auto-fix: false]
- govet #(vet, vetshadow): Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string [fast: false, auto-fix: false]
- grouper # An analyzer to analyze expression groups. [fast: true, auto-fix: false]
- ifshort # Checks that your code uses short syntax for if-statements whenever possible [fast: true, auto-fix: false]
- importas # Enforces consistent import aliases [fast: false, auto-fix: false]
- ineffassign # Detects when assignments to existing variables are not used [fast: true, auto-fix: false]
- makezero # Finds slice declarations with non-zero initial length [fast: false, auto-fix: false]
- misspell # Finds commonly misspelled English words in comments [fast: true, auto-fix: true]
- nakedret # Finds naked returns in functions greater than a specified function length [fast: true, auto-fix: false]
- nilerr # Finds the code that returns nil even if it checks that the error is not nil. [fast: false, auto-fix: false]
- noctx # noctx finds sending http request without context.Context [fast: false, auto-fix: false]
- nolintlint # Reports ill-formed or insufficient nolint directives [fast: true, auto-fix: false]
Expand All @@ -48,40 +37,41 @@ linters:
- revive # Fast, configurable, extensible, flexible, and beautiful linter for Go. Drop-in replacement of golint. [fast: false, auto-fix: false]
- rowserrcheck # checks whether Err of rows is checked successfully [fast: false, auto-fix: false]
- sqlclosecheck # Checks that sql.Rows and sql.Stmt are closed. [fast: false, auto-fix: false]
- structcheck # Finds unused struct fields [fast: false, auto-fix: false]
- stylecheck # Stylecheck is a replacement for golint [fast: false, auto-fix: false]
- tagliatelle # Checks the struct tags. [fast: true, auto-fix: false]
- tenv # tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17 [fast: false, auto-fix: false]
- tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes [fast: false, auto-fix: false]
- typecheck # Like the front-end of a Go compiler, parses and type-checks Go code [fast: false, auto-fix: false]
- unconvert # Remove unnecessary type conversions [fast: false, auto-fix: false]
- varcheck # Finds unused global variables and constants [fast: false, auto-fix: false]
- wastedassign # wastedassign finds wasted assignment statements. [fast: false, auto-fix: false]
- whitespace # Tool for detection of leading and trailing whitespace [fast: true, auto-fix: true]
- errorlint # errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13. [fast: false, auto-fix: false]
- nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value. [fast: false, auto-fix: false]
- godot # Check if comments end in a period [fast: true, auto-fix: true]
- unused #(megacheck): Checks Go code for unused constants, variables, functions and types [fast: false, auto-fix: false]
- unparam # reports unused function parameters
- staticcheck #(megacheck): Staticcheck is a go vet on steroids, applying a ton of static analysis checks [fast: false, auto-fix: false]
- bodyclose # checks whether HTTP response body is closed successfully
- goconst # Finds repeated strings that could be replaced by a constant [fast: true, auto-fix: false]

disable:
- depguard # Go linter that checks if package imports are in a list of acceptable packages [fast: true, auto-fix: false]
- dupl # Tool for code clone detection [fast: true, auto-fix: false]
- nakedret # Finds naked returns in functions greater than a specified function length [fast: true, auto-fix: false]
- depguard # Go linter that checks if package imports are in a list of acceptable packages [fast: true, auto-fix: false]
- goimports # In addition to fixing imports, goimports also formats your code in the same style as gofmt. [fast: true, auto-fix: true]
- containedctx # containedctx is a linter that detects struct contained context.Context field [fast: true, auto-fix: false]
- thelper # thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers [fast: false, auto-fix: false]
- cyclop # checks function and package cyclomatic complexity [fast: false, auto-fix: false]
- errorlint # errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13. [fast: false, auto-fix: false]
- exhaustive # check exhaustiveness of enum switch statements [fast: false, auto-fix: false]
- funlen # Tool for detection of long functions [fast: true, auto-fix: false]
- gochecknoglobals # check that no global variables exist [fast: true, auto-fix: false]
- gochecknoinits # Checks that no init functions are present in Go code [fast: true, auto-fix: false]
- gocognit # Computes and checks the cognitive complexity of functions [fast: true, auto-fix: false]
- godot # Check if comments end in a period [fast: true, auto-fix: true]
- godox # Tool for detection of FIXME, TODO and other comment keywords [fast: true, auto-fix: false]
- goerr113 # Golang linter to check the errors handling expressions [fast: false, auto-fix: false]
- gomnd # An analyzer to detect magic numbers. [fast: true, auto-fix: false]
- lll # Reports long lines [fast: true, auto-fix: false]
- maintidx # maintidx measures the maintainability index of each function. [fast: true, auto-fix: false]
- nestif # Reports deeply nested if statements [fast: true, auto-fix: false]
- nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value. [fast: false, auto-fix: false]
- nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity [fast: true, auto-fix: false]
- staticcheck #(megacheck): Staticcheck is a go vet on steroids, applying a ton of static analysis checks [fast: false, auto-fix: false]
- unused #(megacheck): Checks Go code for unused constants, variables, functions and types [fast: false, auto-fix: false]
- varnamelen # checks that the length of a variable's name matches its scope [fast: false, auto-fix: false]
- wrapcheck # Checks that errors returned from external packages are wrapped [fast: false, auto-fix: false]
- wsl # Whitespace Linter - Forces you to use empty lines! [fast: true, auto-fix: false]
Expand Down Expand Up @@ -140,6 +130,4 @@ linters-settings:
allow:
- $gostd
- github.com/hashicorp
- github.com/FrangipaneTeam
# Packages that are not allowed where the value is a suggestion.
deny:
- github.com/FrangipaneTeam
2 changes: 1 addition & 1 deletion boolvalidator/require_if_attribute_is_set.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"github.com/FrangipaneTeam/terraform-plugin-framework-validators/internal"
)

// RequireIfAttributeIsSet checks if the path.Path attribute is set
// RequireIfAttributeIsSet checks if the path.Path attribute is set.
func RequireIfAttributeIsSet(path path.Expression) validator.Bool {
return internal.RequireIfAttributeIsSet{
PathExpression: path,
Expand Down
59 changes: 59 additions & 0 deletions docs/common/oneofwithdescriptionifattributeisoneof.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# `OneOfWithDescription`

!!! quote inline end "Released in v1.9.0"

This validator allows to check if the string is one of the values ​​of another attribute.
It also allows to format the description and markdown description accordingly

## How to use it

```go
// Schema defines the schema for the resource.
func (r *xResource) Schema(ctx context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
(...)
"foo": schema.StringAttribute{
Optional: true,
MarkdownDescription: "foo ...",
Validators: []validator.String{
fstringvalidator.OneOf("VM_NAME", "VM_TAGS"),
},
},
"bar": schema.StringAttribute{
Optional: true,
MarkdownDescription: "bar of ...",
Validators: []validator.String{
fstringvalidator.OneOfWithDescriptionIfAttributeIsOneOf(
path.MatchRelative().AtParent().AtName("foo"),
[]attr.Value{types.StringValue("VM_NAME")},
func() []fstringvalidator.OneOfWithDescriptionIfAttributeIsOneOfValues {
return []fstringvalidator.OneOfWithDescriptionIfAttributeIsOneOfValues{
{
Value: "CONTAINS",
Description: "The `value` must be contained in the VM name.",
},
{
Value: "STARTS_WITH",
Description: "The VM name must start with the `value`.",
},
{
Value: "ENDS_WITH",
Description: "The VM name must end with the `value`.",
},
{
Value: "EQUALS",
Description: "The VM name must be equal to the `value`.",
},
}
}()...),
},
},
```
## Description and Markdown description
* **Description:**
If the value of attribute <.type is "VM_NAME" the allowed values are : "CONTAINS" (The `value` must be contained in the VM name.), "STARTS_WITH" (The VM name must start with the `value`.), "ENDS_WITH" (The VM name must end with the `value`.), "EQUALS" (The VM name must be equal to the `value`.)
* **Markdown description:**
![oneofwithdescriptionifattributeisoneof](oneofwithdescriptionifattributeisoneof.png)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/int64validator/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
- [`NullIfAttributeIsOneOf`](../common/null_if_attribute_is_one_of.md) - This validator is used to verify the attribute value is null if another attribute is one of the given values.
- [`NullIfAttributeIsSet`](../common/null_if_attribute_is_set.md) - This validator is used to verify the attribute value is null if another attribute is set.
- [`OneOfWithDescription`](oneofwithdescription.md) - This validator is used to check if the string is one of the given values and format the description and the markdown description.
- [`OneOfWithDescriptionIfAttributeIsOneOf`](../common/oneofwithdescriptionifattributeisoneof.md) - This validator is used to check if the string is one of the given values if the attribute is one of and format the description and the markdown description.
- [`AttributeIsDivisibleByAnInteger`](attribute_is_divisible_by_an_integer.md) - This validator is used to validate that the attribute is divisible by an integer.
- [`ZeroRemainder`](zero_remainder.md) - This validator checks if the configured attribute is divisible by a specified integer X, and has zero remainder.

Expand Down
1 change: 1 addition & 0 deletions docs/stringvalidator/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
- [`NullIfAttributeIsOneOf`](../common/null_if_attribute_is_one_of.md) - This validator is used to verify the attribute value is null if another attribute is one of the given values.
- [`NullIfAttributeIsSet`](../common/null_if_attribute_is_set.md) - This validator is used to verify the attribute value is null if another attribute is set.
- [`OneOfWithDescription`](oneofwithdescription.md) - This validator is used to check if the string is one of the given values and format the description and the markdown description.
- [`OneOfWithDescriptionIfAttributeIsOneOf`](../common/oneofwithdescriptionifattributeisoneof.md) - This validator is used to check if the string is one of the given values if the attribute is one of and format the description and the markdown description.

### Network

Expand Down
35 changes: 35 additions & 0 deletions int64validator/one_of_with_description_if_attribute_is_one_of.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package int64validator

import (
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"

"github.com/FrangipaneTeam/terraform-plugin-framework-validators/internal"
)

type OneOfWithDescriptionIfAttributeIsOneOfValues struct {
Value int64
Description string
}

// OneOfWithDescriptionIfAttributeIsOneOf checks that the value is one of the expected values if the attribute is one of the exceptedValue.
// The description of the value is used to generate advanced
// Description and MarkdownDescription messages.
func OneOfWithDescriptionIfAttributeIsOneOf(path path.Expression, exceptedValue []attr.Value, values ...OneOfWithDescriptionIfAttributeIsOneOfValues) validator.String {
frameworkValues := make([]internal.OneOfWithDescriptionIfAttributeIsOneOf, 0, len(values))

for _, v := range values {
frameworkValues = append(frameworkValues, internal.OneOfWithDescriptionIfAttributeIsOneOf{
Value: types.Int64Value(v.Value),
Description: v.Description,
})
}

return internal.OneOfWithDescriptionIfAttributeIsOneOfValidator{
Values: frameworkValues,
ExceptedValues: exceptedValue,
PathExpression: path,
}
}
2 changes: 1 addition & 1 deletion int64validator/require_if_attribute_is_set.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"github.com/FrangipaneTeam/terraform-plugin-framework-validators/internal"
)

// RequireIfAttributeIsSet checks if the path.Path attribute is set
// RequireIfAttributeIsSet checks if the path.Path attribute is set.
func RequireIfAttributeIsSet(path path.Expression) validator.Int64 {
return internal.RequireIfAttributeIsSet{
PathExpression: path,
Expand Down
12 changes: 0 additions & 12 deletions internal/one_of_with_description.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,18 +75,6 @@ func (v OneOfWithDescriptionValidator) MarkdownDescription(_ context.Context) st
return fmt.Sprintf("%s %s", oneOfWithDescriptionValidatorDescription, valuesDescription)
}

func (v OneOfWithDescriptionValidator) valuesDescription(_ context.Context) string {
var valuesDescription string
for i, value := range v.Values {
if i == len(v.Values)-1 {
valuesDescription += fmt.Sprintf("%s (%s)", value.Value.String(), value.Description)
break
}
valuesDescription += fmt.Sprintf("%s (%s), ", value.Value.String(), value.Description)
}
return valuesDescription
}

func (v OneOfWithDescriptionValidator) Validate(ctx context.Context, req OneOfWithDescriptionValidatorRequest, res *OneOfWithDescriptionValidatorResponse) {
// If attribute configuration is not null or unknown, there is nothing else to validate
if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() || len(v.Values) == 0 {
Expand Down
Loading

0 comments on commit 9804aa3

Please sign in to comment.