1// Code generated by smithy-go-codegen DO NOT EDIT.
2
3package route53
4
5import (
6	"context"
7	"fmt"
8	awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware"
9	"github.com/aws/aws-sdk-go-v2/aws/signer/v4"
10	"github.com/aws/aws-sdk-go-v2/service/route53/types"
11	"github.com/aws/smithy-go/middleware"
12	smithytime "github.com/aws/smithy-go/time"
13	smithyhttp "github.com/aws/smithy-go/transport/http"
14	smithywaiter "github.com/aws/smithy-go/waiter"
15	"github.com/jmespath/go-jmespath"
16	"time"
17)
18
19// Returns the current status of a change batch request. The status is one of the
20// following values:
21//
22// * PENDING indicates that the changes in this request have not
23// propagated to all Amazon Route 53 DNS servers. This is the initial status of all
24// change batch requests.
25//
26// * INSYNC indicates that the changes have propagated to
27// all Route 53 DNS servers.
28func (c *Client) GetChange(ctx context.Context, params *GetChangeInput, optFns ...func(*Options)) (*GetChangeOutput, error) {
29	if params == nil {
30		params = &GetChangeInput{}
31	}
32
33	result, metadata, err := c.invokeOperation(ctx, "GetChange", params, optFns, c.addOperationGetChangeMiddlewares)
34	if err != nil {
35		return nil, err
36	}
37
38	out := result.(*GetChangeOutput)
39	out.ResultMetadata = metadata
40	return out, nil
41}
42
43// The input for a GetChange request.
44type GetChangeInput struct {
45
46	// The ID of the change batch request. The value that you specify here is the value
47	// that ChangeResourceRecordSets returned in the Id element when you submitted the
48	// request.
49	//
50	// This member is required.
51	Id *string
52
53	noSmithyDocumentSerde
54}
55
56// A complex type that contains the ChangeInfo element.
57type GetChangeOutput struct {
58
59	// A complex type that contains information about the specified change batch.
60	//
61	// This member is required.
62	ChangeInfo *types.ChangeInfo
63
64	// Metadata pertaining to the operation's result.
65	ResultMetadata middleware.Metadata
66
67	noSmithyDocumentSerde
68}
69
70func (c *Client) addOperationGetChangeMiddlewares(stack *middleware.Stack, options Options) (err error) {
71	err = stack.Serialize.Add(&awsRestxml_serializeOpGetChange{}, middleware.After)
72	if err != nil {
73		return err
74	}
75	err = stack.Deserialize.Add(&awsRestxml_deserializeOpGetChange{}, middleware.After)
76	if err != nil {
77		return err
78	}
79	if err = addSetLoggerMiddleware(stack, options); err != nil {
80		return err
81	}
82	if err = awsmiddleware.AddClientRequestIDMiddleware(stack); err != nil {
83		return err
84	}
85	if err = smithyhttp.AddComputeContentLengthMiddleware(stack); err != nil {
86		return err
87	}
88	if err = addResolveEndpointMiddleware(stack, options); err != nil {
89		return err
90	}
91	if err = v4.AddComputePayloadSHA256Middleware(stack); err != nil {
92		return err
93	}
94	if err = addRetryMiddlewares(stack, options); err != nil {
95		return err
96	}
97	if err = addHTTPSignerV4Middleware(stack, options); err != nil {
98		return err
99	}
100	if err = awsmiddleware.AddRawResponseToMetadata(stack); err != nil {
101		return err
102	}
103	if err = awsmiddleware.AddRecordResponseTiming(stack); err != nil {
104		return err
105	}
106	if err = addClientUserAgent(stack); err != nil {
107		return err
108	}
109	if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil {
110		return err
111	}
112	if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil {
113		return err
114	}
115	if err = addOpGetChangeValidationMiddleware(stack); err != nil {
116		return err
117	}
118	if err = stack.Initialize.Add(newServiceMetadataMiddleware_opGetChange(options.Region), middleware.Before); err != nil {
119		return err
120	}
121	if err = addRequestIDRetrieverMiddleware(stack); err != nil {
122		return err
123	}
124	if err = addResponseErrorMiddleware(stack); err != nil {
125		return err
126	}
127	if err = addSanitizeURLMiddleware(stack); err != nil {
128		return err
129	}
130	if err = addRequestResponseLogging(stack, options); err != nil {
131		return err
132	}
133	return nil
134}
135
136// GetChangeAPIClient is a client that implements the GetChange operation.
137type GetChangeAPIClient interface {
138	GetChange(context.Context, *GetChangeInput, ...func(*Options)) (*GetChangeOutput, error)
139}
140
141var _ GetChangeAPIClient = (*Client)(nil)
142
143// ResourceRecordSetsChangedWaiterOptions are waiter options for
144// ResourceRecordSetsChangedWaiter
145type ResourceRecordSetsChangedWaiterOptions struct {
146
147	// Set of options to modify how an operation is invoked. These apply to all
148	// operations invoked for this client. Use functional options on operation call to
149	// modify this list for per operation behavior.
150	APIOptions []func(*middleware.Stack) error
151
152	// MinDelay is the minimum amount of time to delay between retries. If unset,
153	// ResourceRecordSetsChangedWaiter will use default minimum delay of 30 seconds.
154	// Note that MinDelay must resolve to a value lesser than or equal to the MaxDelay.
155	MinDelay time.Duration
156
157	// MaxDelay is the maximum amount of time to delay between retries. If unset or set
158	// to zero, ResourceRecordSetsChangedWaiter will use default max delay of 120
159	// seconds. Note that MaxDelay must resolve to value greater than or equal to the
160	// MinDelay.
161	MaxDelay time.Duration
162
163	// LogWaitAttempts is used to enable logging for waiter retry attempts
164	LogWaitAttempts bool
165
166	// Retryable is function that can be used to override the service defined
167	// waiter-behavior based on operation output, or returned error. This function is
168	// used by the waiter to decide if a state is retryable or a terminal state. By
169	// default service-modeled logic will populate this option. This option can thus be
170	// used to define a custom waiter state with fall-back to service-modeled waiter
171	// state mutators.The function returns an error in case of a failure state. In case
172	// of retry state, this function returns a bool value of true and nil error, while
173	// in case of success it returns a bool value of false and nil error.
174	Retryable func(context.Context, *GetChangeInput, *GetChangeOutput, error) (bool, error)
175}
176
177// ResourceRecordSetsChangedWaiter defines the waiters for
178// ResourceRecordSetsChanged
179type ResourceRecordSetsChangedWaiter struct {
180	client GetChangeAPIClient
181
182	options ResourceRecordSetsChangedWaiterOptions
183}
184
185// NewResourceRecordSetsChangedWaiter constructs a ResourceRecordSetsChangedWaiter.
186func NewResourceRecordSetsChangedWaiter(client GetChangeAPIClient, optFns ...func(*ResourceRecordSetsChangedWaiterOptions)) *ResourceRecordSetsChangedWaiter {
187	options := ResourceRecordSetsChangedWaiterOptions{}
188	options.MinDelay = 30 * time.Second
189	options.MaxDelay = 120 * time.Second
190	options.Retryable = resourceRecordSetsChangedStateRetryable
191
192	for _, fn := range optFns {
193		fn(&options)
194	}
195	return &ResourceRecordSetsChangedWaiter{
196		client:  client,
197		options: options,
198	}
199}
200
201// Wait calls the waiter function for ResourceRecordSetsChanged waiter. The
202// maxWaitDur is the maximum wait duration the waiter will wait. The maxWaitDur is
203// required and must be greater than zero.
204func (w *ResourceRecordSetsChangedWaiter) Wait(ctx context.Context, params *GetChangeInput, maxWaitDur time.Duration, optFns ...func(*ResourceRecordSetsChangedWaiterOptions)) error {
205	if maxWaitDur <= 0 {
206		return fmt.Errorf("maximum wait time for waiter must be greater than zero")
207	}
208
209	options := w.options
210	for _, fn := range optFns {
211		fn(&options)
212	}
213
214	if options.MaxDelay <= 0 {
215		options.MaxDelay = 120 * time.Second
216	}
217
218	if options.MinDelay > options.MaxDelay {
219		return fmt.Errorf("minimum waiter delay %v must be lesser than or equal to maximum waiter delay of %v.", options.MinDelay, options.MaxDelay)
220	}
221
222	ctx, cancelFn := context.WithTimeout(ctx, maxWaitDur)
223	defer cancelFn()
224
225	logger := smithywaiter.Logger{}
226	remainingTime := maxWaitDur
227
228	var attempt int64
229	for {
230
231		attempt++
232		apiOptions := options.APIOptions
233		start := time.Now()
234
235		if options.LogWaitAttempts {
236			logger.Attempt = attempt
237			apiOptions = append([]func(*middleware.Stack) error{}, options.APIOptions...)
238			apiOptions = append(apiOptions, logger.AddLogger)
239		}
240
241		out, err := w.client.GetChange(ctx, params, func(o *Options) {
242			o.APIOptions = append(o.APIOptions, apiOptions...)
243		})
244
245		retryable, err := options.Retryable(ctx, params, out, err)
246		if err != nil {
247			return err
248		}
249		if !retryable {
250			return nil
251		}
252
253		remainingTime -= time.Since(start)
254		if remainingTime < options.MinDelay || remainingTime <= 0 {
255			break
256		}
257
258		// compute exponential backoff between waiter retries
259		delay, err := smithywaiter.ComputeDelay(
260			attempt, options.MinDelay, options.MaxDelay, remainingTime,
261		)
262		if err != nil {
263			return fmt.Errorf("error computing waiter delay, %w", err)
264		}
265
266		remainingTime -= delay
267		// sleep for the delay amount before invoking a request
268		if err := smithytime.SleepWithContext(ctx, delay); err != nil {
269			return fmt.Errorf("request cancelled while waiting, %w", err)
270		}
271	}
272	return fmt.Errorf("exceeded max wait time for ResourceRecordSetsChanged waiter")
273}
274
275func resourceRecordSetsChangedStateRetryable(ctx context.Context, input *GetChangeInput, output *GetChangeOutput, err error) (bool, error) {
276
277	if err == nil {
278		pathValue, err := jmespath.Search("ChangeInfo.Status", output)
279		if err != nil {
280			return false, fmt.Errorf("error evaluating waiter state: %w", err)
281		}
282
283		expectedValue := "INSYNC"
284		value, ok := pathValue.(types.ChangeStatus)
285		if !ok {
286			return false, fmt.Errorf("waiter comparator expected types.ChangeStatus value, got %T", pathValue)
287		}
288
289		if string(value) == expectedValue {
290			return false, nil
291		}
292	}
293
294	return true, nil
295}
296
297func newServiceMetadataMiddleware_opGetChange(region string) *awsmiddleware.RegisterServiceMetadata {
298	return &awsmiddleware.RegisterServiceMetadata{
299		Region:        region,
300		ServiceID:     ServiceID,
301		SigningName:   "route53",
302		OperationName: "GetChange",
303	}
304}
305