Skip to content

Commit e6592dc

Browse files
Paddypaultyng
andauthored
Add support for provider metadata to modules. (#22583)
Implement a new provider_meta block in the terraform block of modules, allowing provider-keyed metadata to be communicated from HCL to provider binaries. Bundled in this change for minimal protocol version bumping is the addition of markdown support for attribute descriptions and the ability to indicate when an attribute is deprecated, so this information can be shown in the schema dump. Co-authored-by: Paul Tyng <paul@paultyng.net>
1 parent 4654b45 commit e6592dc

Some content is hidden

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

56 files changed

+2457
-246
lines changed

builtin/providers/test/provider.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ func Provider() terraform.ResourceProvider {
1616
Optional: true,
1717
},
1818
},
19+
ProviderMetaSchema: map[string]*schema.Schema{
20+
// Optionally allow specifying information at a module-level
21+
"foo": {
22+
Type: schema.TypeString,
23+
Optional: true,
24+
},
25+
},
1926
ResourcesMap: map[string]*schema.Resource{
2027
"test_resource": testResource(),
2128
"test_resource_gh12183": testResourceGH12183(),
@@ -36,6 +43,7 @@ func Provider() terraform.ResourceProvider {
3643
"test_resource_computed_set": testResourceComputedSet(),
3744
"test_resource_config_mode": testResourceConfigMode(),
3845
"test_resource_nested_id": testResourceNestedId(),
46+
"test_resource_provider_meta": testResourceProviderMeta(),
3947
"test_undeleteable": testResourceUndeleteable(),
4048
"test_resource_required_min": testResourceRequiredMin(),
4149
},
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package test
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/hashicorp/terraform/helper/schema"
7+
)
8+
9+
func testResourceProviderMeta() *schema.Resource {
10+
return &schema.Resource{
11+
Create: testResourceProviderMetaCreate,
12+
Read: testResourceProviderMetaRead,
13+
Update: testResourceProviderMetaUpdate,
14+
Delete: testResourceProviderMetaDelete,
15+
16+
Importer: &schema.ResourceImporter{
17+
State: schema.ImportStatePassthrough,
18+
},
19+
20+
Schema: map[string]*schema.Schema{
21+
"optional": {
22+
Type: schema.TypeString,
23+
Optional: true,
24+
},
25+
},
26+
}
27+
}
28+
29+
type providerMeta struct {
30+
Foo string `cty:"foo"`
31+
}
32+
33+
func testResourceProviderMetaCreate(d *schema.ResourceData, meta interface{}) error {
34+
d.SetId("testId")
35+
var m providerMeta
36+
37+
err := d.GetProviderMeta(&m)
38+
if err != nil {
39+
return err
40+
}
41+
42+
if m.Foo != "bar" {
43+
return fmt.Errorf("expected provider_meta.foo to be %q, was %q",
44+
"bar", m.Foo)
45+
}
46+
47+
return testResourceProviderMetaRead(d, meta)
48+
}
49+
50+
func testResourceProviderMetaRead(d *schema.ResourceData, meta interface{}) error {
51+
var m providerMeta
52+
53+
err := d.GetProviderMeta(&m)
54+
if err != nil {
55+
return err
56+
}
57+
58+
if m.Foo != "bar" {
59+
return fmt.Errorf("expected provider_meta.foo to be %q, was %q",
60+
"bar", m.Foo)
61+
}
62+
63+
return nil
64+
}
65+
66+
func testResourceProviderMetaUpdate(d *schema.ResourceData, meta interface{}) error {
67+
var m providerMeta
68+
69+
err := d.GetProviderMeta(&m)
70+
if err != nil {
71+
return err
72+
}
73+
74+
if m.Foo != "bar" {
75+
return fmt.Errorf("expected provider_meta.foo to be %q, was %q",
76+
"bar", m.Foo)
77+
}
78+
return testResourceProviderMetaRead(d, meta)
79+
}
80+
81+
func testResourceProviderMetaDelete(d *schema.ResourceData, meta interface{}) error {
82+
d.SetId("")
83+
var m providerMeta
84+
85+
err := d.GetProviderMeta(&m)
86+
if err != nil {
87+
return err
88+
}
89+
90+
if m.Foo != "bar" {
91+
return fmt.Errorf("expected provider_meta.foo to be %q, was %q",
92+
"bar", m.Foo)
93+
}
94+
return nil
95+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package test
2+
3+
import (
4+
"strings"
5+
"testing"
6+
7+
"github.com/hashicorp/terraform/helper/resource"
8+
)
9+
10+
func TestResourceProviderMeta_basic(t *testing.T) {
11+
resource.UnitTest(t, resource.TestCase{
12+
Providers: testAccProviders,
13+
CheckDestroy: testAccCheckResourceDestroy,
14+
Steps: []resource.TestStep{
15+
resource.TestStep{
16+
Config: strings.TrimSpace(`
17+
terraform {
18+
provider_meta "test" {
19+
foo = "bar"
20+
}
21+
}
22+
23+
resource "test_resource_provider_meta" "foo" {
24+
}
25+
`),
26+
},
27+
},
28+
})
29+
}

command/jsonprovider/attribute.go

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,23 @@ import (
77
)
88

99
type attribute struct {
10-
AttributeType json.RawMessage `json:"type,omitempty"`
11-
Description string `json:"description,omitempty"`
12-
Required bool `json:"required,omitempty"`
13-
Optional bool `json:"optional,omitempty"`
14-
Computed bool `json:"computed,omitempty"`
15-
Sensitive bool `json:"sensitive,omitempty"`
10+
AttributeType json.RawMessage `json:"type,omitempty"`
11+
Description string `json:"description,omitempty"`
12+
DescriptionKind string `json:"description_kind,omitempty"`
13+
Deprecated bool `json:"deprecated,omitempty"`
14+
Required bool `json:"required,omitempty"`
15+
Optional bool `json:"optional,omitempty"`
16+
Computed bool `json:"computed,omitempty"`
17+
Sensitive bool `json:"sensitive,omitempty"`
18+
}
19+
20+
func marshalStringKind(sk configschema.StringKind) string {
21+
switch sk {
22+
default:
23+
return "plain"
24+
case configschema.StringMarkdown:
25+
return "markdown"
26+
}
1627
}
1728

1829
func marshalAttribute(attr *configschema.Attribute) *attribute {
@@ -21,11 +32,13 @@ func marshalAttribute(attr *configschema.Attribute) *attribute {
2132
attrTy, _ := attr.Type.MarshalJSON()
2233

2334
return &attribute{
24-
AttributeType: attrTy,
25-
Description: attr.Description,
26-
Required: attr.Required,
27-
Optional: attr.Optional,
28-
Computed: attr.Computed,
29-
Sensitive: attr.Sensitive,
35+
AttributeType: attrTy,
36+
Description: attr.Description,
37+
DescriptionKind: marshalStringKind(attr.DescriptionKind),
38+
Required: attr.Required,
39+
Optional: attr.Optional,
40+
Computed: attr.Computed,
41+
Sensitive: attr.Sensitive,
42+
Deprecated: attr.Deprecated,
3043
}
3144
}

command/jsonprovider/attribute_test.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,19 @@ func TestMarshalAttribute(t *testing.T) {
1818
{
1919
&configschema.Attribute{Type: cty.String, Optional: true, Computed: true},
2020
&attribute{
21-
AttributeType: json.RawMessage(`"string"`),
22-
Optional: true,
23-
Computed: true,
21+
AttributeType: json.RawMessage(`"string"`),
22+
Optional: true,
23+
Computed: true,
24+
DescriptionKind: "plain",
2425
},
2526
},
2627
{ // collection types look a little odd.
2728
&configschema.Attribute{Type: cty.Map(cty.String), Optional: true, Computed: true},
2829
&attribute{
29-
AttributeType: json.RawMessage(`["map","string"]`),
30-
Optional: true,
31-
Computed: true,
30+
AttributeType: json.RawMessage(`["map","string"]`),
31+
Optional: true,
32+
Computed: true,
33+
DescriptionKind: "plain",
3234
},
3335
},
3436
}

command/jsonprovider/block.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@ import (
55
)
66

77
type block struct {
8-
Attributes map[string]*attribute `json:"attributes,omitempty"`
9-
BlockTypes map[string]*blockType `json:"block_types,omitempty"`
8+
Attributes map[string]*attribute `json:"attributes,omitempty"`
9+
BlockTypes map[string]*blockType `json:"block_types,omitempty"`
10+
Description string `json:"description,omitempty"`
11+
DescriptionKind string `json:"description_kind,omitempty"`
12+
Deprecated bool `json:"deprecated,omitempty"`
1013
}
1114

1215
type blockType struct {
@@ -48,7 +51,12 @@ func marshalBlock(configBlock *configschema.Block) *block {
4851
return &block{}
4952
}
5053

51-
var ret block
54+
ret := block{
55+
Deprecated: configBlock.Deprecated,
56+
Description: configBlock.Description,
57+
DescriptionKind: marshalStringKind(configBlock.DescriptionKind),
58+
}
59+
5260
if len(configBlock.Attributes) > 0 {
5361
attrs := make(map[string]*attribute, len(configBlock.Attributes))
5462
for k, attr := range configBlock.Attributes {

command/jsonprovider/block_test.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,20 +39,22 @@ func TestMarshalBlock(t *testing.T) {
3939
},
4040
Want: &block{
4141
Attributes: map[string]*attribute{
42-
"ami": {AttributeType: json.RawMessage(`"string"`), Optional: true},
43-
"id": {AttributeType: json.RawMessage(`"string"`), Optional: true, Computed: true},
42+
"ami": {AttributeType: json.RawMessage(`"string"`), Optional: true, DescriptionKind: "plain"},
43+
"id": {AttributeType: json.RawMessage(`"string"`), Optional: true, Computed: true, DescriptionKind: "plain"},
4444
},
4545
BlockTypes: map[string]*blockType{
4646
"network_interface": {
4747
NestingMode: "list",
4848
Block: &block{
4949
Attributes: map[string]*attribute{
50-
"description": {AttributeType: json.RawMessage(`"string"`), Optional: true},
51-
"device_index": {AttributeType: json.RawMessage(`"string"`), Optional: true},
50+
"description": {AttributeType: json.RawMessage(`"string"`), Optional: true, DescriptionKind: "plain"},
51+
"device_index": {AttributeType: json.RawMessage(`"string"`), Optional: true, DescriptionKind: "plain"},
5252
},
53+
DescriptionKind: "plain",
5354
},
5455
},
5556
},
57+
DescriptionKind: "plain",
5658
},
5759
},
5860
}

command/jsonprovider/provider_test.go

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,12 @@ func TestMarshalProvider(t *testing.T) {
2828
Block: &block{
2929
Attributes: map[string]*attribute{
3030
"region": {
31-
AttributeType: json.RawMessage(`"string"`),
32-
Required: true,
31+
AttributeType: json.RawMessage(`"string"`),
32+
Required: true,
33+
DescriptionKind: "plain",
3334
},
3435
},
36+
DescriptionKind: "plain",
3537
},
3638
},
3739
ResourceSchemas: map[string]*schema{
@@ -40,32 +42,38 @@ func TestMarshalProvider(t *testing.T) {
4042
Block: &block{
4143
Attributes: map[string]*attribute{
4244
"id": {
43-
AttributeType: json.RawMessage(`"string"`),
44-
Optional: true,
45-
Computed: true,
45+
AttributeType: json.RawMessage(`"string"`),
46+
Optional: true,
47+
Computed: true,
48+
DescriptionKind: "plain",
4649
},
4750
"ami": {
48-
AttributeType: json.RawMessage(`"string"`),
49-
Optional: true,
51+
AttributeType: json.RawMessage(`"string"`),
52+
Optional: true,
53+
DescriptionKind: "plain",
5054
},
5155
},
5256
BlockTypes: map[string]*blockType{
5357
"network_interface": {
5458
Block: &block{
5559
Attributes: map[string]*attribute{
5660
"device_index": {
57-
AttributeType: json.RawMessage(`"string"`),
58-
Optional: true,
61+
AttributeType: json.RawMessage(`"string"`),
62+
Optional: true,
63+
DescriptionKind: "plain",
5964
},
6065
"description": {
61-
AttributeType: json.RawMessage(`"string"`),
62-
Optional: true,
66+
AttributeType: json.RawMessage(`"string"`),
67+
Optional: true,
68+
DescriptionKind: "plain",
6369
},
6470
},
71+
DescriptionKind: "plain",
6572
},
6673
NestingMode: "list",
6774
},
6875
},
76+
DescriptionKind: "plain",
6977
},
7078
},
7179
},
@@ -75,32 +83,38 @@ func TestMarshalProvider(t *testing.T) {
7583
Block: &block{
7684
Attributes: map[string]*attribute{
7785
"id": {
78-
AttributeType: json.RawMessage(`"string"`),
79-
Optional: true,
80-
Computed: true,
86+
AttributeType: json.RawMessage(`"string"`),
87+
Optional: true,
88+
Computed: true,
89+
DescriptionKind: "plain",
8190
},
8291
"ami": {
83-
AttributeType: json.RawMessage(`"string"`),
84-
Optional: true,
92+
AttributeType: json.RawMessage(`"string"`),
93+
Optional: true,
94+
DescriptionKind: "plain",
8595
},
8696
},
8797
BlockTypes: map[string]*blockType{
8898
"network_interface": {
8999
Block: &block{
90100
Attributes: map[string]*attribute{
91101
"device_index": {
92-
AttributeType: json.RawMessage(`"string"`),
93-
Optional: true,
102+
AttributeType: json.RawMessage(`"string"`),
103+
Optional: true,
104+
DescriptionKind: "plain",
94105
},
95106
"description": {
96-
AttributeType: json.RawMessage(`"string"`),
97-
Optional: true,
107+
AttributeType: json.RawMessage(`"string"`),
108+
Optional: true,
109+
DescriptionKind: "plain",
98110
},
99111
},
112+
DescriptionKind: "plain",
100113
},
101114
NestingMode: "list",
102115
},
103116
},
117+
DescriptionKind: "plain",
104118
},
105119
},
106120
},

0 commit comments

Comments
 (0)