@@ -5,28 +5,145 @@ package provider
55
66import (
77 "context"
8+ "fmt"
89
10+ "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator"
911 "github.com/hashicorp/terraform-plugin-framework/datasource"
12+ "github.com/hashicorp/terraform-plugin-framework/diag"
13+ "github.com/hashicorp/terraform-plugin-framework/path"
1014 "github.com/hashicorp/terraform-plugin-framework/provider"
15+ "github.com/hashicorp/terraform-plugin-framework/provider/schema"
1116 "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"
1221)
1322
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+
1433func New () provider.Provider {
1534 return & httpProvider {}
1635}
1736
18- var _ provider.Provider = (* httpProvider )(nil )
37+ type httpProviderConfigModel struct {
38+ Host types.List `tfsdk:"host"`
39+ }
1940
20- type httpProvider struct {}
41+ type httpProviderHostConfigModel struct {
42+ Name types.String `tfsdk:"name"`
43+ RequestHeaders types.Map `tfsdk:"request_headers"`
44+ }
2145
2246func (p * httpProvider ) Metadata (_ context.Context , _ provider.MetadataRequest , resp * provider.MetadataResponse ) {
2347 resp .TypeName = "http"
2448}
2549
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+ }
2781}
2882
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" )
30147}
31148
32149func (p * httpProvider ) Resources (context.Context ) []func () resource.Resource {
@@ -38,3 +155,25 @@ func (p *httpProvider) DataSources(context.Context) []func() datasource.DataSour
38155 NewHttpDataSource ,
39156 }
40157}
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