Skip to content

Commit 3a3be3e

Browse files
committed
tfsdk: Migrate server to internal/proto6server package
Reference: #215 This change was accomplished by: - `mkdir internal/proto6server` - `git mv tfsdk/serve* internal/proto6server/` - Replacing `package tfsdk` with `package proto6server` in those moved files - Removing `NewProtocol6Server()`, `Serve()`, and `ServeOpts` in moved files - Adding necessary `tfsdk.` scoping to the now external `tfsdk` package references - Moved necessary unexported methods (e.g. `Schema.tfprotov6Schema()`) to `internal/toproto6` (this package will be expanded further in the future) - Moved attribute plan modification testing (including test plan modifiers) to `internal/proto6server/attribute_plan_modification_test.go` - Moved attribute validation testing (including test validators) to `internal/proto6server/attribute_validation_test.go` - Moved block plan modification testing (including test plan modifiers) to `internal/proto6server/block_plan_modification_test.go` - Moved block validation testing (including test validators) to `internal/proto6server/block_validation_test.go` - Copied tfsdk Config/Plan/State.getAttributeValue methods to internal/proto6server (Config/Plan/State)GetAttributeValue functions temporarily to not export existing methods There are some other planned refactorings in the future for the `internal/proto6server` and `tfsdk` code including: - Creating a shared implementation for the underlying `Config`/`Plan`/`State` details - Creating a `internal/fromproto6` package with protocol version 6 type to framework type conversions - Migrating additional framework type to protocol version 6 code to `internal/toproto6` - Migrating RPC handling into individual code and test files These will be handled separately to reduce review burden, as this change was already very large.
1 parent cd843a9 commit 3a3be3e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+7963
-7735
lines changed

