1// Code generated by smithy-go-codegen DO NOT EDIT. 2 3package redshift 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/redshift/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 properties of provisioned clusters including general cluster properties, 20// cluster database properties, maintenance and backup properties, and security and 21// access properties. This operation supports pagination. For more information 22// about managing clusters, go to Amazon Redshift Clusters 23// (https://docs.aws.amazon.com/redshift/latest/mgmt/working-with-clusters.html) in 24// the Amazon Redshift Cluster Management Guide. If you specify both tag keys and 25// tag values in the same request, Amazon Redshift returns all clusters that match 26// any combination of the specified keys and values. For example, if you have owner 27// and environment for tag keys, and admin and test for tag values, all clusters 28// that have any combination of those values are returned. If both tag keys and 29// values are omitted from the request, clusters are returned regardless of whether 30// they have tag keys or values associated with them. 31func (c *Client) DescribeClusters(ctx context.Context, params *DescribeClustersInput, optFns ...func(*Options)) (*DescribeClustersOutput, error) { 32 if params == nil { 33 params = &DescribeClustersInput{} 34 } 35 36 result, metadata, err := c.invokeOperation(ctx, "DescribeClusters", params, optFns, addOperationDescribeClustersMiddlewares) 37 if err != nil { 38 return nil, err 39 } 40 41 out := result.(*DescribeClustersOutput) 42 out.ResultMetadata = metadata 43 return out, nil 44} 45 46// 47type DescribeClustersInput struct { 48 49 // The unique identifier of a cluster whose properties you are requesting. This 50 // parameter is case sensitive. The default is that all clusters defined for an 51 // account are returned. 52 ClusterIdentifier *string 53 54 // An optional parameter that specifies the starting point to return a set of 55 // response records. When the results of a DescribeClusters request exceed the 56 // value specified in MaxRecords, AWS returns a value in the Marker field of the 57 // response. You can retrieve the next set of response records by providing the 58 // returned marker value in the Marker parameter and retrying the request. 59 // Constraints: You can specify either the ClusterIdentifier parameter or the 60 // Marker parameter, but not both. 61 Marker *string 62 63 // The maximum number of response records to return in each call. If the number of 64 // remaining response records exceeds the specified MaxRecords value, a value is 65 // returned in a marker field of the response. You can retrieve the next set of 66 // records by retrying the command with the returned marker value. Default: 100 67 // Constraints: minimum 20, maximum 100. 68 MaxRecords *int32 69 70 // A tag key or keys for which you want to return all matching clusters that are 71 // associated with the specified key or keys. For example, suppose that you have 72 // clusters that are tagged with keys called owner and environment. If you specify 73 // both of these tag keys in the request, Amazon Redshift returns a response with 74 // the clusters that have either or both of these tag keys associated with them. 75 TagKeys []string 76 77 // A tag value or values for which you want to return all matching clusters that 78 // are associated with the specified tag value or values. For example, suppose that 79 // you have clusters that are tagged with values called admin and test. If you 80 // specify both of these tag values in the request, Amazon Redshift returns a 81 // response with the clusters that have either or both of these tag values 82 // associated with them. 83 TagValues []string 84} 85 86// Contains the output from the DescribeClusters action. 87type DescribeClustersOutput struct { 88 89 // A list of Cluster objects, where each object describes one cluster. 90 Clusters []types.Cluster 91 92 // A value that indicates the starting point for the next set of response records 93 // in a subsequent request. If a value is returned in a response, you can retrieve 94 // the next set of records by providing this returned marker value in the Marker 95 // parameter and retrying the command. If the Marker field is empty, all response 96 // records have been retrieved for the request. 97 Marker *string 98 99 // Metadata pertaining to the operation's result. 100 ResultMetadata middleware.Metadata 101} 102 103func addOperationDescribeClustersMiddlewares(stack *middleware.Stack, options Options) (err error) { 104 err = stack.Serialize.Add(&awsAwsquery_serializeOpDescribeClusters{}, middleware.After) 105 if err != nil { 106 return err 107 } 108 err = stack.Deserialize.Add(&awsAwsquery_deserializeOpDescribeClusters{}, middleware.After) 109 if err != nil { 110 return err 111 } 112 if err = addSetLoggerMiddleware(stack, options); err != nil { 113 return err 114 } 115 if err = awsmiddleware.AddClientRequestIDMiddleware(stack); err != nil { 116 return err 117 } 118 if err = smithyhttp.AddComputeContentLengthMiddleware(stack); err != nil { 119 return err 120 } 121 if err = addResolveEndpointMiddleware(stack, options); err != nil { 122 return err 123 } 124 if err = v4.AddComputePayloadSHA256Middleware(stack); err != nil { 125 return err 126 } 127 if err = addRetryMiddlewares(stack, options); err != nil { 128 return err 129 } 130 if err = addHTTPSignerV4Middleware(stack, options); err != nil { 131 return err 132 } 133 if err = awsmiddleware.AddRawResponseToMetadata(stack); err != nil { 134 return err 135 } 136 if err = awsmiddleware.AddRecordResponseTiming(stack); err != nil { 137 return err 138 } 139 if err = addClientUserAgent(stack); err != nil { 140 return err 141 } 142 if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { 143 return err 144 } 145 if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { 146 return err 147 } 148 if err = stack.Initialize.Add(newServiceMetadataMiddleware_opDescribeClusters(options.Region), middleware.Before); err != nil { 149 return err 150 } 151 if err = addRequestIDRetrieverMiddleware(stack); err != nil { 152 return err 153 } 154 if err = addResponseErrorMiddleware(stack); err != nil { 155 return err 156 } 157 if err = addRequestResponseLogging(stack, options); err != nil { 158 return err 159 } 160 return nil 161} 162 163// DescribeClustersAPIClient is a client that implements the DescribeClusters 164// operation. 165type DescribeClustersAPIClient interface { 166 DescribeClusters(context.Context, *DescribeClustersInput, ...func(*Options)) (*DescribeClustersOutput, error) 167} 168 169var _ DescribeClustersAPIClient = (*Client)(nil) 170 171// DescribeClustersPaginatorOptions is the paginator options for DescribeClusters 172type DescribeClustersPaginatorOptions struct { 173 // The maximum number of response records to return in each call. If the number of 174 // remaining response records exceeds the specified MaxRecords value, a value is 175 // returned in a marker field of the response. You can retrieve the next set of 176 // records by retrying the command with the returned marker value. Default: 100 177 // Constraints: minimum 20, maximum 100. 178 Limit int32 179 180 // Set to true if pagination should stop if the service returns a pagination token 181 // that matches the most recent token provided to the service. 182 StopOnDuplicateToken bool 183} 184 185// DescribeClustersPaginator is a paginator for DescribeClusters 186type DescribeClustersPaginator struct { 187 options DescribeClustersPaginatorOptions 188 client DescribeClustersAPIClient 189 params *DescribeClustersInput 190 nextToken *string 191 firstPage bool 192} 193 194// NewDescribeClustersPaginator returns a new DescribeClustersPaginator 195func NewDescribeClustersPaginator(client DescribeClustersAPIClient, params *DescribeClustersInput, optFns ...func(*DescribeClustersPaginatorOptions)) *DescribeClustersPaginator { 196 if params == nil { 197 params = &DescribeClustersInput{} 198 } 199 200 options := DescribeClustersPaginatorOptions{} 201 if params.MaxRecords != nil { 202 options.Limit = *params.MaxRecords 203 } 204 205 for _, fn := range optFns { 206 fn(&options) 207 } 208 209 return &DescribeClustersPaginator{ 210 options: options, 211 client: client, 212 params: params, 213 firstPage: true, 214 } 215} 216 217// HasMorePages returns a boolean indicating whether more pages are available 218func (p *DescribeClustersPaginator) HasMorePages() bool { 219 return p.firstPage || p.nextToken != nil 220} 221 222// NextPage retrieves the next DescribeClusters page. 223func (p *DescribeClustersPaginator) NextPage(ctx context.Context, optFns ...func(*Options)) (*DescribeClustersOutput, error) { 224 if !p.HasMorePages() { 225 return nil, fmt.Errorf("no more pages available") 226 } 227 228 params := *p.params 229 params.Marker = p.nextToken 230 231 var limit *int32 232 if p.options.Limit > 0 { 233 limit = &p.options.Limit 234 } 235 params.MaxRecords = limit 236 237 result, err := p.client.DescribeClusters(ctx, ¶ms, optFns...) 238 if err != nil { 239 return nil, err 240 } 241 p.firstPage = false 242 243 prevToken := p.nextToken 244 p.nextToken = result.Marker 245 246 if p.options.StopOnDuplicateToken && prevToken != nil && p.nextToken != nil && *prevToken == *p.nextToken { 247 p.nextToken = nil 248 } 249 250 return result, nil 251} 252 253// ClusterRestoredWaiterOptions are waiter options for ClusterRestoredWaiter 254type ClusterRestoredWaiterOptions struct { 255 256 // Set of options to modify how an operation is invoked. These apply to all 257 // operations invoked for this client. Use functional options on operation call to 258 // modify this list for per operation behavior. 259 APIOptions []func(*middleware.Stack) error 260 261 // MinDelay is the minimum amount of time to delay between retries. If unset, 262 // ClusterRestoredWaiter will use default minimum delay of 60 seconds. Note that 263 // MinDelay must resolve to a value lesser than or equal to the MaxDelay. 264 MinDelay time.Duration 265 266 // MaxDelay is the maximum amount of time to delay between retries. If unset or set 267 // to zero, ClusterRestoredWaiter will use default max delay of 120 seconds. Note 268 // that MaxDelay must resolve to value greater than or equal to the MinDelay. 269 MaxDelay time.Duration 270 271 // LogWaitAttempts is used to enable logging for waiter retry attempts 272 LogWaitAttempts bool 273 274 // Retryable is function that can be used to override the service defined 275 // waiter-behavior based on operation output, or returned error. This function is 276 // used by the waiter to decide if a state is retryable or a terminal state. By 277 // default service-modeled logic will populate this option. This option can thus be 278 // used to define a custom waiter state with fall-back to service-modeled waiter 279 // state mutators.The function returns an error in case of a failure state. In case 280 // of retry state, this function returns a bool value of true and nil error, while 281 // in case of success it returns a bool value of false and nil error. 282 Retryable func(context.Context, *DescribeClustersInput, *DescribeClustersOutput, error) (bool, error) 283} 284 285// ClusterRestoredWaiter defines the waiters for ClusterRestored 286type ClusterRestoredWaiter struct { 287 client DescribeClustersAPIClient 288 289 options ClusterRestoredWaiterOptions 290} 291 292// NewClusterRestoredWaiter constructs a ClusterRestoredWaiter. 293func NewClusterRestoredWaiter(client DescribeClustersAPIClient, optFns ...func(*ClusterRestoredWaiterOptions)) *ClusterRestoredWaiter { 294 options := ClusterRestoredWaiterOptions{} 295 options.MinDelay = 60 * time.Second 296 options.MaxDelay = 120 * time.Second 297 options.Retryable = clusterRestoredStateRetryable 298 299 for _, fn := range optFns { 300 fn(&options) 301 } 302 return &ClusterRestoredWaiter{ 303 client: client, 304 options: options, 305 } 306} 307 308// Wait calls the waiter function for ClusterRestored waiter. The maxWaitDur is the 309// maximum wait duration the waiter will wait. The maxWaitDur is required and must 310// be greater than zero. 311func (w *ClusterRestoredWaiter) Wait(ctx context.Context, params *DescribeClustersInput, maxWaitDur time.Duration, optFns ...func(*ClusterRestoredWaiterOptions)) error { 312 if maxWaitDur <= 0 { 313 return fmt.Errorf("maximum wait time for waiter must be greater than zero") 314 } 315 316 options := w.options 317 for _, fn := range optFns { 318 fn(&options) 319 } 320 321 if options.MaxDelay <= 0 { 322 options.MaxDelay = 120 * time.Second 323 } 324 325 if options.MinDelay > options.MaxDelay { 326 return fmt.Errorf("minimum waiter delay %v must be lesser than or equal to maximum waiter delay of %v.", options.MinDelay, options.MaxDelay) 327 } 328 329 ctx, cancelFn := context.WithTimeout(ctx, maxWaitDur) 330 defer cancelFn() 331 332 logger := smithywaiter.Logger{} 333 remainingTime := maxWaitDur 334 335 var attempt int64 336 for { 337 338 attempt++ 339 apiOptions := options.APIOptions 340 start := time.Now() 341 342 if options.LogWaitAttempts { 343 logger.Attempt = attempt 344 apiOptions = append([]func(*middleware.Stack) error{}, options.APIOptions...) 345 apiOptions = append(apiOptions, logger.AddLogger) 346 } 347 348 out, err := w.client.DescribeClusters(ctx, params, func(o *Options) { 349 o.APIOptions = append(o.APIOptions, apiOptions...) 350 }) 351 352 retryable, err := options.Retryable(ctx, params, out, err) 353 if err != nil { 354 return err 355 } 356 if !retryable { 357 return nil 358 } 359 360 remainingTime -= time.Since(start) 361 if remainingTime < options.MinDelay || remainingTime <= 0 { 362 break 363 } 364 365 // compute exponential backoff between waiter retries 366 delay, err := smithywaiter.ComputeDelay( 367 attempt, options.MinDelay, options.MaxDelay, remainingTime, 368 ) 369 if err != nil { 370 return fmt.Errorf("error computing waiter delay, %w", err) 371 } 372 373 remainingTime -= delay 374 // sleep for the delay amount before invoking a request 375 if err := smithytime.SleepWithContext(ctx, delay); err != nil { 376 return fmt.Errorf("request cancelled while waiting, %w", err) 377 } 378 } 379 return fmt.Errorf("exceeded max wait time for ClusterRestored waiter") 380} 381 382func clusterRestoredStateRetryable(ctx context.Context, input *DescribeClustersInput, output *DescribeClustersOutput, err error) (bool, error) { 383 384 if err == nil { 385 pathValue, err := jmespath.Search("Clusters[].RestoreStatus.Status", output) 386 if err != nil { 387 return false, fmt.Errorf("error evaluating waiter state: %w", err) 388 } 389 390 expectedValue := "completed" 391 var match = true 392 listOfValues, ok := pathValue.([]interface{}) 393 if !ok { 394 return false, fmt.Errorf("waiter comparator expected list got %T", pathValue) 395 } 396 397 if len(listOfValues) == 0 { 398 match = false 399 } 400 for _, v := range listOfValues { 401 value, ok := v.(*string) 402 if !ok { 403 return false, fmt.Errorf("waiter comparator expected *string value, got %T", pathValue) 404 } 405 406 if string(*value) != expectedValue { 407 match = false 408 } 409 } 410 411 if match { 412 return false, nil 413 } 414 } 415 416 if err == nil { 417 pathValue, err := jmespath.Search("Clusters[].ClusterStatus", output) 418 if err != nil { 419 return false, fmt.Errorf("error evaluating waiter state: %w", err) 420 } 421 422 expectedValue := "deleting" 423 listOfValues, ok := pathValue.([]interface{}) 424 if !ok { 425 return false, fmt.Errorf("waiter comparator expected list got %T", pathValue) 426 } 427 428 for _, v := range listOfValues { 429 value, ok := v.(*string) 430 if !ok { 431 return false, fmt.Errorf("waiter comparator expected *string value, got %T", pathValue) 432 } 433 434 if string(*value) == expectedValue { 435 return false, fmt.Errorf("waiter state transitioned to Failure") 436 } 437 } 438 } 439 440 return true, nil 441} 442 443func newServiceMetadataMiddleware_opDescribeClusters(region string) *awsmiddleware.RegisterServiceMetadata { 444 return &awsmiddleware.RegisterServiceMetadata{ 445 Region: region, 446 ServiceID: ServiceID, 447 SigningName: "redshift", 448 OperationName: "DescribeClusters", 449 } 450} 451