Skip to content

Commit 45d8f28

Browse files
Ensure validate called during tfgen (#1854)
fixes #1852 #1669 removed the runtime calls to `InternalValidate` to speed up provider startup. This assumed it was called during tfgen but it turns out it was not. This introduces an explicit call to `InternalValidate` during tfgen. Thanks to @t0yv0 for prompting the investigation and @iwahbe for helping with the muxer. To facilitate that, I've added `InternalValidate` to the shim Provider interface. Technically breaking but seems unlikely to be depended on externally. Calling `Validate` does not do the job as that requires passing in a valid config which is not available during tfgen. I've added an e2e test for an sdk provider, need to add one for a pf provider. --------- Co-authored-by: Ian Wahbe <[email protected]>
1 parent 69f75b8 commit 45d8f28

File tree

19 files changed

+354
-19
lines changed

19 files changed

+354
-19
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*/cmd/*/Pulumi.yaml
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# testprovider_sdkv2
2+
3+
Defines a provider using `github.com/hashicorp/terraform-plugin-sdk/v2` that is dedicated to testing the features of
4+
`pulumi-terraform-bridge`. Specifically the provider is crafted to support `ProgramTest` tests that exercise it together
5+
with the latest Pulumi CLI. These tests verify that the bridged providers integrate correctly with the engine.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright 2016-2022, Pulumi Corporation.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package main
16+
17+
import (
18+
_ "embed"
19+
20+
tpinvschema "github.com/pulumi/pulumi-terraform-bridge/v3/internal/testprovider_invalid_schema"
21+
"github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfbridge"
22+
)
23+
24+
//go:embed schema.json
25+
var pulumiSchema []byte
26+
27+
func main() {
28+
tfbridge.Main("tpinvschema", "1.0.0", tpinvschema.ProviderInfo(), pulumiSchema)
29+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
{
2+
"name": "tpinvschema",
3+
"attribution": "This Pulumi package is based on the [`tpinvschema` Terraform Provider](https://github.com/terraform-providers/terraform-provider-tpinvschema).",
4+
"meta": {
5+
"moduleFormat": "(.*)(?:/[^/]*)"
6+
},
7+
"language": {
8+
"nodejs": {
9+
"readme": "\u003e This provider is a derived work of the [Terraform Provider](https://github.com/terraform-providers/terraform-provider-tpinvschema)\n\u003e distributed under [MPL 2.0](https://www.mozilla.org/en-US/MPL/2.0/). If you encounter a bug or missing feature,\n\u003e first check the [`pulumi-tpinvschema` repo](/issues); however, if that doesn't turn up anything,\n\u003e please consult the source [`terraform-provider-tpinvschema` repo](https://github.com/terraform-providers/terraform-provider-tpinvschema/issues).",
10+
"compatibility": "tfbridge20",
11+
"disableUnionOutputTypes": true
12+
},
13+
"python": {
14+
"readme": "\u003e This provider is a derived work of the [Terraform Provider](https://github.com/terraform-providers/terraform-provider-tpinvschema)\n\u003e distributed under [MPL 2.0](https://www.mozilla.org/en-US/MPL/2.0/). If you encounter a bug or missing feature,\n\u003e first check the [`pulumi-tpinvschema` repo](/issues); however, if that doesn't turn up anything,\n\u003e please consult the source [`terraform-provider-tpinvschema` repo](https://github.com/terraform-providers/terraform-provider-tpinvschema/issues).",
15+
"compatibility": "tfbridge20",
16+
"pyproject": {}
17+
}
18+
},
19+
"config": {},
20+
"provider": {
21+
"description": "The provider type for the tpinvschema package. By default, resources use package-wide configuration\nsettings, however an explicit `Provider` instance may be created and passed during resource\nconstruction to achieve fine-grained programmatic control over provider settings. See the\n[documentation](https://www.pulumi.com/docs/reference/programming-model/#providers) for more information.\n"
22+
},
23+
"resources": {
24+
"tpinvschema:index/invalid_res:invalid_res": {
25+
"properties": {
26+
"blockStringProp": {
27+
"type": "string"
28+
},
29+
"computedDefaultProp": {
30+
"type": "string"
31+
},
32+
"maxItemsStringProp": {
33+
"type": "string"
34+
},
35+
"optAndReqProp": {
36+
"type": "string"
37+
}
38+
},
39+
"required": [
40+
"blockStringProp",
41+
"computedDefaultProp",
42+
"maxItemsStringProp"
43+
],
44+
"inputProperties": {
45+
"optAndReqProp": {
46+
"type": "string"
47+
}
48+
},
49+
"stateInputs": {
50+
"description": "Input properties used for looking up and filtering invalid_res resources.\n",
51+
"properties": {
52+
"blockStringProp": {
53+
"type": "string"
54+
},
55+
"computedDefaultProp": {
56+
"type": "string"
57+
},
58+
"maxItemsStringProp": {
59+
"type": "string"
60+
},
61+
"optAndReqProp": {
62+
"type": "string"
63+
}
64+
},
65+
"type": "object"
66+
}
67+
}
68+
}
69+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2016-2023, Pulumi Corporation.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package main
16+
17+
import (
18+
tpinvschema "github.com/pulumi/pulumi-terraform-bridge/v3/internal/testprovider_invalid_schema"
19+
"github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfgen"
20+
)
21+
22+
func main() {
23+
tfgen.Main("tpinvschema", "1.0.0", tpinvschema.ProviderInfo())
24+
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// Copyright 2016-2023, Pulumi Corporation.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package tpinvschema
16+
17+
import (
18+
"context"
19+
20+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
21+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
22+
)
23+
24+
// An assortment of invalid resources according to
25+
// https://github.com/pulumi/terraform-plugin-sdk/blob/b374785cb6462f8d89eb31d4874a9e3228d74633/helper/schema/resource.go#L1132
26+
//
27+
//nolint:lll
28+
func Provider() *schema.Provider {
29+
return &schema.Provider{
30+
Schema: map[string]*schema.Schema{},
31+
ResourcesMap: map[string]*schema.Resource{
32+
"invalid_res": {
33+
Schema: map[string]*schema.Schema{
34+
"opt_and_req_prop": {
35+
Type: schema.TypeString,
36+
Optional: true,
37+
Required: true,
38+
},
39+
},
40+
Create: func(*schema.ResourceData, interface{}) error { return nil },
41+
Update: func(*schema.ResourceData, interface{}) error { return nil },
42+
Read: func(*schema.ResourceData, interface{}) error { return nil },
43+
Delete: func(*schema.ResourceData, interface{}) error { return nil },
44+
},
45+
"no_read_res": {
46+
Schema: map[string]*schema.Schema{},
47+
Create: func(*schema.ResourceData, interface{}) error { return nil },
48+
Delete: func(*schema.ResourceData, interface{}) error { return nil },
49+
},
50+
"block_string_res": {
51+
Schema: map[string]*schema.Schema{
52+
"block_string_prop": {
53+
Type: schema.TypeString,
54+
Required: true,
55+
ConfigMode: schema.SchemaConfigModeBlock,
56+
Elem: &schema.Schema{
57+
Type: schema.TypeString,
58+
},
59+
},
60+
},
61+
Create: func(*schema.ResourceData, interface{}) error { return nil },
62+
Update: func(*schema.ResourceData, interface{}) error { return nil },
63+
Read: func(*schema.ResourceData, interface{}) error { return nil },
64+
Delete: func(*schema.ResourceData, interface{}) error { return nil },
65+
},
66+
"computed_default_res": {
67+
Schema: map[string]*schema.Schema{
68+
"computed_default_prop": {
69+
Type: schema.TypeString,
70+
Computed: true,
71+
Default: "default",
72+
},
73+
},
74+
Create: func(*schema.ResourceData, interface{}) error { return nil },
75+
Read: func(*schema.ResourceData, interface{}) error { return nil },
76+
Delete: func(*schema.ResourceData, interface{}) error { return nil },
77+
},
78+
"max_string_res": {
79+
Schema: map[string]*schema.Schema{
80+
"max_string_prop": {
81+
Type: schema.TypeString,
82+
MaxItems: 1,
83+
Optional: true,
84+
},
85+
},
86+
Create: func(*schema.ResourceData, interface{}) error { return nil },
87+
Update: func(*schema.ResourceData, interface{}) error { return nil },
88+
Read: func(*schema.ResourceData, interface{}) error { return nil },
89+
Delete: func(*schema.ResourceData, interface{}) error { return nil },
90+
},
91+
"create_and_create_context_res": {
92+
Schema: map[string]*schema.Schema{},
93+
Create: func(*schema.ResourceData, interface{}) error { return nil },
94+
Read: func(*schema.ResourceData, interface{}) error { return nil },
95+
Delete: func(*schema.ResourceData, interface{}) error { return nil },
96+
CreateContext: func(context.Context, *schema.ResourceData, interface{}) diag.Diagnostics {
97+
return nil
98+
},
99+
},
100+
},
101+
}
102+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright 2016-2023, Pulumi Corporation.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package tpinvschema
16+
17+
import (
18+
"github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfbridge"
19+
shim "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfshim"
20+
sdkv2 "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfshim/sdk-v2"
21+
"github.com/pulumi/pulumi/sdk/v3/go/common/resource"
22+
)
23+
24+
func ProviderInfo() tfbridge.ProviderInfo {
25+
prov := tfbridge.ProviderInfo{
26+
P: sdkv2.NewProvider(Provider()),
27+
Name: "tpinvschema",
28+
29+
PreConfigureCallback: func(vars resource.PropertyMap, config shim.ResourceConfig) error {
30+
return nil
31+
},
32+
Resources: map[string]*tfbridge.ResourceInfo{
33+
"invalid_res": {
34+
Tok: tfbridge.MakeResource("tpinvschema", "index", "invalid_res"),
35+
},
36+
},
37+
}
38+
39+
return prov
40+
}

pf/internal/schemashim/provider.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package schemashim
1616

1717
import (
1818
"context"
19+
1920
shim "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfshim"
2021

2122
pfprovider "github.com/hashicorp/terraform-plugin-framework/provider"
@@ -59,6 +60,10 @@ func (p *SchemaOnlyProvider) DataSourcesMap() shim.ResourceMap {
5960
return &schemaOnlyDataSourceMap{dataSources}
6061
}
6162

63+
func (p *SchemaOnlyProvider) InternalValidate() error {
64+
return nil
65+
}
66+
6267
func (p *SchemaOnlyProvider) Validate(context.Context, shim.ResourceConfig) ([]string, []error) {
6368
panic("schemaOnlyProvider does not implement runtime operation Validate")
6469
}

pf/tfgen/main.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package tfgen
1616

1717
import (
1818
"fmt"
19+
"os"
1920

2021
"github.com/pulumi/pulumi/sdk/v3/go/common/util/contract"
2122

@@ -39,7 +40,6 @@ func Main(provider string, info sdkBridge.ProviderInfo) {
3940
version := info.Version
4041

4142
tfgen.MainWithCustomGenerate(provider, version, info, func(opts tfgen.GeneratorOptions) error {
42-
4343
if info.MetadataInfo == nil {
4444
return fmt.Errorf("ProviderInfo.MetadataInfo is required and cannot be nil")
4545
}
@@ -83,8 +83,17 @@ func MainWithMuxer(provider string, info sdkBridge.ProviderInfo) {
8383
shim, ok := info.P.(*pfmuxer.ProviderShim)
8484
contract.Assertf(ok, "MainWithMuxer must have a ProviderInfo.P created with AugmentShimWithPF")
8585

86-
tfgen.MainWithCustomGenerate(provider, info.Version, info, func(opts tfgen.GeneratorOptions) error {
86+
// Validate any sdk providers that are being muxed in.
87+
for _, prov := range shim.MuxedProviders {
88+
err := prov.InternalValidate()
89+
if err != nil {
90+
_, fmterr := fmt.Fprintf(os.Stderr, "Internal validation of the provider failed: %v\n", err)
91+
contract.IgnoreError(fmterr)
92+
os.Exit(-1)
93+
}
94+
}
8795

96+
tfgen.MainWithCustomGenerate(provider, info.Version, info, func(opts tfgen.GeneratorOptions) error {
8897
if info.MetadataInfo == nil {
8998
return fmt.Errorf("ProviderInfo.MetadataInfo is required and cannot be nil")
9099
}

0 commit comments

Comments
 (0)