-
Notifications
You must be signed in to change notification settings - Fork 114
/
resource_pet.go
158 lines (133 loc) · 4.94 KB
/
resource_pet.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package provider
import (
"context"
"fmt"
"strings"
petname "github.com/dustinkirkland/golang-petname"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/provider"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/terraform-providers/terraform-provider-random/internal/planmodifiers"
)
var _ provider.ResourceType = (*petResourceType)(nil)
type petResourceType struct{}
func (r *petResourceType) GetSchema(context.Context) (tfsdk.Schema, diag.Diagnostics) {
return tfsdk.Schema{
Description: "The resource `random_pet` generates random pet names that are intended to be used as " +
"unique identifiers for other resources.\n" +
"\n" +
"This resource can be used in conjunction with resources that have the `create_before_destroy` " +
"lifecycle flag set, to avoid conflicts with unique names during the brief period where both the old " +
"and new resources exist concurrently.",
Attributes: map[string]tfsdk.Attribute{
"keepers": {
Description: "Arbitrary map of values that, when changed, will trigger recreation of " +
"resource. See [the main provider documentation](../index.html) for more information.",
Type: types.MapType{
ElemType: types.StringType,
},
Optional: true,
PlanModifiers: []tfsdk.AttributePlanModifier{
planmodifiers.RequiresReplaceIfValuesNotNull(),
},
},
"length": {
Description: "The length (in words) of the pet name. Defaults to 2",
Type: types.Int64Type,
Optional: true,
Computed: true,
PlanModifiers: []tfsdk.AttributePlanModifier{
planmodifiers.DefaultValue(types.Int64{Value: 2}),
planmodifiers.RequiresReplace(),
},
},
"prefix": {
Description: "A string to prefix the name with.",
Type: types.StringType,
Optional: true,
PlanModifiers: []tfsdk.AttributePlanModifier{resource.RequiresReplace()},
},
"separator": {
Description: "The character to separate words in the pet name. Defaults to \"-\"",
Type: types.StringType,
Optional: true,
Computed: true,
PlanModifiers: []tfsdk.AttributePlanModifier{
planmodifiers.DefaultValue(types.String{Value: "-"}),
planmodifiers.RequiresReplace(),
},
},
"id": {
Description: "The random pet name.",
Type: types.StringType,
Computed: true,
PlanModifiers: []tfsdk.AttributePlanModifier{
resource.UseStateForUnknown(),
},
},
},
}, nil
}
func (r *petResourceType) NewResource(_ context.Context, p provider.Provider) (resource.Resource, diag.Diagnostics) {
return &petResource{}, nil
}
var _ resource.Resource = (*petResource)(nil)
type petResource struct{}
func (r *petResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
// This is necessary to ensure each call to petname is properly randomised:
// the library uses `rand.Intn()` and does NOT seed `rand.Seed()` by default,
// so this call takes care of that.
petname.NonDeterministicMode()
var plan petModelV0
diags := req.Plan.Get(ctx, &plan)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
length := plan.Length.Value
separator := plan.Separator.Value
prefix := plan.Prefix.Value
pet := strings.ToLower(petname.Generate(int(length), separator))
pn := petModelV0{
Keepers: plan.Keepers,
Length: types.Int64{Value: length},
Separator: types.String{Value: separator},
}
if prefix != "" {
pet = fmt.Sprintf("%s%s%s", prefix, separator, pet)
pn.Prefix.Value = prefix
} else {
pn.Prefix.Null = true
}
pn.ID.Value = pet
diags = resp.State.Set(ctx, pn)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
}
// Read does not need to perform any operations as the state in ReadResourceResponse is already populated.
func (r *petResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
}
// Update ensures the plan value is copied to the state to complete the update.
func (r *petResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
var model petModelV0
resp.Diagnostics.Append(req.Plan.Get(ctx, &model)...)
if resp.Diagnostics.HasError() {
return
}
resp.Diagnostics.Append(resp.State.Set(ctx, &model)...)
}
// Delete does not need to explicitly call resp.State.RemoveResource() as this is automatically handled by the
// [framework](https://github.com/hashicorp/terraform-plugin-framework/pull/301).
func (r *petResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
}
type petModelV0 struct {
ID types.String `tfsdk:"id"`
Keepers types.Map `tfsdk:"keepers"`
Length types.Int64 `tfsdk:"length"`
Prefix types.String `tfsdk:"prefix"`
Separator types.String `tfsdk:"separator"`
}