1// Code generated by smithy-go-codegen DO NOT EDIT.
2
3package cloudformation
4
5import (
6	"context"
7	cryptorand "crypto/rand"
8	"github.com/aws/aws-sdk-go-v2/aws"
9	awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware"
10	"github.com/aws/aws-sdk-go-v2/aws/retry"
11	"github.com/aws/aws-sdk-go-v2/aws/signer/v4"
12	awshttp "github.com/aws/aws-sdk-go-v2/aws/transport/http"
13	smithy "github.com/aws/smithy-go"
14	"github.com/aws/smithy-go/logging"
15	"github.com/aws/smithy-go/middleware"
16	smithyrand "github.com/aws/smithy-go/rand"
17	smithyhttp "github.com/aws/smithy-go/transport/http"
18	"net/http"
19	"time"
20)
21
22const ServiceID = "CloudFormation"
23const ServiceAPIVersion = "2010-05-15"
24
25// Client provides the API client to make operations call for AWS CloudFormation.
26type Client struct {
27	options Options
28}
29
30// New returns an initialized Client based on the functional options. Provide
31// additional functional options to further configure the behavior of the client,
32// such as changing the client's endpoint or adding custom middleware behavior.
33func New(options Options, optFns ...func(*Options)) *Client {
34	options = options.Copy()
35
36	resolveDefaultLogger(&options)
37
38	resolveRetryer(&options)
39
40	resolveHTTPClient(&options)
41
42	resolveHTTPSignerV4(&options)
43
44	resolveDefaultEndpointConfiguration(&options)
45
46	resolveIdempotencyTokenProvider(&options)
47
48	for _, fn := range optFns {
49		fn(&options)
50	}
51
52	client := &Client{
53		options: options,
54	}
55
56	return client
57}
58
59type Options struct {
60	// Set of options to modify how an operation is invoked. These apply to all
61	// operations invoked for this client. Use functional options on operation call to
62	// modify this list for per operation behavior.
63	APIOptions []func(*middleware.Stack) error
64
65	// Configures the events that will be sent to the configured logger.
66	ClientLogMode aws.ClientLogMode
67
68	// The credentials object to use when signing requests.
69	Credentials aws.CredentialsProvider
70
71	// The endpoint options to be used when attempting to resolve an endpoint.
72	EndpointOptions EndpointResolverOptions
73
74	// The service endpoint resolver.
75	EndpointResolver EndpointResolver
76
77	// Signature Version 4 (SigV4) Signer
78	HTTPSignerV4 HTTPSignerV4
79
80	// Provides idempotency tokens values that will be automatically populated into
81	// idempotent API operations.
82	IdempotencyTokenProvider IdempotencyTokenProvider
83
84	// The logger writer interface to write logging messages to.
85	Logger logging.Logger
86
87	// The region to send requests to. (Required)
88	Region string
89
90	// Retryer guides how HTTP requests should be retried in case of recoverable
91	// failures. When nil the API client will use a default retryer.
92	Retryer aws.Retryer
93
94	// The HTTP client to invoke API calls with. Defaults to client's default HTTP
95	// implementation if nil.
96	HTTPClient HTTPClient
97}
98
99// WithAPIOptions returns a functional option for setting the Client's APIOptions
100// option.
101func WithAPIOptions(optFns ...func(*middleware.Stack) error) func(*Options) {
102	return func(o *Options) {
103		o.APIOptions = append(o.APIOptions, optFns...)
104	}
105}
106
107// WithEndpointResolver returns a functional option for setting the Client's
108// EndpointResolver option.
109func WithEndpointResolver(v EndpointResolver) func(*Options) {
110	return func(o *Options) {
111		o.EndpointResolver = v
112	}
113}
114
115type HTTPClient interface {
116	Do(*http.Request) (*http.Response, error)
117}
118
119// Copy creates a clone where the APIOptions list is deep copied.
120func (o Options) Copy() Options {
121	to := o
122	to.APIOptions = make([]func(*middleware.Stack) error, len(o.APIOptions))
123	copy(to.APIOptions, o.APIOptions)
124	return to
125}
126func (c *Client) invokeOperation(ctx context.Context, opID string, params interface{}, optFns []func(*Options), stackFns ...func(*middleware.Stack, Options) error) (result interface{}, metadata middleware.Metadata, err error) {
127	ctx = middleware.ClearStackValues(ctx)
128	stack := middleware.NewStack(opID, smithyhttp.NewStackRequest)
129	options := c.options.Copy()
130	for _, fn := range optFns {
131		fn(&options)
132	}
133
134	for _, fn := range stackFns {
135		if err := fn(stack, options); err != nil {
136			return nil, metadata, err
137		}
138	}
139
140	for _, fn := range options.APIOptions {
141		if err := fn(stack); err != nil {
142			return nil, metadata, err
143		}
144	}
145
146	handler := middleware.DecorateHandler(smithyhttp.NewClientHandler(options.HTTPClient), stack)
147	result, metadata, err = handler.Handle(ctx, params)
148	if err != nil {
149		err = &smithy.OperationError{
150			ServiceID:     ServiceID,
151			OperationName: opID,
152			Err:           err,
153		}
154	}
155	return result, metadata, err
156}
157
158func resolveDefaultLogger(o *Options) {
159	if o.Logger != nil {
160		return
161	}
162	o.Logger = logging.Nop{}
163}
164
165func addSetLoggerMiddleware(stack *middleware.Stack, o Options) error {
166	return middleware.AddSetLoggerMiddleware(stack, o.Logger)
167}
168
169// NewFromConfig returns a new client from the provided config.
170func NewFromConfig(cfg aws.Config, optFns ...func(*Options)) *Client {
171	opts := Options{
172		Region:        cfg.Region,
173		HTTPClient:    cfg.HTTPClient,
174		Credentials:   cfg.Credentials,
175		APIOptions:    cfg.APIOptions,
176		Logger:        cfg.Logger,
177		ClientLogMode: cfg.ClientLogMode,
178	}
179	resolveAWSRetryerProvider(cfg, &opts)
180	resolveAWSEndpointResolver(cfg, &opts)
181	return New(opts, optFns...)
182}
183
184func resolveHTTPClient(o *Options) {
185	if o.HTTPClient != nil {
186		return
187	}
188	o.HTTPClient = awshttp.NewBuildableClient()
189}
190
191func resolveRetryer(o *Options) {
192	if o.Retryer != nil {
193		return
194	}
195	o.Retryer = retry.NewStandard()
196}
197
198func resolveAWSRetryerProvider(cfg aws.Config, o *Options) {
199	if cfg.Retryer == nil {
200		return
201	}
202	o.Retryer = cfg.Retryer()
203}
204
205func resolveAWSEndpointResolver(cfg aws.Config, o *Options) {
206	if cfg.EndpointResolver == nil {
207		return
208	}
209	o.EndpointResolver = withEndpointResolver(cfg.EndpointResolver, NewDefaultEndpointResolver())
210}
211
212func addClientUserAgent(stack *middleware.Stack) error {
213	return awsmiddleware.AddRequestUserAgentMiddleware(stack)
214}
215
216func addHTTPSignerV4Middleware(stack *middleware.Stack, o Options) error {
217	mw := v4.NewSignHTTPRequestMiddleware(v4.SignHTTPRequestMiddlewareOptions{
218		CredentialsProvider: o.Credentials,
219		Signer:              o.HTTPSignerV4,
220		LogSigning:          o.ClientLogMode.IsSigning(),
221	})
222	return stack.Finalize.Add(mw, middleware.After)
223}
224
225type HTTPSignerV4 interface {
226	SignHTTP(ctx context.Context, credentials aws.Credentials, r *http.Request, payloadHash string, service string, region string, signingTime time.Time, optFns ...func(*v4.SignerOptions)) error
227}
228
229func resolveHTTPSignerV4(o *Options) {
230	if o.HTTPSignerV4 != nil {
231		return
232	}
233	o.HTTPSignerV4 = newDefaultV4Signer(*o)
234}
235
236func newDefaultV4Signer(o Options) *v4.Signer {
237	return v4.NewSigner(func(so *v4.SignerOptions) {
238		so.Logger = o.Logger
239		so.LogSigning = o.ClientLogMode.IsSigning()
240	})
241}
242
243func resolveIdempotencyTokenProvider(o *Options) {
244	if o.IdempotencyTokenProvider != nil {
245		return
246	}
247	o.IdempotencyTokenProvider = smithyrand.NewUUIDIdempotencyToken(cryptorand.Reader)
248}
249
250func addRetryMiddlewares(stack *middleware.Stack, o Options) error {
251	mo := retry.AddRetryMiddlewaresOptions{
252		Retryer:          o.Retryer,
253		LogRetryAttempts: o.ClientLogMode.IsRetries(),
254	}
255	return retry.AddRetryMiddlewares(stack, mo)
256}
257
258// IdempotencyTokenProvider interface for providing idempotency token
259type IdempotencyTokenProvider interface {
260	GetIdempotencyToken() (string, error)
261}
262
263func addRequestIDRetrieverMiddleware(stack *middleware.Stack) error {
264	return awsmiddleware.AddRequestIDRetrieverMiddleware(stack)
265}
266
267func addResponseErrorMiddleware(stack *middleware.Stack) error {
268	return awshttp.AddResponseErrorMiddleware(stack)
269}
270
271func addRequestResponseLogging(stack *middleware.Stack, o Options) error {
272	return stack.Deserialize.Add(&smithyhttp.RequestResponseLogger{
273		LogRequest:          o.ClientLogMode.IsRequest(),
274		LogRequestWithBody:  o.ClientLogMode.IsRequestWithBody(),
275		LogResponse:         o.ClientLogMode.IsResponse(),
276		LogResponseWithBody: o.ClientLogMode.IsResponseWithBody(),
277	}, middleware.After)
278}
279