Skip to content

Commit 36fb64f

Browse files
radeksimkodbanck
andauthored
grpcwrap+provider-simple: Test ephemeral resource schemas in v5 protocol (#36878)
* grpcwrap+provider-simple: Test ephemeral resource schemas in v5 protocol * Update internal/command/e2etest/providers_schema_test.go Co-authored-by: Daniel Banck <dbanck@users.noreply.github.com> --------- Co-authored-by: Daniel Banck <dbanck@users.noreply.github.com>
1 parent 1e4df3e commit 36fb64f

File tree

3 files changed

+274
-0
lines changed

3 files changed

+274
-0
lines changed
Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: BUSL-1.1
3+
4+
package e2etest
5+
6+
import (
7+
"bytes"
8+
"encoding/json"
9+
"os"
10+
"path/filepath"
11+
"testing"
12+
13+
"github.com/google/go-cmp/cmp"
14+
"github.com/hashicorp/terraform/internal/e2e"
15+
"github.com/hashicorp/terraform/internal/getproviders"
16+
)
17+
18+
// TestProvidersSchema is a test for `provider schemas -json` subcommand
19+
// which effectively tests much of the schema-related logic underneath
20+
func TestProvidersSchema(t *testing.T) {
21+
if !canRunGoBuild {
22+
// We're running in a separate-build-then-run context, so we can't
23+
// currently execute this test which depends on being able to build
24+
// new executable at runtime.
25+
//
26+
// (See the comment on canRunGoBuild's declaration for more information.)
27+
t.Skip("can't run without building a new provider executable")
28+
}
29+
t.Parallel()
30+
31+
tf := e2e.NewBinary(t, terraformBin, "testdata/provider-plugin")
32+
33+
// In order to do a decent end-to-end test for this case we will need a real
34+
// enough provider plugin to try to run and make sure we are able to
35+
// actually run it. Here will build the simple and simple6 (built with
36+
// protocol v6) providers.
37+
simple6Provider := filepath.Join(tf.WorkDir(), "terraform-provider-simple6")
38+
simple6ProviderExe := e2e.GoBuild("github.com/hashicorp/terraform/internal/provider-simple-v6/main", simple6Provider)
39+
40+
simpleProvider := filepath.Join(tf.WorkDir(), "terraform-provider-simple")
41+
simpleProviderExe := e2e.GoBuild("github.com/hashicorp/terraform/internal/provider-simple/main", simpleProvider)
42+
43+
// Move the provider binaries into a directory that we will point terraform
44+
// to using the -plugin-dir cli flag.
45+
platform := getproviders.CurrentPlatform.String()
46+
hashiDir := "cache/registry.terraform.io/hashicorp/"
47+
if err := os.MkdirAll(tf.Path(hashiDir, "simple6/0.0.1/", platform), os.ModePerm); err != nil {
48+
t.Fatal(err)
49+
}
50+
if err := os.Rename(simple6ProviderExe, tf.Path(hashiDir, "simple6/0.0.1/", platform, "terraform-provider-simple6")); err != nil {
51+
t.Fatal(err)
52+
}
53+
54+
if err := os.MkdirAll(tf.Path(hashiDir, "simple/0.0.1/", platform), os.ModePerm); err != nil {
55+
t.Fatal(err)
56+
}
57+
if err := os.Rename(simpleProviderExe, tf.Path(hashiDir, "simple/0.0.1/", platform, "terraform-provider-simple")); err != nil {
58+
t.Fatal(err)
59+
}
60+
61+
//// INIT
62+
_, stderr, err := tf.Run("init", "-plugin-dir=cache")
63+
if err != nil {
64+
t.Fatalf("unexpected init error: %s\nstderr:\n%s", err, stderr)
65+
}
66+
67+
expectedRawOutput := `{
68+
"format_version": "1.0",
69+
"provider_schemas": {
70+
"registry.terraform.io/hashicorp/simple": {
71+
"provider": {
72+
"version": 0,
73+
"block": {
74+
"description_kind": "plain"
75+
}
76+
},
77+
"resource_schemas": {
78+
"simple_resource": {
79+
"version": 0,
80+
"block": {
81+
"attributes": {
82+
"id": {
83+
"type": "string",
84+
"description_kind": "plain",
85+
"computed": true
86+
},
87+
"value": {
88+
"type": "string",
89+
"description_kind": "plain",
90+
"optional": true
91+
}
92+
},
93+
"description_kind": "plain"
94+
}
95+
}
96+
},
97+
"data_source_schemas": {
98+
"simple_resource": {
99+
"version": 0,
100+
"block": {
101+
"attributes": {
102+
"id": {
103+
"type": "string",
104+
"description_kind": "plain",
105+
"computed": true
106+
},
107+
"value": {
108+
"type": "string",
109+
"description_kind": "plain",
110+
"optional": true
111+
}
112+
},
113+
"description_kind": "plain"
114+
}
115+
}
116+
},
117+
"ephemeral_resource_schemas": {
118+
"simple_resource": {
119+
"version": 0,
120+
"block": {
121+
"attributes": {
122+
"id": {
123+
"type": "string",
124+
"description_kind": "plain",
125+
"computed": true
126+
},
127+
"value": {
128+
"type": "string",
129+
"description_kind": "plain",
130+
"optional": true
131+
}
132+
},
133+
"description_kind": "plain"
134+
}
135+
}
136+
},
137+
"resource_identity_schemas": {
138+
"simple_resource": {
139+
"version": 0,
140+
"attributes": {
141+
"id": {
142+
"type": "string",
143+
"required_for_import": true
144+
}
145+
}
146+
}
147+
}
148+
},
149+
"registry.terraform.io/hashicorp/simple6": {
150+
"provider": {
151+
"version": 0,
152+
"block": {
153+
"description_kind": "plain"
154+
}
155+
},
156+
"resource_schemas": {
157+
"simple_resource": {
158+
"version": 0,
159+
"block": {
160+
"attributes": {
161+
"id": {
162+
"type": "string",
163+
"description_kind": "plain",
164+
"computed": true
165+
},
166+
"value": {
167+
"type": "string",
168+
"description_kind": "plain",
169+
"optional": true
170+
}
171+
},
172+
"description_kind": "plain"
173+
}
174+
}
175+
},
176+
"data_source_schemas": {
177+
"simple_resource": {
178+
"version": 0,
179+
"block": {
180+
"attributes": {
181+
"id": {
182+
"type": "string",
183+
"description_kind": "plain",
184+
"computed": true
185+
},
186+
"value": {
187+
"type": "string",
188+
"description_kind": "plain",
189+
"optional": true
190+
}
191+
},
192+
"description_kind": "plain"
193+
}
194+
}
195+
},
196+
"ephemeral_resource_schemas": {
197+
"simple_resource": {
198+
"version": 0,
199+
"block": {
200+
"attributes": {
201+
"id": {
202+
"type": "string",
203+
"description_kind": "plain",
204+
"computed": true
205+
},
206+
"value": {
207+
"type": "string",
208+
"description_kind": "plain",
209+
"optional": true
210+
}
211+
},
212+
"description_kind": "plain"
213+
}
214+
}
215+
},
216+
"functions": {
217+
"noop": {
218+
"description": "noop takes any single argument and returns the same value",
219+
"return_type": "dynamic",
220+
"parameters": [
221+
{
222+
"name": "noop",
223+
"description": "any value",
224+
"is_nullable": true,
225+
"type": "dynamic"
226+
}
227+
]
228+
}
229+
},
230+
"resource_identity_schemas": {
231+
"simple_resource": {
232+
"version": 0,
233+
"attributes": {
234+
"id": {
235+
"type": "string",
236+
"required_for_import": true
237+
}
238+
}
239+
}
240+
}
241+
}
242+
}
243+
}
244+
`
245+
var expectedOutput bytes.Buffer
246+
err = json.Compact(&expectedOutput, []byte(expectedRawOutput))
247+
if err != nil {
248+
t.Fatal(err)
249+
}
250+
251+
stdout, stderr, err := tf.Run("providers", "schema", "-json")
252+
if err != nil {
253+
t.Fatalf("unexpected error: %s\n%s", err, stderr)
254+
}
255+
256+
var output bytes.Buffer
257+
err = json.Compact(&output, []byte(stdout))
258+
if err != nil {
259+
t.Fatal(err)
260+
}
261+
262+
if diff := cmp.Diff(expectedOutput.String(), output.String()); diff != "" {
263+
t.Fatalf("unexpected schema: %s\n", diff)
264+
}
265+
}

internal/grpcwrap/provider.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,12 @@ func (p *provider) GetSchema(_ context.Context, req *tfplugin5.GetProviderSchema
7373
Block: convert.ConfigSchemaToProto(dat.Body),
7474
}
7575
}
76+
for typ, dat := range p.schema.EphemeralResourceTypes {
77+
resp.EphemeralResourceSchemas[typ] = &tfplugin5.Schema{
78+
Version: int64(dat.Version),
79+
Block: convert.ConfigSchemaToProto(dat.Body),
80+
}
81+
}
7682
if decls, err := convert.FunctionDeclsToProto(p.schema.Functions); err == nil {
7783
resp.Functions = decls
7884
} else {

internal/provider-simple/provider.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ func Provider() providers.Interface {
4646
DataSources: map[string]providers.Schema{
4747
"simple_resource": simpleResource,
4848
},
49+
EphemeralResourceTypes: map[string]providers.Schema{
50+
"simple_resource": simpleResource,
51+
},
4952
ServerCapabilities: providers.ServerCapabilities{
5053
PlanDestroy: true,
5154
},

0 commit comments

Comments
 (0)