@@ -5,28 +5,145 @@ package provider
5
5
6
6
import (
7
7
"context"
8
+ "fmt"
8
9
10
+ "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator"
9
11
"github.com/hashicorp/terraform-plugin-framework/datasource"
12
+ "github.com/hashicorp/terraform-plugin-framework/diag"
13
+ "github.com/hashicorp/terraform-plugin-framework/path"
10
14
"github.com/hashicorp/terraform-plugin-framework/provider"
15
+ "github.com/hashicorp/terraform-plugin-framework/provider/schema"
11
16
"github.com/hashicorp/terraform-plugin-framework/resource"
17
+ "github.com/hashicorp/terraform-plugin-framework/schema/validator"
18
+ "github.com/hashicorp/terraform-plugin-framework/tfsdk"
19
+ "github.com/hashicorp/terraform-plugin-framework/types"
20
+ "github.com/hashicorp/terraform-plugin-log/tflog"
12
21
)
13
22
23
+ type httpProviderConfig struct {
24
+ }
25
+
26
+ type httpProvider struct {
27
+ Hostname string
28
+ RequestHeaders map [string ]string
29
+ }
30
+
31
+ var _ provider.Provider = (* httpProvider )(nil )
32
+
14
33
func New () provider.Provider {
15
34
return & httpProvider {}
16
35
}
17
36
18
- var _ provider.Provider = (* httpProvider )(nil )
37
+ type httpProviderConfigModel struct {
38
+ Host types.List `tfsdk:"host"`
39
+ }
19
40
20
- type httpProvider struct {}
41
+ type httpProviderHostConfigModel struct {
42
+ Name types.String `tfsdk:"name"`
43
+ RequestHeaders types.Map `tfsdk:"request_headers"`
44
+ }
21
45
22
46
func (p * httpProvider ) Metadata (_ context.Context , _ provider.MetadataRequest , resp * provider.MetadataResponse ) {
23
47
resp .TypeName = "http"
24
48
}
25
49
26
- func (p * httpProvider ) Schema (context.Context , provider.SchemaRequest , * provider.SchemaResponse ) {
50
+ func (p * httpProvider ) Schema (_ context.Context , _ provider.SchemaRequest , resp * provider.SchemaResponse ) {
51
+ resp .Schema = schema.Schema {
52
+ Description : "Configures the HTTP provider" ,
53
+ Blocks : map [string ]schema.Block {
54
+ "host" : schema.ListNestedBlock {
55
+ Description : "A host-specific provider configuration." ,
56
+ Validators : []validator.List {
57
+ listvalidator .SizeBetween (0 , 1 ),
58
+ },
59
+ NestedObject : schema.NestedBlockObject {
60
+ Attributes : map [string ]schema.Attribute {
61
+ "name" : schema.StringAttribute {
62
+ Description : `The hostname for which the host configuration should
63
+ take affect. If the name matches an HTTP request URL's hostname, the provider's
64
+ host configuration takes affect (in addition to any data- or resource-specific
65
+ request configuration.` ,
66
+ Required : true ,
67
+ },
68
+ "request_headers" : schema.MapAttribute {
69
+ Description : `A map of request header field names and values to
70
+ include in HTTP requests if/when the request URL's hostname matches the provider
71
+ host configuration name.` ,
72
+ ElementType : types .StringType ,
73
+ Optional : true ,
74
+ Sensitive : true ,
75
+ },
76
+ },
77
+ },
78
+ },
79
+ },
80
+ }
27
81
}
28
82
29
- func (p * httpProvider ) Configure (context.Context , provider.ConfigureRequest , * provider.ConfigureResponse ) {
83
+ func (p * httpProvider ) Configure (ctx context.Context , req provider.ConfigureRequest , res * provider.ConfigureResponse ) {
84
+ tflog .Debug (ctx , "Configuring provider" )
85
+ //p.resetConfig()
86
+
87
+ // Ensure these response values are set before early returns, etc.
88
+ res .DataSourceData = p
89
+ res .ResourceData = p
90
+
91
+ // Load configuration into the model
92
+ var conf httpProviderConfigModel
93
+ res .Diagnostics .Append (req .Config .Get (ctx , & conf )... )
94
+ if res .Diagnostics .HasError () {
95
+ return
96
+ }
97
+ if conf .Host .IsNull () || conf .Host .IsUnknown () || len (conf .Host .Elements ()) == 0 {
98
+ tflog .Debug (ctx , "No host configuration detected; using provider defaults" )
99
+ return
100
+ }
101
+
102
+ // Load proxy configuration into model
103
+ hostConfSlice := make ([]httpProviderHostConfigModel , 1 )
104
+ res .Diagnostics .Append (conf .Host .ElementsAs (ctx , & hostConfSlice , true )... )
105
+ if res .Diagnostics .HasError () {
106
+ return
107
+ }
108
+ if len (hostConfSlice ) != 1 {
109
+ res .Diagnostics .AddAttributeError (
110
+ path .Root ("host" ),
111
+ "Provider Proxy Configuration Handling Error" ,
112
+ "The provider failed to fully load the expected host configuration. " +
113
+ "This is likely a bug in the Terraform Provider and should be reported to the provider developers." ,
114
+ )
115
+ return
116
+ }
117
+ hostConf := hostConfSlice [0 ]
118
+ tflog .Debug (ctx , "Loaded provider configuration" )
119
+
120
+ // Parse the host name
121
+ if ! hostConf .Name .IsNull () && ! hostConf .Name .IsUnknown () {
122
+ tflog .Debug (ctx , "Configuring host via name" , map [string ]interface {}{
123
+ "name" : hostConf .Name .ValueString (),
124
+ })
125
+
126
+ p .Hostname = hostConf .Name .ValueString ()
127
+ }
128
+
129
+ if ! hostConf .RequestHeaders .IsNull () && ! hostConf .RequestHeaders .IsUnknown () {
130
+ tflog .Debug (ctx , "Configuring request headers" )
131
+ requestHeaders := map [string ]string {}
132
+ for name , value := range hostConf .RequestHeaders .Elements () {
133
+ var header string
134
+ diags := tfsdk .ValueAs (ctx , value , & header )
135
+ res .Diagnostics .Append (diags ... )
136
+ if res .Diagnostics .HasError () {
137
+ return
138
+ }
139
+
140
+ requestHeaders [name ] = header
141
+ }
142
+
143
+ p .RequestHeaders = requestHeaders
144
+ }
145
+
146
+ tflog .Debug (ctx , "Provider configured" )
30
147
}
31
148
32
149
func (p * httpProvider ) Resources (context.Context ) []func () resource.Resource {
@@ -38,3 +155,25 @@ func (p *httpProvider) DataSources(context.Context) []func() datasource.DataSour
38
155
NewHttpDataSource ,
39
156
}
40
157
}
158
+
159
+ // toProvider casts a generic provider.Provider reference to this specific provider.
160
+ // This can be used in DataSourceType.NewDataSource and ResourceType.NewResource calls.
161
+ func toProvider (in any ) (* httpProvider , diag.Diagnostics ) {
162
+ if in == nil {
163
+ return nil , nil
164
+ }
165
+
166
+ var diags diag.Diagnostics
167
+ p , ok := in .(* httpProvider )
168
+ if ! ok {
169
+ diags .AddError (
170
+ "Unexpected Provider Instance Type" ,
171
+ fmt .Sprintf ("While creating the data source or resource, an unexpected provider type (%T) was received. " +
172
+ "This is likely a bug in the provider code and should be reported to the provider developers." , in ,
173
+ ),
174
+ )
175
+ return nil , diags
176
+ }
177
+
178
+ return p , diags
179
+ }
0 commit comments