forked from hashicorp/terraform-plugin-framework
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
path+website: Additional Go documentation and initial website documen…
…tation for paths and path expressions (hashicorp#413) Reference: hashicorp#81
- Loading branch information
Showing
8 changed files
with
882 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
--- | ||
page_title: 'Plugin Development - Framework: Path Expressions' | ||
description: >- | ||
How to implement path expressions in the provider development framework. | ||
Path expressions are logic built on top of paths, which may represent one or | ||
more actual paths within schema data. | ||
--- | ||
|
||
# Path Expressions | ||
|
||
Path expressions are logic built on top of [paths](/plugin/framework/paths), which may represent one or more actual paths within a schema or schema-based data. Expressions enable providers to work outside the restrictions of absolute paths and steps. | ||
|
||
## Usage | ||
|
||
Example uses include: | ||
|
||
- [Path based attribute validators](/plugin/framework/validation#path-based-attribute-validators), such as those in the [`terraform-plugin-framework-validators` module `schemavalidator` package](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/schemavalidator). | ||
|
||
Use cases which require exact locations, such as [diagnostics](/plugin/framework/diagnostics), implement [paths](/plugin/framework/paths). | ||
|
||
## Concepts | ||
|
||
Path expressions are an abstraction above [paths](/plugin/framework/paths). This page assumes knowledge of path concepts and implementations. | ||
|
||
At its core, expressions implement the following on top of paths: | ||
|
||
- Information that designates whether path information is intended to be absolute, similar to paths, or relative, where it is assumed it will be merged with other absolute path information. | ||
- Parent steps, which enables backwards traversal towards the root of a schema in relative paths, after being merged with other absolute path information. | ||
- Path matching, which enables path information to logically return one or more actual paths. | ||
|
||
Similar to paths, expressions are built using steps. There are expression steps which directly correspond to exact path steps, such as `AtListIndex()`, `AtMapKey()`, `AtName()`, `AtSetValue()`. Their implementation is the same. However, there are additional expression steps, such as `AtAnyListIndex()`, which cannot be represented in paths due to the potential for ambiguity. | ||
|
||
Path matching is the notion that each expression step implements a method that logically determines if a given exact path step should match. For example, the `AtAnyListIndex()` expression step will accept any exact path step for a list index. Path matching with an expression is a collection of matching each expression step against each exact path step, after resolving any potential parent steps. | ||
|
||
Every path expression must align with the schema definition or an error diagnostic will be raised when working with path matching within the framework. Provider-defined functionality that is schema-based, such as attribute validation and attribute plan modification, are provided an accurate current path expression since that functionality would not be able to determine its own path expression. | ||
|
||
## Building Path Expressions | ||
|
||
The framework implementation for path expressions is in the [`path` package](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/path), with the [`path.Expression` type](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/path#Expression) being the main provider developer interaction point. | ||
|
||
### Building Absolute Path Expressions | ||
|
||
Call the [`path.MatchRoot()` function](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/path#MatchRoot) with an attribute name or block name at the root of the schema to begin an absolute path expression. | ||
|
||
Given this example schema with a root attribute named `example_root_attribute`: | ||
|
||
```go | ||
tfsdk.Schema{ | ||
Attributes: map[string]tfsdk.Attribute{ | ||
"example_root_attribute": { | ||
Required: true, | ||
Type: types.StringType, | ||
}, | ||
}, | ||
} | ||
``` | ||
|
||
The call to `path.MatchRoot()` which matches the location of `example_root_attribute` string value is: | ||
|
||
```go | ||
path.MatchRoot("example_root_attribute") | ||
``` | ||
|
||
For blocks, the beginning of a path expression is similarly defined. Attribute and block names cannot overlap, so the framework automatically handles whether a path expression is referring to an attribute or block to start. | ||
|
||
Given this example schema with a root block named `example_root_block`: | ||
|
||
```go | ||
tfsdk.Schema{ | ||
Blocks: map[string]tfsdk.Block{ | ||
"example_root_block": { | ||
Attributes: map[string]tfsdk.Attribute{/* ... */}, | ||
NestingMode: tfsdk.BlockNestingModeList, | ||
}, | ||
}, | ||
} | ||
``` | ||
|
||
The call to `path.MatchRoot()` which matches the location of `example_root_block` list value is: | ||
|
||
```go | ||
path.MatchRoot("example_root_block") | ||
``` | ||
|
||
Once a `path.Expression` is started, it supports a builder pattern, which allows for chaining method calls to construct a full path. | ||
|
||
This example shows a hypothetical path expression that points to any element of a list attribute to highlight the builder pattern: | ||
|
||
```go | ||
path.MatchRoot("example_list_attribute").AtAnyListIndex() | ||
``` | ||
|
||
This pattern can be extended to as many calls as necessary. The [Building Expression Steps section](#building-expression-steps) covers the different framework schema types and any special path step methods. | ||
|
||
### Building Relative Path Expressions | ||
|
||
Relative path expressions are, by nature, contextual to the actual path where they are defined in a schema. Call the [`path.MatchRelative()` function](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/path#MatchRelative) to begin a relative path expression. | ||
|
||
This example shows a relative path expression which references a child attribute: | ||
|
||
```go | ||
tfsdk.Schema{ | ||
Attributes: map[string]tfsdk.Attribute{ | ||
"root_list_attribute": { | ||
Attributes: tfsdk.ListNestedAttributes(map[string]tfsdk.Attribute{ | ||
"nested_list_attribute": { | ||
Attributes: tfsdk.ListNestedAttributes(map[string]tfsdk.Attribute{ | ||
"deeply_nested_string_attribute": { | ||
Required: true, | ||
Type: types.StringType, | ||
}, | ||
}), | ||
Required: true, | ||
Validators: []tfsdk.AttributeValidator{ | ||
exampleValidatorThatAcceptsExpressions( | ||
path.MatchRelative().AtAnyListIndex().AtName("deeply_nested_string_attribute"), | ||
), | ||
}, | ||
}, | ||
"nested_string_attribute": { | ||
Required: true, | ||
Type: types.StringType, | ||
}, | ||
}), | ||
Required: true, | ||
}, | ||
}, | ||
} | ||
``` | ||
|
||
This example shows a relative path expression which references a different attribute within the same list index: | ||
|
||
```go | ||
tfsdk.Schema{ | ||
Attributes: map[string]tfsdk.Attribute{ | ||
"root_list_attribute": { | ||
Attributes: tfsdk.ListNestedAttributes(map[string]tfsdk.Attribute{ | ||
"nested_list_attribute": { | ||
Attributes: tfsdk.ListNestedAttributes(map[string]tfsdk.Attribute{ | ||
"deeply_nested_string_attribute": { | ||
Required: true, | ||
Type: types.StringType, | ||
}, | ||
}), | ||
Required: true, | ||
Validators: []tfsdk.AttributeValidator{ | ||
exampleValidatorThatAcceptsExpressions( | ||
path.MatchRelative().AtParent().AtName("nested_string_attribute"), | ||
), | ||
}, | ||
}, | ||
"nested_string_attribute": { | ||
Required: true, | ||
Type: types.StringType, | ||
}, | ||
}), | ||
Required: true, | ||
}, | ||
}, | ||
} | ||
``` | ||
|
||
### Building Expression Steps | ||
|
||
Expressions follow similar schema type rules as paths, in particular [Building Attribute Paths](/plugin/framework/paths#building-attribute-paths), [Building Nested Attribute Paths](/plugin/framework/paths#building-nested-attribute-paths), and [Building Block Paths](/plugin/framework/paths#building-block-paths). | ||
|
||
The following list shows the [`path.Expression` type](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/path#Expression) methods that behave similar to [`path.Path` type](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/path#Path) methods. | ||
|
||
- `AtListIndex()` | ||
- `AtMapKey()` | ||
- `AtName()` | ||
- `AtSetValue()` | ||
|
||
The following table shows the additional [`path.Expression` type](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/path#Expression) methods and their descriptions. | ||
|
||
| Expression Method | Description | | ||
| ------------------ | ----------- | | ||
| `AtAnyListIndex()` | Will return matches for any list index. Can be used anywhere `AtListIndex()` can be used. | | ||
| `AtAnyMapKey()` | Will return matches for any map key. Can be used anywhere `AtMapKey()` can be used. | | ||
| `AtAnySetValue()` | Will return matches for any set value. Can be used anywhere `AtSetValue()` can be used. | | ||
| `AtParent()` | Will remove the last expression step, or put differently, will match the path closer to the root of the schema. | | ||
|
Oops, something went wrong.