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