.changelog/pending.txt

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
```release-note:breaking-change
2+
tfsdk: The `NewProtocol6Server()` function, `Serve()` function, and `ServeOpts` type have been removed. Use the `providerserver` package instead.
3+
```
4+
5+
```release-note:breaking-change
6+
tfsdk: The `ModifySchemaPlanRequest`, `ModifySchemaPlanResponse`, `ValidateSchemaRequest`, and `ValidateSchemaResponse` types have been removed. These were not intended for provider developer usage.
7+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
package proto6server
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/hashicorp/terraform-plugin-framework/internal/logging"
8+
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
9+
"github.com/hashicorp/terraform-plugin-framework/types"
10+
)
11+
12+
// AttributeModifyPlan runs all AttributePlanModifiers
13+
//
14+
// TODO: Clean up this abstraction back into an internal Attribute type method.
15+
// The extra Attribute parameter is a carry-over of creating the proto6server
16+
// package from the tfsdk package and not wanting to export the method.
17+
// Reference: https://github.com/hashicorp/terraform-plugin-framework/issues/215
18+
func AttributeModifyPlan(ctx context.Context, a tfsdk.Attribute, req tfsdk.ModifyAttributePlanRequest, resp *ModifySchemaPlanResponse) {
19+
ctx = logging.FrameworkWithAttributePath(ctx, req.AttributePath.String())
20+
21+
attrConfig, diags := ConfigGetAttributeValue(ctx, req.Config, req.AttributePath)
22+
resp.Diagnostics.Append(diags...)
23+
24+
// Only on new errors.
25+
if diags.HasError() {
26+
return
27+
}
28+
req.AttributeConfig = attrConfig
29+
30+
attrState, diags := StateGetAttributeValue(ctx, req.State, req.AttributePath)
31+
resp.Diagnostics.Append(diags...)
32+
33+
// Only on new errors.
34+
if diags.HasError() {
35+
return
36+
}
37+
req.AttributeState = attrState
38+
39+
attrPlan, diags := PlanGetAttributeValue(ctx, req.Plan, req.AttributePath)
40+
resp.Diagnostics.Append(diags...)
41+
42+
// Only on new errors.
43+
if diags.HasError() {
44+
return
45+
}
46+
req.AttributePlan = attrPlan
47+
48+
var requiresReplace bool
49+
for _, planModifier := range a.PlanModifiers {
50+
modifyResp := &tfsdk.ModifyAttributePlanResponse{
51+
AttributePlan: req.AttributePlan,
52+
RequiresReplace: requiresReplace,
53+
}
54+
55+
logging.FrameworkDebug(
56+
ctx,
57+
"Calling provider defined AttributePlanModifier",
58+
map[string]interface{}{
59+
logging.KeyDescription: planModifier.Description(ctx),
60+
},
61+
)
62+
planModifier.Modify(ctx, req, modifyResp)
63+
logging.FrameworkDebug(
64+
ctx,
65+
"Called provider defined AttributePlanModifier",
66+
map[string]interface{}{
67+
logging.KeyDescription: planModifier.Description(ctx),
68+
},
69+
)
70+
71+
req.AttributePlan = modifyResp.AttributePlan
72+
resp.Diagnostics.Append(modifyResp.Diagnostics...)
73+
requiresReplace = modifyResp.RequiresReplace
74+
75+
// Only on new errors.
76+
if modifyResp.Diagnostics.HasError() {
77+
return
78+
}
79+
}
80+
81+
if requiresReplace {
82+
resp.RequiresReplace = append(resp.RequiresReplace, req.AttributePath)
83+
}
84+
85+
setAttrDiags := resp.Plan.SetAttribute(ctx, req.AttributePath, req.AttributePlan)
86+
resp.Diagnostics.Append(setAttrDiags...)
87+
88+
if setAttrDiags.HasError() {
89+
return
90+
}
91+
92+
if a.Attributes == nil || len(a.Attributes.GetAttributes()) == 0 {
93+
return
94+
}
95+
96+
nm := a.Attributes.GetNestingMode()
97+
switch nm {
98+
case tfsdk.NestingModeList:
99+
l, ok := req.AttributePlan.(types.List)
100+
101+
if !ok {
102+
err := fmt.Errorf("unknown attribute value type (%T) for nesting mode (%T) at path: %s", req.AttributePlan, nm, req.AttributePath)
103+
resp.Diagnostics.AddAttributeError(
104+
req.AttributePath,
105+
"Attribute Plan Modification Error",
106+
"Attribute plan modifier cannot walk schema. Report this to the provider developer:\n\n"+err.Error(),
107+
)
108+
109+
return
110+
}
111+
112+
for idx := range l.Elems {
113+
for name, attr := range a.Attributes.GetAttributes() {
114+
attrReq := tfsdk.ModifyAttributePlanRequest{
115+
AttributePath: req.AttributePath.WithElementKeyInt(idx).WithAttributeName(name),
116+
Config: req.Config,
117+
Plan: resp.Plan,
118+
ProviderMeta: req.ProviderMeta,
119+
State: req.State,
120+
}
121+
122+
AttributeModifyPlan(ctx, attr, attrReq, resp)
123+
}
124+
}
125+
case tfsdk.NestingModeSet:
126+
s, ok := req.AttributePlan.(types.Set)
127+
128+
if !ok {
129+
err := fmt.Errorf("unknown attribute value type (%T) for nesting mode (%T) at path: %s", req.AttributePlan, nm, req.AttributePath)
130+
resp.Diagnostics.AddAttributeError(
131+
req.AttributePath,
132+
"Attribute Plan Modification Error",
133+
"Attribute plan modifier cannot walk schema. Report this to the provider developer:\n\n"+err.Error(),
134+
)
135+
136+
return
137+
}
138+
139+
for _, value := range s.Elems {
140+
tfValue, err := value.ToTerraformValue(ctx)
141+
if err != nil {
142+
err := fmt.Errorf("error running ToTerraformValue on element value: %v", value)
143+
resp.Diagnostics.AddAttributeError(
144+
req.AttributePath,
145+
"Attribute Plan Modification Error",
146+
"Attribute plan modification cannot convert element into a Terraform value. Report this to the provider developer:\n\n"+err.Error(),
147+
)
148+
149+
return
150+
}
151+
152+
for name, attr := range a.Attributes.GetAttributes() {
153+
attrReq := tfsdk.ModifyAttributePlanRequest{
154+
AttributePath: req.AttributePath.WithElementKeyValue(tfValue).WithAttributeName(name),
155+
Config: req.Config,
156+
Plan: resp.Plan,
157+
ProviderMeta: req.ProviderMeta,
158+
State: req.State,
159+
}
160+
161+
AttributeModifyPlan(ctx, attr, attrReq, resp)
162+
}
163+
}
164+
case tfsdk.NestingModeMap:
165+
m, ok := req.AttributePlan.(types.Map)
166+
167+
if !ok {
168+
err := fmt.Errorf("unknown attribute value type (%T) for nesting mode (%T) at path: %s", req.AttributePlan, nm, req.AttributePath)
169+
resp.Diagnostics.AddAttributeError(
170+
req.AttributePath,
171+
"Attribute Plan Modification Error",
172+
"Attribute plan modifier cannot walk schema. Report this to the provider developer:\n\n"+err.Error(),
173+
)
174+
175+
return
176+
}
177+
178+
for key := range m.Elems {
179+
for name, attr := range a.Attributes.GetAttributes() {
180+
attrReq := tfsdk.ModifyAttributePlanRequest{
181+
AttributePath: req.AttributePath.WithElementKeyString(key).WithAttributeName(name),
182+
Config: req.Config,
183+
Plan: resp.Plan,
184+
ProviderMeta: req.ProviderMeta,
185+
State: req.State,
186+
}
187+
188+
AttributeModifyPlan(ctx, attr, attrReq, resp)
189+
}
190+
}
191+
case tfsdk.NestingModeSingle:
192+
o, ok := req.AttributePlan.(types.Object)
193+
194+
if !ok {
195+
err := fmt.Errorf("unknown attribute value type (%T) for nesting mode (%T) at path: %s", req.AttributePlan, nm, req.AttributePath)
196+
resp.Diagnostics.AddAttributeError(
197+
req.AttributePath,
198+
"Attribute Plan Modification Error",
199+
"Attribute plan modifier cannot walk schema. Report this to the provider developer:\n\n"+err.Error(),
200+
)
201+
202+
return
203+
}
204+
205+
if len(o.Attrs) == 0 {
206+
return
207+
}
208+
209+
for name, attr := range a.Attributes.GetAttributes() {
210+
attrReq := tfsdk.ModifyAttributePlanRequest{
211+
AttributePath: req.AttributePath.WithAttributeName(name),
212+
Config: req.Config,
213+
Plan: resp.Plan,
214+
ProviderMeta: req.ProviderMeta,
215+
State: req.State,
216+
}
217+
218+
AttributeModifyPlan(ctx, attr, attrReq, resp)
219+
}
220+
default:
221+
err := fmt.Errorf("unknown attribute nesting mode (%T: %v) at path: %s", nm, nm, req.AttributePath)
222+
resp.Diagnostics.AddAttributeError(
223+
req.AttributePath,
224+
"Attribute Plan Modification Error",
225+
"Attribute plan modifier cannot walk schema. Report this to the provider developer:\n\n"+err.Error(),
226+
)
227+
228+
return
229+
}
230+
}

0 commit comments

Comments
 (0)