1// Code generated by smithy-go-codegen DO NOT EDIT.
2
3package cloudwatch
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/cloudwatch/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	"strconv"
17	"time"
18)
19
20// Retrieves the specified alarms. You can filter the results by specifying a
21// prefix for the alarm name, the alarm state, or a prefix for any action.
22func (c *Client) DescribeAlarms(ctx context.Context, params *DescribeAlarmsInput, optFns ...func(*Options)) (*DescribeAlarmsOutput, error) {
23	if params == nil {
24		params = &DescribeAlarmsInput{}
25	}
26
27	result, metadata, err := c.invokeOperation(ctx, "DescribeAlarms", params, optFns, c.addOperationDescribeAlarmsMiddlewares)
28	if err != nil {
29		return nil, err
30	}
31
32	out := result.(*DescribeAlarmsOutput)
33	out.ResultMetadata = metadata
34	return out, nil
35}
36
37type DescribeAlarmsInput struct {
38
39	// Use this parameter to filter the results of the operation to only those alarms
40	// that use a certain alarm action. For example, you could specify the ARN of an
41	// SNS topic to find all alarms that send notifications to that topic.
42	ActionPrefix *string
43
44	// An alarm name prefix. If you specify this parameter, you receive information
45	// about all alarms that have names that start with this prefix. If this parameter
46	// is specified, you cannot specify AlarmNames.
47	AlarmNamePrefix *string
48
49	// The names of the alarms to retrieve information about.
50	AlarmNames []string
51
52	// Use this parameter to specify whether you want the operation to return metric
53	// alarms or composite alarms. If you omit this parameter, only metric alarms are
54	// returned.
55	AlarmTypes []types.AlarmType
56
57	// If you use this parameter and specify the name of a composite alarm, the
58	// operation returns information about the "children" alarms of the alarm you
59	// specify. These are the metric alarms and composite alarms referenced in the
60	// AlarmRule field of the composite alarm that you specify in ChildrenOfAlarmName.
61	// Information about the composite alarm that you name in ChildrenOfAlarmName is
62	// not returned. If you specify ChildrenOfAlarmName, you cannot specify any other
63	// parameters in the request except for MaxRecords and NextToken. If you do so, you
64	// receive a validation error. Only the Alarm Name, ARN, StateValue
65	// (OK/ALARM/INSUFFICIENT_DATA), and StateUpdatedTimestamp information are returned
66	// by this operation when you use this parameter. To get complete information about
67	// these alarms, perform another DescribeAlarms operation and specify the parent
68	// alarm names in the AlarmNames parameter.
69	ChildrenOfAlarmName *string
70
71	// The maximum number of alarm descriptions to retrieve.
72	MaxRecords *int32
73
74	// The token returned by a previous call to indicate that there is more data
75	// available.
76	NextToken *string
77
78	// If you use this parameter and specify the name of a metric or composite alarm,
79	// the operation returns information about the "parent" alarms of the alarm you
80	// specify. These are the composite alarms that have AlarmRule parameters that
81	// reference the alarm named in ParentsOfAlarmName. Information about the alarm
82	// that you specify in ParentsOfAlarmName is not returned. If you specify
83	// ParentsOfAlarmName, you cannot specify any other parameters in the request
84	// except for MaxRecords and NextToken. If you do so, you receive a validation
85	// error. Only the Alarm Name and ARN are returned by this operation when you use
86	// this parameter. To get complete information about these alarms, perform another
87	// DescribeAlarms operation and specify the parent alarm names in the AlarmNames
88	// parameter.
89	ParentsOfAlarmName *string
90
91	// Specify this parameter to receive information only about alarms that are
92	// currently in the state that you specify.
93	StateValue types.StateValue
94
95	noSmithyDocumentSerde
96}
97
98type DescribeAlarmsOutput struct {
99
100	// The information about any composite alarms returned by the operation.
101	CompositeAlarms []types.CompositeAlarm
102
103	// The information about any metric alarms returned by the operation.
104	MetricAlarms []types.MetricAlarm
105
106	// The token that marks the start of the next batch of returned results.
107	NextToken *string
108
109	// Metadata pertaining to the operation's result.
110	ResultMetadata middleware.Metadata
111
112	noSmithyDocumentSerde
113}
114
115func (c *Client) addOperationDescribeAlarmsMiddlewares(stack *middleware.Stack, options Options) (err error) {
116	err = stack.Serialize.Add(&awsAwsquery_serializeOpDescribeAlarms{}, middleware.After)
117	if err != nil {
118		return err
119	}
120	err = stack.Deserialize.Add(&awsAwsquery_deserializeOpDescribeAlarms{}, middleware.After)
121	if err != nil {
122		return err
123	}
124	if err = addSetLoggerMiddleware(stack, options); err != nil {
125		return err
126	}
127	if err = awsmiddleware.AddClientRequestIDMiddleware(stack); err != nil {
128		return err
129	}
130	if err = smithyhttp.AddComputeContentLengthMiddleware(stack); err != nil {
131		return err
132	}
133	if err = addResolveEndpointMiddleware(stack, options); err != nil {
134		return err
135	}
136	if err = v4.AddComputePayloadSHA256Middleware(stack); err != nil {
137		return err
138	}
139	if err = addRetryMiddlewares(stack, options); err != nil {
140		return err
141	}
142	if err = addHTTPSignerV4Middleware(stack, options); err != nil {
143		return err
144	}
145	if err = awsmiddleware.AddRawResponseToMetadata(stack); err != nil {
146		return err
147	}
148	if err = awsmiddleware.AddRecordResponseTiming(stack); err != nil {
149		return err
150	}
151	if err = addClientUserAgent(stack); err != nil {
152		return err
153	}
154	if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil {
155		return err
156	}
157	if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil {
158		return err
159	}
160	if err = stack.Initialize.Add(newServiceMetadataMiddleware_opDescribeAlarms(options.Region), middleware.Before); err != nil {
161		return err
162	}
163	if err = addRequestIDRetrieverMiddleware(stack); err != nil {
164		return err
165	}
166	if err = addResponseErrorMiddleware(stack); err != nil {
167		return err
168	}
169	if err = addRequestResponseLogging(stack, options); err != nil {
170		return err
171	}
172	return nil
173}
174
175// DescribeAlarmsAPIClient is a client that implements the DescribeAlarms
176// operation.
177type DescribeAlarmsAPIClient interface {
178	DescribeAlarms(context.Context, *DescribeAlarmsInput, ...func(*Options)) (*DescribeAlarmsOutput, error)
179}
180
181var _ DescribeAlarmsAPIClient = (*Client)(nil)
182
183// DescribeAlarmsPaginatorOptions is the paginator options for DescribeAlarms
184type DescribeAlarmsPaginatorOptions struct {
185	// The maximum number of alarm descriptions to retrieve.
186	Limit int32
187
188	// Set to true if pagination should stop if the service returns a pagination token
189	// that matches the most recent token provided to the service.
190	StopOnDuplicateToken bool
191}
192
193// DescribeAlarmsPaginator is a paginator for DescribeAlarms
194type DescribeAlarmsPaginator struct {
195	options   DescribeAlarmsPaginatorOptions
196	client    DescribeAlarmsAPIClient
197	params    *DescribeAlarmsInput
198	nextToken *string
199	firstPage bool
200}
201
202// NewDescribeAlarmsPaginator returns a new DescribeAlarmsPaginator
203func NewDescribeAlarmsPaginator(client DescribeAlarmsAPIClient, params *DescribeAlarmsInput, optFns ...func(*DescribeAlarmsPaginatorOptions)) *DescribeAlarmsPaginator {
204	if params == nil {
205		params = &DescribeAlarmsInput{}
206	}
207
208	options := DescribeAlarmsPaginatorOptions{}
209	if params.MaxRecords != nil {
210		options.Limit = *params.MaxRecords
211	}
212
213	for _, fn := range optFns {
214		fn(&options)
215	}
216
217	return &DescribeAlarmsPaginator{
218		options:   options,
219		client:    client,
220		params:    params,
221		firstPage: true,
222	}
223}
224
225// HasMorePages returns a boolean indicating whether more pages are available
226func (p *DescribeAlarmsPaginator) HasMorePages() bool {
227	return p.firstPage || p.nextToken != nil
228}
229
230// NextPage retrieves the next DescribeAlarms page.
231func (p *DescribeAlarmsPaginator) NextPage(ctx context.Context, optFns ...func(*Options)) (*DescribeAlarmsOutput, error) {
232	if !p.HasMorePages() {
233		return nil, fmt.Errorf("no more pages available")
234	}
235
236	params := *p.params
237	params.NextToken = p.nextToken
238
239	var limit *int32
240	if p.options.Limit > 0 {
241		limit = &p.options.Limit
242	}
243	params.MaxRecords = limit
244
245	result, err := p.client.DescribeAlarms(ctx, &params, optFns...)
246	if err != nil {
247		return nil, err
248	}
249	p.firstPage = false
250
251	prevToken := p.nextToken
252	p.nextToken = result.NextToken
253
254	if p.options.StopOnDuplicateToken && prevToken != nil && p.nextToken != nil && *prevToken == *p.nextToken {
255		p.nextToken = nil
256	}
257
258	return result, nil
259}
260
261// AlarmExistsWaiterOptions are waiter options for AlarmExistsWaiter
262type AlarmExistsWaiterOptions struct {
263
264	// Set of options to modify how an operation is invoked. These apply to all
265	// operations invoked for this client. Use functional options on operation call to
266	// modify this list for per operation behavior.
267	APIOptions []func(*middleware.Stack) error
268
269	// MinDelay is the minimum amount of time to delay between retries. If unset,
270	// AlarmExistsWaiter will use default minimum delay of 5 seconds. Note that
271	// MinDelay must resolve to a value lesser than or equal to the MaxDelay.
272	MinDelay time.Duration
273
274	// MaxDelay is the maximum amount of time to delay between retries. If unset or set
275	// to zero, AlarmExistsWaiter will use default max delay of 120 seconds. Note that
276	// MaxDelay must resolve to value greater than or equal to the MinDelay.
277	MaxDelay time.Duration
278
279	// LogWaitAttempts is used to enable logging for waiter retry attempts
280	LogWaitAttempts bool
281
282	// Retryable is function that can be used to override the service defined
283	// waiter-behavior based on operation output, or returned error. This function is
284	// used by the waiter to decide if a state is retryable or a terminal state. By
285	// default service-modeled logic will populate this option. This option can thus be
286	// used to define a custom waiter state with fall-back to service-modeled waiter
287	// state mutators.The function returns an error in case of a failure state. In case
288	// of retry state, this function returns a bool value of true and nil error, while
289	// in case of success it returns a bool value of false and nil error.
290	Retryable func(context.Context, *DescribeAlarmsInput, *DescribeAlarmsOutput, error) (bool, error)
291}
292
293// AlarmExistsWaiter defines the waiters for AlarmExists
294type AlarmExistsWaiter struct {
295	client DescribeAlarmsAPIClient
296
297	options AlarmExistsWaiterOptions
298}
299
300// NewAlarmExistsWaiter constructs a AlarmExistsWaiter.
301func NewAlarmExistsWaiter(client DescribeAlarmsAPIClient, optFns ...func(*AlarmExistsWaiterOptions)) *AlarmExistsWaiter {
302	options := AlarmExistsWaiterOptions{}
303	options.MinDelay = 5 * time.Second
304	options.MaxDelay = 120 * time.Second
305	options.Retryable = alarmExistsStateRetryable
306
307	for _, fn := range optFns {
308		fn(&options)
309	}
310	return &AlarmExistsWaiter{
311		client:  client,
312		options: options,
313	}
314}
315
316// Wait calls the waiter function for AlarmExists waiter. The maxWaitDur is the
317// maximum wait duration the waiter will wait. The maxWaitDur is required and must
318// be greater than zero.
319func (w *AlarmExistsWaiter) Wait(ctx context.Context, params *DescribeAlarmsInput, maxWaitDur time.Duration, optFns ...func(*AlarmExistsWaiterOptions)) error {
320	if maxWaitDur <= 0 {
321		return fmt.Errorf("maximum wait time for waiter must be greater than zero")
322	}
323
324	options := w.options
325	for _, fn := range optFns {
326		fn(&options)
327	}
328
329	if options.MaxDelay <= 0 {
330		options.MaxDelay = 120 * time.Second
331	}
332
333	if options.MinDelay > options.MaxDelay {
334		return fmt.Errorf("minimum waiter delay %v must be lesser than or equal to maximum waiter delay of %v.", options.MinDelay, options.MaxDelay)
335	}
336
337	ctx, cancelFn := context.WithTimeout(ctx, maxWaitDur)
338	defer cancelFn()
339
340	logger := smithywaiter.Logger{}
341	remainingTime := maxWaitDur
342
343	var attempt int64
344	for {
345
346		attempt++
347		apiOptions := options.APIOptions
348		start := time.Now()
349
350		if options.LogWaitAttempts {
351			logger.Attempt = attempt
352			apiOptions = append([]func(*middleware.Stack) error{}, options.APIOptions...)
353			apiOptions = append(apiOptions, logger.AddLogger)
354		}
355
356		out, err := w.client.DescribeAlarms(ctx, params, func(o *Options) {
357			o.APIOptions = append(o.APIOptions, apiOptions...)
358		})
359
360		retryable, err := options.Retryable(ctx, params, out, err)
361		if err != nil {
362			return err
363		}
364		if !retryable {
365			return nil
366		}
367
368		remainingTime -= time.Since(start)
369		if remainingTime < options.MinDelay || remainingTime <= 0 {
370			break
371		}
372
373		// compute exponential backoff between waiter retries
374		delay, err := smithywaiter.ComputeDelay(
375			attempt, options.MinDelay, options.MaxDelay, remainingTime,
376		)
377		if err != nil {
378			return fmt.Errorf("error computing waiter delay, %w", err)
379		}
380
381		remainingTime -= delay
382		// sleep for the delay amount before invoking a request
383		if err := smithytime.SleepWithContext(ctx, delay); err != nil {
384			return fmt.Errorf("request cancelled while waiting, %w", err)
385		}
386	}
387	return fmt.Errorf("exceeded max wait time for AlarmExists waiter")
388}
389
390func alarmExistsStateRetryable(ctx context.Context, input *DescribeAlarmsInput, output *DescribeAlarmsOutput, err error) (bool, error) {
391
392	if err == nil {
393		pathValue, err := jmespath.Search("length(MetricAlarms[]) > `0`", output)
394		if err != nil {
395			return false, fmt.Errorf("error evaluating waiter state: %w", err)
396		}
397
398		expectedValue := "true"
399		bv, err := strconv.ParseBool(expectedValue)
400		if err != nil {
401			return false, fmt.Errorf("error parsing boolean from string %w", err)
402		}
403		value, ok := pathValue.(bool)
404		if !ok {
405			return false, fmt.Errorf("waiter comparator expected bool value got %T", pathValue)
406		}
407
408		if value == bv {
409			return false, nil
410		}
411	}
412
413	return true, nil
414}
415
416// CompositeAlarmExistsWaiterOptions are waiter options for
417// CompositeAlarmExistsWaiter
418type CompositeAlarmExistsWaiterOptions struct {
419
420	// Set of options to modify how an operation is invoked. These apply to all
421	// operations invoked for this client. Use functional options on operation call to
422	// modify this list for per operation behavior.
423	APIOptions []func(*middleware.Stack) error
424
425	// MinDelay is the minimum amount of time to delay between retries. If unset,
426	// CompositeAlarmExistsWaiter will use default minimum delay of 5 seconds. Note
427	// that MinDelay must resolve to a value lesser than or equal to the MaxDelay.
428	MinDelay time.Duration
429
430	// MaxDelay is the maximum amount of time to delay between retries. If unset or set
431	// to zero, CompositeAlarmExistsWaiter will use default max delay of 120 seconds.
432	// Note that MaxDelay must resolve to value greater than or equal to the MinDelay.
433	MaxDelay time.Duration
434
435	// LogWaitAttempts is used to enable logging for waiter retry attempts
436	LogWaitAttempts bool
437
438	// Retryable is function that can be used to override the service defined
439	// waiter-behavior based on operation output, or returned error. This function is
440	// used by the waiter to decide if a state is retryable or a terminal state. By
441	// default service-modeled logic will populate this option. This option can thus be
442	// used to define a custom waiter state with fall-back to service-modeled waiter
443	// state mutators.The function returns an error in case of a failure state. In case
444	// of retry state, this function returns a bool value of true and nil error, while
445	// in case of success it returns a bool value of false and nil error.
446	Retryable func(context.Context, *DescribeAlarmsInput, *DescribeAlarmsOutput, error) (bool, error)
447}
448
449// CompositeAlarmExistsWaiter defines the waiters for CompositeAlarmExists
450type CompositeAlarmExistsWaiter struct {
451	client DescribeAlarmsAPIClient
452
453	options CompositeAlarmExistsWaiterOptions
454}
455
456// NewCompositeAlarmExistsWaiter constructs a CompositeAlarmExistsWaiter.
457func NewCompositeAlarmExistsWaiter(client DescribeAlarmsAPIClient, optFns ...func(*CompositeAlarmExistsWaiterOptions)) *CompositeAlarmExistsWaiter {
458	options := CompositeAlarmExistsWaiterOptions{}
459	options.MinDelay = 5 * time.Second
460	options.MaxDelay = 120 * time.Second
461	options.Retryable = compositeAlarmExistsStateRetryable
462
463	for _, fn := range optFns {
464		fn(&options)
465	}
466	return &CompositeAlarmExistsWaiter{
467		client:  client,
468		options: options,
469	}
470}
471
472// Wait calls the waiter function for CompositeAlarmExists waiter. The maxWaitDur
473// is the maximum wait duration the waiter will wait. The maxWaitDur is required
474// and must be greater than zero.
475func (w *CompositeAlarmExistsWaiter) Wait(ctx context.Context, params *DescribeAlarmsInput, maxWaitDur time.Duration, optFns ...func(*CompositeAlarmExistsWaiterOptions)) error {
476	if maxWaitDur <= 0 {
477		return fmt.Errorf("maximum wait time for waiter must be greater than zero")
478	}
479
480	options := w.options
481	for _, fn := range optFns {
482		fn(&options)
483	}
484
485	if options.MaxDelay <= 0 {
486		options.MaxDelay = 120 * time.Second
487	}
488
489	if options.MinDelay > options.MaxDelay {
490		return fmt.Errorf("minimum waiter delay %v must be lesser than or equal to maximum waiter delay of %v.", options.MinDelay, options.MaxDelay)
491	}
492
493	ctx, cancelFn := context.WithTimeout(ctx, maxWaitDur)
494	defer cancelFn()
495
496	logger := smithywaiter.Logger{}
497	remainingTime := maxWaitDur
498
499	var attempt int64
500	for {
501
502		attempt++
503		apiOptions := options.APIOptions
504		start := time.Now()
505
506		if options.LogWaitAttempts {
507			logger.Attempt = attempt
508			apiOptions = append([]func(*middleware.Stack) error{}, options.APIOptions...)
509			apiOptions = append(apiOptions, logger.AddLogger)
510		}
511
512		out, err := w.client.DescribeAlarms(ctx, params, func(o *Options) {
513			o.APIOptions = append(o.APIOptions, apiOptions...)
514		})
515
516		retryable, err := options.Retryable(ctx, params, out, err)
517		if err != nil {
518			return err
519		}
520		if !retryable {
521			return nil
522		}
523
524		remainingTime -= time.Since(start)
525		if remainingTime < options.MinDelay || remainingTime <= 0 {
526			break
527		}
528
529		// compute exponential backoff between waiter retries
530		delay, err := smithywaiter.ComputeDelay(
531			attempt, options.MinDelay, options.MaxDelay, remainingTime,
532		)
533		if err != nil {
534			return fmt.Errorf("error computing waiter delay, %w", err)
535		}
536
537		remainingTime -= delay
538		// sleep for the delay amount before invoking a request
539		if err := smithytime.SleepWithContext(ctx, delay); err != nil {
540			return fmt.Errorf("request cancelled while waiting, %w", err)
541		}
542	}
543	return fmt.Errorf("exceeded max wait time for CompositeAlarmExists waiter")
544}
545
546func compositeAlarmExistsStateRetryable(ctx context.Context, input *DescribeAlarmsInput, output *DescribeAlarmsOutput, err error) (bool, error) {
547
548	if err == nil {
549		pathValue, err := jmespath.Search("length(CompositeAlarms[]) > `0`", output)
550		if err != nil {
551			return false, fmt.Errorf("error evaluating waiter state: %w", err)
552		}
553
554		expectedValue := "true"
555		bv, err := strconv.ParseBool(expectedValue)
556		if err != nil {
557			return false, fmt.Errorf("error parsing boolean from string %w", err)
558		}
559		value, ok := pathValue.(bool)
560		if !ok {
561			return false, fmt.Errorf("waiter comparator expected bool value got %T", pathValue)
562		}
563
564		if value == bv {
565			return false, nil
566		}
567	}
568
569	return true, nil
570}
571
572func newServiceMetadataMiddleware_opDescribeAlarms(region string) *awsmiddleware.RegisterServiceMetadata {
573	return &awsmiddleware.RegisterServiceMetadata{
574		Region:        region,
575		ServiceID:     ServiceID,
576		SigningName:   "monitoring",
577		OperationName: "DescribeAlarms",
578	}
579}
580