1// Code generated by smithy-go-codegen DO NOT EDIT. 2 3package elasticache 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/elasticache/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 information about all provisioned clusters if no cluster identifier is 20// specified, or about a specific cache cluster if a cluster identifier is 21// supplied. By default, abbreviated information about the clusters is returned. 22// You can use the optional ShowCacheNodeInfo flag to retrieve detailed information 23// about the cache nodes associated with the clusters. These details include the 24// DNS address and port for the cache node endpoint. If the cluster is in the 25// creating state, only cluster-level information is displayed until all of the 26// nodes are successfully provisioned. If the cluster is in the deleting state, 27// only cluster-level information is displayed. If cache nodes are currently being 28// added to the cluster, node endpoint information and creation time for the 29// additional nodes are not displayed until they are completely provisioned. When 30// the cluster state is available, the cluster is ready for use. If cache nodes are 31// currently being removed from the cluster, no endpoint information for the 32// removed nodes is displayed. 33func (c *Client) DescribeCacheClusters(ctx context.Context, params *DescribeCacheClustersInput, optFns ...func(*Options)) (*DescribeCacheClustersOutput, error) { 34 if params == nil { 35 params = &DescribeCacheClustersInput{} 36 } 37 38 result, metadata, err := c.invokeOperation(ctx, "DescribeCacheClusters", params, optFns, addOperationDescribeCacheClustersMiddlewares) 39 if err != nil { 40 return nil, err 41 } 42 43 out := result.(*DescribeCacheClustersOutput) 44 out.ResultMetadata = metadata 45 return out, nil 46} 47 48// Represents the input of a DescribeCacheClusters operation. 49type DescribeCacheClustersInput struct { 50 51 // The user-supplied cluster identifier. If this parameter is specified, only 52 // information about that specific cluster is returned. This parameter isn't case 53 // sensitive. 54 CacheClusterId *string 55 56 // An optional marker returned from a prior request. Use this marker for pagination 57 // of results from this operation. If this parameter is specified, the response 58 // includes only records beyond the marker, up to the value specified by 59 // MaxRecords. 60 Marker *string 61 62 // The maximum number of records to include in the response. If more records exist 63 // than the specified MaxRecords value, a marker is included in the response so 64 // that the remaining results can be retrieved. Default: 100 Constraints: minimum 65 // 20; maximum 100. 66 MaxRecords *int32 67 68 // An optional flag that can be included in the DescribeCacheCluster request to 69 // show only nodes (API/CLI: clusters) that are not members of a replication group. 70 // In practice, this mean Memcached and single node Redis clusters. 71 ShowCacheClustersNotInReplicationGroups *bool 72 73 // An optional flag that can be included in the DescribeCacheCluster request to 74 // retrieve information about the individual cache nodes. 75 ShowCacheNodeInfo *bool 76} 77 78// Represents the output of a DescribeCacheClusters operation. 79type DescribeCacheClustersOutput struct { 80 81 // A list of clusters. Each item in the list contains detailed information about 82 // one cluster. 83 CacheClusters []types.CacheCluster 84 85 // Provides an identifier to allow retrieval of paginated results. 86 Marker *string 87 88 // Metadata pertaining to the operation's result. 89 ResultMetadata middleware.Metadata 90} 91 92func addOperationDescribeCacheClustersMiddlewares(stack *middleware.Stack, options Options) (err error) { 93 err = stack.Serialize.Add(&awsAwsquery_serializeOpDescribeCacheClusters{}, middleware.After) 94 if err != nil { 95 return err 96 } 97 err = stack.Deserialize.Add(&awsAwsquery_deserializeOpDescribeCacheClusters{}, middleware.After) 98 if err != nil { 99 return err 100 } 101 if err = addSetLoggerMiddleware(stack, options); err != nil { 102 return err 103 } 104 if err = awsmiddleware.AddClientRequestIDMiddleware(stack); err != nil { 105 return err 106 } 107 if err = smithyhttp.AddComputeContentLengthMiddleware(stack); err != nil { 108 return err 109 } 110 if err = addResolveEndpointMiddleware(stack, options); err != nil { 111 return err 112 } 113 if err = v4.AddComputePayloadSHA256Middleware(stack); err != nil { 114 return err 115 } 116 if err = addRetryMiddlewares(stack, options); err != nil { 117 return err 118 } 119 if err = addHTTPSignerV4Middleware(stack, options); err != nil { 120 return err 121 } 122 if err = awsmiddleware.AddRawResponseToMetadata(stack); err != nil { 123 return err 124 } 125 if err = awsmiddleware.AddRecordResponseTiming(stack); err != nil { 126 return err 127 } 128 if err = addClientUserAgent(stack); err != nil { 129 return err 130 } 131 if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { 132 return err 133 } 134 if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { 135 return err 136 } 137 if err = stack.Initialize.Add(newServiceMetadataMiddleware_opDescribeCacheClusters(options.Region), middleware.Before); err != nil { 138 return err 139 } 140 if err = addRequestIDRetrieverMiddleware(stack); err != nil { 141 return err 142 } 143 if err = addResponseErrorMiddleware(stack); err != nil { 144 return err 145 } 146 if err = addRequestResponseLogging(stack, options); err != nil { 147 return err 148 } 149 return nil 150} 151 152// DescribeCacheClustersAPIClient is a client that implements the 153// DescribeCacheClusters operation. 154type DescribeCacheClustersAPIClient interface { 155 DescribeCacheClusters(context.Context, *DescribeCacheClustersInput, ...func(*Options)) (*DescribeCacheClustersOutput, error) 156} 157 158var _ DescribeCacheClustersAPIClient = (*Client)(nil) 159 160// DescribeCacheClustersPaginatorOptions is the paginator options for 161// DescribeCacheClusters 162type DescribeCacheClustersPaginatorOptions struct { 163 // The maximum number of records to include in the response. If more records exist 164 // than the specified MaxRecords value, a marker is included in the response so 165 // that the remaining results can be retrieved. Default: 100 Constraints: minimum 166 // 20; maximum 100. 167 Limit int32 168 169 // Set to true if pagination should stop if the service returns a pagination token 170 // that matches the most recent token provided to the service. 171 StopOnDuplicateToken bool 172} 173 174// DescribeCacheClustersPaginator is a paginator for DescribeCacheClusters 175type DescribeCacheClustersPaginator struct { 176 options DescribeCacheClustersPaginatorOptions 177 client DescribeCacheClustersAPIClient 178 params *DescribeCacheClustersInput 179 nextToken *string 180 firstPage bool 181} 182 183// NewDescribeCacheClustersPaginator returns a new DescribeCacheClustersPaginator 184func NewDescribeCacheClustersPaginator(client DescribeCacheClustersAPIClient, params *DescribeCacheClustersInput, optFns ...func(*DescribeCacheClustersPaginatorOptions)) *DescribeCacheClustersPaginator { 185 options := DescribeCacheClustersPaginatorOptions{} 186 if params.MaxRecords != nil { 187 options.Limit = *params.MaxRecords 188 } 189 190 for _, fn := range optFns { 191 fn(&options) 192 } 193 194 if params == nil { 195 params = &DescribeCacheClustersInput{} 196 } 197 198 return &DescribeCacheClustersPaginator{ 199 options: options, 200 client: client, 201 params: params, 202 firstPage: true, 203 } 204} 205 206// HasMorePages returns a boolean indicating whether more pages are available 207func (p *DescribeCacheClustersPaginator) HasMorePages() bool { 208 return p.firstPage || p.nextToken != nil 209} 210 211// NextPage retrieves the next DescribeCacheClusters page. 212func (p *DescribeCacheClustersPaginator) NextPage(ctx context.Context, optFns ...func(*Options)) (*DescribeCacheClustersOutput, error) { 213 if !p.HasMorePages() { 214 return nil, fmt.Errorf("no more pages available") 215 } 216 217 params := *p.params 218 params.Marker = p.nextToken 219 220 var limit *int32 221 if p.options.Limit > 0 { 222 limit = &p.options.Limit 223 } 224 params.MaxRecords = limit 225 226 result, err := p.client.DescribeCacheClusters(ctx, ¶ms, optFns...) 227 if err != nil { 228 return nil, err 229 } 230 p.firstPage = false 231 232 prevToken := p.nextToken 233 p.nextToken = result.Marker 234 235 if p.options.StopOnDuplicateToken && prevToken != nil && p.nextToken != nil && *prevToken == *p.nextToken { 236 p.nextToken = nil 237 } 238 239 return result, nil 240} 241 242// CacheClusterAvailableWaiterOptions are waiter options for 243// CacheClusterAvailableWaiter 244type CacheClusterAvailableWaiterOptions struct { 245 246 // Set of options to modify how an operation is invoked. These apply to all 247 // operations invoked for this client. Use functional options on operation call to 248 // modify this list for per operation behavior. 249 APIOptions []func(*middleware.Stack) error 250 251 // MinDelay is the minimum amount of time to delay between retries. If unset, 252 // CacheClusterAvailableWaiter will use default minimum delay of 15 seconds. Note 253 // that MinDelay must resolve to a value lesser than or equal to the MaxDelay. 254 MinDelay time.Duration 255 256 // MaxDelay is the maximum amount of time to delay between retries. If unset or set 257 // to zero, CacheClusterAvailableWaiter will use default max delay of 120 seconds. 258 // Note that MaxDelay must resolve to value greater than or equal to the MinDelay. 259 MaxDelay time.Duration 260 261 // LogWaitAttempts is used to enable logging for waiter retry attempts 262 LogWaitAttempts bool 263 264 // Retryable is function that can be used to override the service defined 265 // waiter-behavior based on operation output, or returned error. This function is 266 // used by the waiter to decide if a state is retryable or a terminal state. By 267 // default service-modeled logic will populate this option. This option can thus be 268 // used to define a custom waiter state with fall-back to service-modeled waiter 269 // state mutators.The function returns an error in case of a failure state. In case 270 // of retry state, this function returns a bool value of true and nil error, while 271 // in case of success it returns a bool value of false and nil error. 272 Retryable func(context.Context, *DescribeCacheClustersInput, *DescribeCacheClustersOutput, error) (bool, error) 273} 274 275// CacheClusterAvailableWaiter defines the waiters for CacheClusterAvailable 276type CacheClusterAvailableWaiter struct { 277 client DescribeCacheClustersAPIClient 278 279 options CacheClusterAvailableWaiterOptions 280} 281 282// NewCacheClusterAvailableWaiter constructs a CacheClusterAvailableWaiter. 283func NewCacheClusterAvailableWaiter(client DescribeCacheClustersAPIClient, optFns ...func(*CacheClusterAvailableWaiterOptions)) *CacheClusterAvailableWaiter { 284 options := CacheClusterAvailableWaiterOptions{} 285 options.MinDelay = 15 * time.Second 286 options.MaxDelay = 120 * time.Second 287 options.Retryable = cacheClusterAvailableStateRetryable 288 289 for _, fn := range optFns { 290 fn(&options) 291 } 292 return &CacheClusterAvailableWaiter{ 293 client: client, 294 options: options, 295 } 296} 297 298// Wait calls the waiter function for CacheClusterAvailable waiter. The maxWaitDur 299// is the maximum wait duration the waiter will wait. The maxWaitDur is required 300// and must be greater than zero. 301func (w *CacheClusterAvailableWaiter) Wait(ctx context.Context, params *DescribeCacheClustersInput, maxWaitDur time.Duration, optFns ...func(*CacheClusterAvailableWaiterOptions)) error { 302 if maxWaitDur <= 0 { 303 return fmt.Errorf("maximum wait time for waiter must be greater than zero") 304 } 305 306 options := w.options 307 for _, fn := range optFns { 308 fn(&options) 309 } 310 311 if options.MaxDelay <= 0 { 312 options.MaxDelay = 120 * time.Second 313 } 314 315 if options.MinDelay > options.MaxDelay { 316 return fmt.Errorf("minimum waiter delay %v must be lesser than or equal to maximum waiter delay of %v.", options.MinDelay, options.MaxDelay) 317 } 318 319 ctx, cancelFn := context.WithTimeout(ctx, maxWaitDur) 320 defer cancelFn() 321 322 logger := smithywaiter.Logger{} 323 remainingTime := maxWaitDur 324 325 var attempt int64 326 for { 327 328 attempt++ 329 apiOptions := options.APIOptions 330 start := time.Now() 331 332 if options.LogWaitAttempts { 333 logger.Attempt = attempt 334 apiOptions = append([]func(*middleware.Stack) error{}, options.APIOptions...) 335 apiOptions = append(apiOptions, logger.AddLogger) 336 } 337 338 out, err := w.client.DescribeCacheClusters(ctx, params, func(o *Options) { 339 o.APIOptions = append(o.APIOptions, apiOptions...) 340 }) 341 342 retryable, err := options.Retryable(ctx, params, out, err) 343 if err != nil { 344 return err 345 } 346 if !retryable { 347 return nil 348 } 349 350 remainingTime -= time.Since(start) 351 if remainingTime < options.MinDelay || remainingTime <= 0 { 352 break 353 } 354 355 // compute exponential backoff between waiter retries 356 delay, err := smithywaiter.ComputeDelay( 357 attempt, options.MinDelay, options.MaxDelay, remainingTime, 358 ) 359 if err != nil { 360 return fmt.Errorf("error computing waiter delay, %w", err) 361 } 362 363 remainingTime -= delay 364 // sleep for the delay amount before invoking a request 365 if err := smithytime.SleepWithContext(ctx, delay); err != nil { 366 return fmt.Errorf("request cancelled while waiting, %w", err) 367 } 368 } 369 return fmt.Errorf("exceeded max wait time for CacheClusterAvailable waiter") 370} 371 372func cacheClusterAvailableStateRetryable(ctx context.Context, input *DescribeCacheClustersInput, output *DescribeCacheClustersOutput, err error) (bool, error) { 373 374 if err == nil { 375 pathValue, err := jmespath.Search("CacheClusters[].CacheClusterStatus", output) 376 if err != nil { 377 return false, fmt.Errorf("error evaluating waiter state: %w", err) 378 } 379 380 expectedValue := "available" 381 var match = true 382 listOfValues, ok := pathValue.([]interface{}) 383 if !ok { 384 return false, fmt.Errorf("waiter comparator expected list got %T", pathValue) 385 } 386 387 if len(listOfValues) == 0 { 388 match = false 389 } 390 for _, v := range listOfValues { 391 value, ok := v.(*string) 392 if !ok { 393 return false, fmt.Errorf("waiter comparator expected *string value, got %T", pathValue) 394 } 395 396 if string(*value) != expectedValue { 397 match = false 398 } 399 } 400 401 if match { 402 return false, nil 403 } 404 } 405 406 if err == nil { 407 pathValue, err := jmespath.Search("CacheClusters[].CacheClusterStatus", output) 408 if err != nil { 409 return false, fmt.Errorf("error evaluating waiter state: %w", err) 410 } 411 412 expectedValue := "deleted" 413 listOfValues, ok := pathValue.([]interface{}) 414 if !ok { 415 return false, fmt.Errorf("waiter comparator expected list got %T", pathValue) 416 } 417 418 for _, v := range listOfValues { 419 value, ok := v.(*string) 420 if !ok { 421 return false, fmt.Errorf("waiter comparator expected *string value, got %T", pathValue) 422 } 423 424 if string(*value) == expectedValue { 425 return false, fmt.Errorf("waiter state transitioned to Failure") 426 } 427 } 428 } 429 430 if err == nil { 431 pathValue, err := jmespath.Search("CacheClusters[].CacheClusterStatus", output) 432 if err != nil { 433 return false, fmt.Errorf("error evaluating waiter state: %w", err) 434 } 435 436 expectedValue := "deleting" 437 listOfValues, ok := pathValue.([]interface{}) 438 if !ok { 439 return false, fmt.Errorf("waiter comparator expected list got %T", pathValue) 440 } 441 442 for _, v := range listOfValues { 443 value, ok := v.(*string) 444 if !ok { 445 return false, fmt.Errorf("waiter comparator expected *string value, got %T", pathValue) 446 } 447 448 if string(*value) == expectedValue { 449 return false, fmt.Errorf("waiter state transitioned to Failure") 450 } 451 } 452 } 453 454 if err == nil { 455 pathValue, err := jmespath.Search("CacheClusters[].CacheClusterStatus", output) 456 if err != nil { 457 return false, fmt.Errorf("error evaluating waiter state: %w", err) 458 } 459 460 expectedValue := "incompatible-network" 461 listOfValues, ok := pathValue.([]interface{}) 462 if !ok { 463 return false, fmt.Errorf("waiter comparator expected list got %T", pathValue) 464 } 465 466 for _, v := range listOfValues { 467 value, ok := v.(*string) 468 if !ok { 469 return false, fmt.Errorf("waiter comparator expected *string value, got %T", pathValue) 470 } 471 472 if string(*value) == expectedValue { 473 return false, fmt.Errorf("waiter state transitioned to Failure") 474 } 475 } 476 } 477 478 if err == nil { 479 pathValue, err := jmespath.Search("CacheClusters[].CacheClusterStatus", output) 480 if err != nil { 481 return false, fmt.Errorf("error evaluating waiter state: %w", err) 482 } 483 484 expectedValue := "restore-failed" 485 listOfValues, ok := pathValue.([]interface{}) 486 if !ok { 487 return false, fmt.Errorf("waiter comparator expected list got %T", pathValue) 488 } 489 490 for _, v := range listOfValues { 491 value, ok := v.(*string) 492 if !ok { 493 return false, fmt.Errorf("waiter comparator expected *string value, got %T", pathValue) 494 } 495 496 if string(*value) == expectedValue { 497 return false, fmt.Errorf("waiter state transitioned to Failure") 498 } 499 } 500 } 501 502 return true, nil 503} 504 505func newServiceMetadataMiddleware_opDescribeCacheClusters(region string) *awsmiddleware.RegisterServiceMetadata { 506 return &awsmiddleware.RegisterServiceMetadata{ 507 Region: region, 508 ServiceID: ServiceID, 509 SigningName: "elasticache", 510 OperationName: "DescribeCacheClusters", 511 } 512} 513