Skip to content

Commit 4ba612d

Browse files
bendbennettbflad
andauthored
Add Description to Timeout Attributes (#52)
* Adding description for each of the timeout attributes (#51) * Adding changelog entries (#51) * Amend attribute description to make valid time units clearer (#51) * Amend attribute description for read and delete to indicate when these timeouts would be applicable (#51) * Adding additional options to allow overriding of default descriptions (#51) * Adding changelog entries (#51) * Fixing changelog entry (#51) * Updating README (#51) * Apply suggestions from code review Co-authored-by: Brian Flad <bflad417@gmail.com> * Updating to latest version of terraform-plugin-framework and fixing tests (#51) --------- Co-authored-by: Brian Flad <bflad417@gmail.com>
1 parent 177b693 commit 4ba612d

9 files changed

+437
-17
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
kind: ENHANCEMENTS
2+
body: 'datasource/timeouts: Add default description for read'
3+
time: 2023-04-28T17:43:31.884258+01:00
4+
custom:
5+
Issue: "51"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
kind: ENHANCEMENTS
2+
body: 'resource/timeouts: Add default description for create, delete, read and update'
3+
time: 2023-04-28T17:44:12.860337+01:00
4+
custom:
5+
Issue: "51"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
kind: ENHANCEMENTS
2+
body: 'resource/timeouts: Add opts for `CreateDescription`, `ReadDescription`, `UpdateDescription`
3+
and `DeleteDescription` to allow overriding of default description'
4+
time: 2023-06-09T11:22:45.08138+01:00
5+
custom:
6+
Issue: "51"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
kind: ENHANCEMENTS
2+
body: 'datasource/timeouts: Add `BlockWithOpts()` and `AttributesWithOpts()` functions
3+
to allow overriding of default description'
4+
time: 2023-06-09T11:24:09.988096+01:00
5+
custom:
6+
Issue: "51"

README.md

+11-3
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,9 @@ data "timeouts_example" "example" {
6060

6161
Use this module to mutate the `schema.Schema`:
6262

63-
You must supply `timeouts.Opts` when calling `timeouts.Block()` on a resource. Alternatively, `timeouts.BlockAll()` will generate attributes for `create`, `read`, `update` and `delete`.
63+
You must supply `timeouts.Opts` when calling `timeouts.Block()` on a resource. The supplied `timeouts.Opts` allows specifying which timeouts to create and whether to override the default description for the timeout.
64+
65+
Alternatively, `timeouts.BlockAll()` will generate attributes for `create`, `read`, `update` and `delete`.
6466

6567
```go
6668
import (
@@ -83,6 +85,8 @@ func (t *exampleResource) Schema(ctx context.Context, req resource.SchemaRequest
8385
8486
The `timeouts.Block()` call does not accept options on a data source as `read` is the only option.
8587
88+
However, the `timeouts.BlockWithOpts()` function is available for overriding the default description.
89+
8690
```go
8791
import (
8892
/* ... */
@@ -126,7 +130,9 @@ data "timeouts_example" "example" {
126130
127131
Use this module to mutate the `schema.Schema` as follows:
128132
129-
You must supply `timeouts.Opts` when calling `timeouts.Attributes()` on a resource.
133+
You must supply `timeouts.Opts` when calling `timeouts.Attributes()` on a resource. The supplied `timeouts.Opts` allows specifying which timeouts to create and whether to override the default description for the timeout.
134+
135+
Alternatively, `timeouts.AttributesAll()` will generate attributes for `create`, `read`, `update` and `delete`.
130136
131137
```go
132138
import (
@@ -144,7 +150,9 @@ func (t *exampleResource) Schema(ctx context.Context, req resource.SchemaRequest
144150
},
145151
```
146152
147-
The `timeouts.Attributes()` call does not accept options on a data source as `read` is the only option.
153+
The `timeouts.Attributes()` call does not accept options on a data source as `read` is the only option.
154+
155+
However, the `timeouts.AttributesWithOpts()` function is available for overriding the default description.
148156
149157
```go
150158
import (

datasource/timeouts/schema.go

+55-9
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,54 @@ const (
1818
attributeNameRead = "read"
1919
)
2020

21+
// Opts is used as an argument to BlockWithOpts and AttributesWithOpts to indicate
22+
// whether supplied descriptions should override default descriptions.
23+
type Opts struct {
24+
ReadDescription string
25+
}
26+
27+
// BlockWithOpts returns a schema.Block containing attributes for `Read`, which is
28+
// defined as types.StringType and optional. A validator is used to verify
29+
// that the value assigned to `Read` can be parsed as time.Duration. The supplied
30+
// Opts are used to override defaults.
31+
func BlockWithOpts(ctx context.Context, opts Opts) schema.Block {
32+
return schema.SingleNestedBlock{
33+
Attributes: attributesMap(opts),
34+
CustomType: Type{
35+
ObjectType: types.ObjectType{
36+
AttrTypes: attrTypesMap(),
37+
},
38+
},
39+
}
40+
}
41+
2142
// Block returns a schema.Block containing attributes for `Read`, which is
2243
// defined as types.StringType and optional. A validator is used to verify
2344
// that the value assigned to `Read` can be parsed as time.Duration.
2445
func Block(ctx context.Context) schema.Block {
2546
return schema.SingleNestedBlock{
26-
Attributes: attributesMap(),
47+
Attributes: attributesMap(Opts{}),
48+
CustomType: Type{
49+
ObjectType: types.ObjectType{
50+
AttrTypes: attrTypesMap(),
51+
},
52+
},
53+
}
54+
}
55+
56+
// AttributesWithOpts returns a schema.SingleNestedAttribute which contains an
57+
// attribute for `Read`, which is defined as types.StringType and optional.
58+
// A validator is used to verify that the value assigned to an attribute
59+
// can be parsed as time.Duration. The supplied Opts are used to override defaults.
60+
func AttributesWithOpts(ctx context.Context, opts Opts) schema.Attribute {
61+
return schema.SingleNestedAttribute{
62+
Attributes: attributesMap(opts),
2763
CustomType: Type{
2864
ObjectType: types.ObjectType{
2965
AttrTypes: attrTypesMap(),
3066
},
3167
},
68+
Optional: true,
3269
}
3370
}
3471

@@ -38,7 +75,7 @@ func Block(ctx context.Context) schema.Block {
3875
// can be parsed as time.Duration.
3976
func Attributes(ctx context.Context) schema.Attribute {
4077
return schema.SingleNestedAttribute{
41-
Attributes: attributesMap(),
78+
Attributes: attributesMap(Opts{}),
4279
CustomType: Type{
4380
ObjectType: types.ObjectType{
4481
AttrTypes: attrTypesMap(),
@@ -48,15 +85,24 @@ func Attributes(ctx context.Context) schema.Attribute {
4885
}
4986
}
5087

51-
func attributesMap() map[string]schema.Attribute {
52-
return map[string]schema.Attribute{
53-
attributeNameRead: schema.StringAttribute{
54-
Optional: true,
55-
Validators: []validator.String{
56-
validators.TimeDuration(),
57-
},
88+
func attributesMap(opts Opts) map[string]schema.Attribute {
89+
attribute := schema.StringAttribute{
90+
Optional: true,
91+
Description: `A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) ` +
92+
`consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are ` +
93+
`"s" (seconds), "m" (minutes), "h" (hours).`,
94+
Validators: []validator.String{
95+
validators.TimeDuration(),
5896
},
5997
}
98+
99+
if opts.ReadDescription != "" {
100+
attribute.Description = opts.ReadDescription
101+
}
102+
103+
return map[string]schema.Attribute{
104+
attributeNameRead: attribute,
105+
}
60106
}
61107

62108
func attrTypesMap() map[string]attr.Type {

datasource/timeouts/schema_test.go

+146
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,75 @@ import (
1717
"github.com/hashicorp/terraform-plugin-framework-timeouts/internal/validators"
1818
)
1919

20+
func TestBlockWithOpts(t *testing.T) {
21+
t.Parallel()
22+
23+
type testCase struct {
24+
opts timeouts.Opts
25+
expected schema.Block
26+
}
27+
tests := map[string]testCase{
28+
"empty-opts": {
29+
opts: timeouts.Opts{},
30+
expected: schema.SingleNestedBlock{
31+
CustomType: timeouts.Type{
32+
ObjectType: types.ObjectType{
33+
AttrTypes: map[string]attr.Type{
34+
"read": types.StringType,
35+
},
36+
},
37+
},
38+
Attributes: map[string]schema.Attribute{
39+
"read": schema.StringAttribute{
40+
Optional: true,
41+
Description: `A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) ` +
42+
`consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are ` +
43+
`"s" (seconds), "m" (minutes), "h" (hours).`,
44+
Validators: []validator.String{
45+
validators.TimeDuration(),
46+
},
47+
},
48+
},
49+
},
50+
},
51+
"read-opts-description": {
52+
opts: timeouts.Opts{
53+
ReadDescription: "read description",
54+
},
55+
expected: schema.SingleNestedBlock{
56+
CustomType: timeouts.Type{
57+
ObjectType: types.ObjectType{
58+
AttrTypes: map[string]attr.Type{
59+
"read": types.StringType,
60+
},
61+
},
62+
},
63+
Attributes: map[string]schema.Attribute{
64+
"read": schema.StringAttribute{
65+
Optional: true,
66+
Description: "read description",
67+
Validators: []validator.String{
68+
validators.TimeDuration(),
69+
},
70+
},
71+
},
72+
},
73+
},
74+
}
75+
76+
for name, test := range tests {
77+
name, test := name, test
78+
t.Run(name, func(t *testing.T) {
79+
t.Parallel()
80+
actual := timeouts.BlockWithOpts(context.Background(), test.opts)
81+
82+
if diff := cmp.Diff(actual, test.expected); diff != "" {
83+
t.Errorf("unexpected block difference: %s", diff)
84+
}
85+
})
86+
}
87+
}
88+
2089
func TestBlock(t *testing.T) {
2190
t.Parallel()
2291

@@ -36,6 +105,9 @@ func TestBlock(t *testing.T) {
36105
Attributes: map[string]schema.Attribute{
37106
"read": schema.StringAttribute{
38107
Optional: true,
108+
Description: `A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) ` +
109+
`consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are ` +
110+
`"s" (seconds), "m" (minutes), "h" (hours).`,
39111
Validators: []validator.String{
40112
validators.TimeDuration(),
41113
},
@@ -58,6 +130,77 @@ func TestBlock(t *testing.T) {
58130
}
59131
}
60132

133+
func TestAttributesWithOpts(t *testing.T) {
134+
t.Parallel()
135+
136+
type testCase struct {
137+
opts timeouts.Opts
138+
expected schema.Attribute
139+
}
140+
tests := map[string]testCase{
141+
"empty-opts": {
142+
opts: timeouts.Opts{},
143+
expected: schema.SingleNestedAttribute{
144+
Attributes: map[string]schema.Attribute{
145+
"read": schema.StringAttribute{
146+
Optional: true,
147+
Description: `A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) ` +
148+
`consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are ` +
149+
`"s" (seconds), "m" (minutes), "h" (hours).`,
150+
Validators: []validator.String{
151+
validators.TimeDuration(),
152+
},
153+
},
154+
},
155+
CustomType: timeouts.Type{
156+
ObjectType: types.ObjectType{
157+
AttrTypes: map[string]attr.Type{
158+
"read": types.StringType,
159+
},
160+
},
161+
},
162+
Optional: true,
163+
},
164+
},
165+
"read-opts-description": {
166+
opts: timeouts.Opts{
167+
ReadDescription: "read description",
168+
},
169+
expected: schema.SingleNestedAttribute{
170+
Attributes: map[string]schema.Attribute{
171+
"read": schema.StringAttribute{
172+
Optional: true,
173+
Description: "read description",
174+
Validators: []validator.String{
175+
validators.TimeDuration(),
176+
},
177+
},
178+
},
179+
CustomType: timeouts.Type{
180+
ObjectType: types.ObjectType{
181+
AttrTypes: map[string]attr.Type{
182+
"read": types.StringType,
183+
},
184+
},
185+
},
186+
Optional: true,
187+
},
188+
},
189+
}
190+
191+
for name, test := range tests {
192+
name, test := name, test
193+
t.Run(name, func(t *testing.T) {
194+
t.Parallel()
195+
actual := timeouts.AttributesWithOpts(context.Background(), test.opts)
196+
197+
if diff := cmp.Diff(actual, test.expected); diff != "" {
198+
t.Errorf("unexpected block difference: %s", diff)
199+
}
200+
})
201+
}
202+
}
203+
61204
func TestAttributes(t *testing.T) {
62205
t.Parallel()
63206

@@ -70,6 +213,9 @@ func TestAttributes(t *testing.T) {
70213
Attributes: map[string]schema.Attribute{
71214
"read": schema.StringAttribute{
72215
Optional: true,
216+
Description: `A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) ` +
217+
`consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are ` +
218+
`"s" (seconds), "m" (minutes), "h" (hours).`,
73219
Validators: []validator.String{
74220
validators.TimeDuration(),
75221
},

0 commit comments

Comments
 (0)