1// Code generated by smithy-go-codegen DO NOT EDIT.
2
3package ec2
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/smithy-go/middleware"
11	smithytime "github.com/aws/smithy-go/time"
12	smithyhttp "github.com/aws/smithy-go/transport/http"
13	smithywaiter "github.com/aws/smithy-go/waiter"
14	"github.com/jmespath/go-jmespath"
15	"strconv"
16	"time"
17)
18
19// Retrieves the encrypted administrator password for a running Windows instance.
20// The Windows password is generated at boot by the EC2Config service or EC2Launch
21// scripts (Windows Server 2016 and later). This usually only happens the first
22// time an instance is launched. For more information, see EC2Config
23// (https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/UsingConfig_WinAMI.html)
24// and EC2Launch
25// (https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/ec2launch.html) in the
26// Amazon EC2 User Guide. For the EC2Config service, the password is not generated
27// for rebundled AMIs unless Ec2SetPassword is enabled before bundling. The
28// password is encrypted using the key pair that you specified when you launched
29// the instance. You must provide the corresponding key pair file. When you launch
30// an instance, password generation and encryption may take a few minutes. If you
31// try to retrieve the password before it's available, the output returns an empty
32// string. We recommend that you wait up to 15 minutes after launching an instance
33// before trying to retrieve the generated password.
34func (c *Client) GetPasswordData(ctx context.Context, params *GetPasswordDataInput, optFns ...func(*Options)) (*GetPasswordDataOutput, error) {
35	if params == nil {
36		params = &GetPasswordDataInput{}
37	}
38
39	result, metadata, err := c.invokeOperation(ctx, "GetPasswordData", params, optFns, addOperationGetPasswordDataMiddlewares)
40	if err != nil {
41		return nil, err
42	}
43
44	out := result.(*GetPasswordDataOutput)
45	out.ResultMetadata = metadata
46	return out, nil
47}
48
49type GetPasswordDataInput struct {
50
51	// The ID of the Windows instance.
52	//
53	// This member is required.
54	InstanceId *string
55
56	// Checks whether you have the required permissions for the action, without
57	// actually making the request, and provides an error response. If you have the
58	// required permissions, the error response is DryRunOperation. Otherwise, it is
59	// UnauthorizedOperation.
60	DryRun bool
61}
62
63type GetPasswordDataOutput struct {
64
65	// The ID of the Windows instance.
66	InstanceId *string
67
68	// The password of the instance. Returns an empty string if the password is not
69	// available.
70	PasswordData *string
71
72	// The time the data was last updated.
73	Timestamp *time.Time
74
75	// Metadata pertaining to the operation's result.
76	ResultMetadata middleware.Metadata
77}
78
79func addOperationGetPasswordDataMiddlewares(stack *middleware.Stack, options Options) (err error) {
80	err = stack.Serialize.Add(&awsEc2query_serializeOpGetPasswordData{}, middleware.After)
81	if err != nil {
82		return err
83	}
84	err = stack.Deserialize.Add(&awsEc2query_deserializeOpGetPasswordData{}, middleware.After)
85	if err != nil {
86		return err
87	}
88	if err = addSetLoggerMiddleware(stack, options); err != nil {
89		return err
90	}
91	if err = awsmiddleware.AddClientRequestIDMiddleware(stack); err != nil {
92		return err
93	}
94	if err = smithyhttp.AddComputeContentLengthMiddleware(stack); err != nil {
95		return err
96	}
97	if err = addResolveEndpointMiddleware(stack, options); err != nil {
98		return err
99	}
100	if err = v4.AddComputePayloadSHA256Middleware(stack); err != nil {
101		return err
102	}
103	if err = addRetryMiddlewares(stack, options); err != nil {
104		return err
105	}
106	if err = addHTTPSignerV4Middleware(stack, options); err != nil {
107		return err
108	}
109	if err = awsmiddleware.AddRawResponseToMetadata(stack); err != nil {
110		return err
111	}
112	if err = awsmiddleware.AddRecordResponseTiming(stack); err != nil {
113		return err
114	}
115	if err = addClientUserAgent(stack); err != nil {
116		return err
117	}
118	if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil {
119		return err
120	}
121	if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil {
122		return err
123	}
124	if err = addOpGetPasswordDataValidationMiddleware(stack); err != nil {
125		return err
126	}
127	if err = stack.Initialize.Add(newServiceMetadataMiddleware_opGetPasswordData(options.Region), middleware.Before); err != nil {
128		return err
129	}
130	if err = addRequestIDRetrieverMiddleware(stack); err != nil {
131		return err
132	}
133	if err = addResponseErrorMiddleware(stack); err != nil {
134		return err
135	}
136	if err = addRequestResponseLogging(stack, options); err != nil {
137		return err
138	}
139	return nil
140}
141
142// GetPasswordDataAPIClient is a client that implements the GetPasswordData
143// operation.
144type GetPasswordDataAPIClient interface {
145	GetPasswordData(context.Context, *GetPasswordDataInput, ...func(*Options)) (*GetPasswordDataOutput, error)
146}
147
148var _ GetPasswordDataAPIClient = (*Client)(nil)
149
150// PasswordDataAvailableWaiterOptions are waiter options for
151// PasswordDataAvailableWaiter
152type PasswordDataAvailableWaiterOptions struct {
153
154	// Set of options to modify how an operation is invoked. These apply to all
155	// operations invoked for this client. Use functional options on operation call to
156	// modify this list for per operation behavior.
157	APIOptions []func(*middleware.Stack) error
158
159	// MinDelay is the minimum amount of time to delay between retries. If unset,
160	// PasswordDataAvailableWaiter will use default minimum delay of 15 seconds. Note
161	// that MinDelay must resolve to a value lesser than or equal to the MaxDelay.
162	MinDelay time.Duration
163
164	// MaxDelay is the maximum amount of time to delay between retries. If unset or set
165	// to zero, PasswordDataAvailableWaiter will use default max delay of 120 seconds.
166	// Note that MaxDelay must resolve to value greater than or equal to the MinDelay.
167	MaxDelay time.Duration
168
169	// LogWaitAttempts is used to enable logging for waiter retry attempts
170	LogWaitAttempts bool
171
172	// Retryable is function that can be used to override the service defined
173	// waiter-behavior based on operation output, or returned error. This function is
174	// used by the waiter to decide if a state is retryable or a terminal state. By
175	// default service-modeled logic will populate this option. This option can thus be
176	// used to define a custom waiter state with fall-back to service-modeled waiter
177	// state mutators.The function returns an error in case of a failure state. In case
178	// of retry state, this function returns a bool value of true and nil error, while
179	// in case of success it returns a bool value of false and nil error.
180	Retryable func(context.Context, *GetPasswordDataInput, *GetPasswordDataOutput, error) (bool, error)
181}
182
183// PasswordDataAvailableWaiter defines the waiters for PasswordDataAvailable
184type PasswordDataAvailableWaiter struct {
185	client GetPasswordDataAPIClient
186
187	options PasswordDataAvailableWaiterOptions
188}
189
190// NewPasswordDataAvailableWaiter constructs a PasswordDataAvailableWaiter.
191func NewPasswordDataAvailableWaiter(client GetPasswordDataAPIClient, optFns ...func(*PasswordDataAvailableWaiterOptions)) *PasswordDataAvailableWaiter {
192	options := PasswordDataAvailableWaiterOptions{}
193	options.MinDelay = 15 * time.Second
194	options.MaxDelay = 120 * time.Second
195	options.Retryable = passwordDataAvailableStateRetryable
196
197	for _, fn := range optFns {
198		fn(&options)
199	}
200	return &PasswordDataAvailableWaiter{
201		client:  client,
202		options: options,
203	}
204}
205
206// Wait calls the waiter function for PasswordDataAvailable waiter. The maxWaitDur
207// is the maximum wait duration the waiter will wait. The maxWaitDur is required
208// and must be greater than zero.
209func (w *PasswordDataAvailableWaiter) Wait(ctx context.Context, params *GetPasswordDataInput, maxWaitDur time.Duration, optFns ...func(*PasswordDataAvailableWaiterOptions)) error {
210	if maxWaitDur <= 0 {
211		return fmt.Errorf("maximum wait time for waiter must be greater than zero")
212	}
213
214	options := w.options
215	for _, fn := range optFns {
216		fn(&options)
217	}
218
219	if options.MaxDelay <= 0 {
220		options.MaxDelay = 120 * time.Second
221	}
222
223	if options.MinDelay > options.MaxDelay {
224		return fmt.Errorf("minimum waiter delay %v must be lesser than or equal to maximum waiter delay of %v.", options.MinDelay, options.MaxDelay)
225	}
226
227	ctx, cancelFn := context.WithTimeout(ctx, maxWaitDur)
228	defer cancelFn()
229
230	logger := smithywaiter.Logger{}
231	remainingTime := maxWaitDur
232
233	var attempt int64
234	for {
235
236		attempt++
237		apiOptions := options.APIOptions
238		start := time.Now()
239
240		if options.LogWaitAttempts {
241			logger.Attempt = attempt
242			apiOptions = append([]func(*middleware.Stack) error{}, options.APIOptions...)
243			apiOptions = append(apiOptions, logger.AddLogger)
244		}
245
246		out, err := w.client.GetPasswordData(ctx, params, func(o *Options) {
247			o.APIOptions = append(o.APIOptions, apiOptions...)
248		})
249
250		retryable, err := options.Retryable(ctx, params, out, err)
251		if err != nil {
252			return err
253		}
254		if !retryable {
255			return nil
256		}
257
258		remainingTime -= time.Since(start)
259		if remainingTime < options.MinDelay || remainingTime <= 0 {
260			break
261		}
262
263		// compute exponential backoff between waiter retries
264		delay, err := smithywaiter.ComputeDelay(
265			attempt, options.MinDelay, options.MaxDelay, remainingTime,
266		)
267		if err != nil {
268			return fmt.Errorf("error computing waiter delay, %w", err)
269		}
270
271		remainingTime -= delay
272		// sleep for the delay amount before invoking a request
273		if err := smithytime.SleepWithContext(ctx, delay); err != nil {
274			return fmt.Errorf("request cancelled while waiting, %w", err)
275		}
276	}
277	return fmt.Errorf("exceeded max wait time for PasswordDataAvailable waiter")
278}
279
280func passwordDataAvailableStateRetryable(ctx context.Context, input *GetPasswordDataInput, output *GetPasswordDataOutput, err error) (bool, error) {
281
282	if err == nil {
283		pathValue, err := jmespath.Search("length(PasswordData) > `0`", output)
284		if err != nil {
285			return false, fmt.Errorf("error evaluating waiter state: %w", err)
286		}
287
288		expectedValue := "true"
289		bv, err := strconv.ParseBool(expectedValue)
290		if err != nil {
291			return false, fmt.Errorf("error parsing boolean from string %w", err)
292		}
293		value, ok := pathValue.(bool)
294		if !ok {
295			return false, fmt.Errorf("waiter comparator expected bool value got %T", pathValue)
296		}
297
298		if value == bv {
299			return false, nil
300		}
301	}
302
303	return true, nil
304}
305
306func newServiceMetadataMiddleware_opGetPasswordData(region string) *awsmiddleware.RegisterServiceMetadata {
307	return &awsmiddleware.RegisterServiceMetadata{
308		Region:        region,
309		ServiceID:     ServiceID,
310		SigningName:   "ec2",
311		OperationName: "GetPasswordData",
312	}
313}
314