// Code generated by smithy-go-codegen DO NOT EDIT.

package secretsmanager

import (
	"context"
	"fmt"
	"github.com/aws/smithy-go/middleware"
	smithyhttp "github.com/aws/smithy-go/transport/http"
)

// Creates a new version of your secret by creating a new encrypted value and
// attaching it to the secret. version can contain a new SecretString value or a
// new SecretBinary value.
//
// Do not call PutSecretValue at a sustained rate of more than once every 10
// minutes. When you update the secret value, Secrets Manager creates a new version
// of the secret. Secrets Manager keeps 100 of the most recent versions, but it
// keeps all secret versions created in the last 24 hours. If you call
// PutSecretValue more than once every 10 minutes, you will create more versions
// than Secrets Manager removes, and you will reach the quota for secret versions.
//
// You can specify the staging labels to attach to the new version in VersionStages
// . If you don't include VersionStages , then Secrets Manager automatically moves
// the staging label AWSCURRENT to this version. If this operation creates the
// first version for the secret, then Secrets Manager automatically attaches the
// staging label AWSCURRENT to it. If this operation moves the staging label
// AWSCURRENT from another version to this version, then Secrets Manager also
// automatically moves the staging label AWSPREVIOUS to the version that AWSCURRENT
// was removed from.
//
// This operation is idempotent. If you call this operation with a
// ClientRequestToken that matches an existing version's VersionId, and you specify
// the same secret data, the operation succeeds but does nothing. However, if the
// secret data is different, then the operation fails because you can't modify an
// existing version; you can only create new ones.
//
// Secrets Manager generates a CloudTrail log entry when you call this action. Do
// not include sensitive information in request parameters except SecretBinary ,
// SecretString , or RotationToken because it might be logged. For more
// information, see [Logging Secrets Manager events with CloudTrail].
//
// Required permissions: secretsmanager:PutSecretValue . For more information, see [IAM policy actions for Secrets Manager]
// and [Authentication and access control in Secrets Manager].
//
// When you enter commands in a command shell, there is a risk of the command
// history being accessed or utilities having access to your command parameters.
// This is a concern if the command includes the value of a secret. Learn how to [Mitigate the risks of using command-line tools to store Secrets Manager secrets].
//
// [Authentication and access control in Secrets Manager]: https://docs.aws.amazon.com/secretsmanager/latest/userguide/auth-and-access.html
// [Logging Secrets Manager events with CloudTrail]: https://docs.aws.amazon.com/secretsmanager/latest/userguide/retrieve-ct-entries.html
// [Mitigate the risks of using command-line tools to store Secrets Manager secrets]: https://docs.aws.amazon.com/secretsmanager/latest/userguide/security_cli-exposure-risks.html
// [IAM policy actions for Secrets Manager]: https://docs.aws.amazon.com/secretsmanager/latest/userguide/reference_iam-permissions.html#reference_iam-permissions_actions
func (c *Client) PutSecretValue(ctx context.Context, params *PutSecretValueInput, optFns ...func(*Options)) (*PutSecretValueOutput, error) {
	if params == nil {
		params = &PutSecretValueInput{}
	}

	result, metadata, err := c.invokeOperation(ctx, "PutSecretValue", params, optFns, c.addOperationPutSecretValueMiddlewares)
	if err != nil {
		return nil, err
	}

	out := result.(*PutSecretValueOutput)
	out.ResultMetadata = metadata
	return out, nil
}

type PutSecretValueInput struct {

	// The ARN or name of the secret to add a new version to.
	//
	// For an ARN, we recommend that you specify a complete ARN rather than a partial
	// ARN. See [Finding a secret from a partial ARN].
	//
	// If the secret doesn't already exist, use CreateSecret instead.
	//
	// [Finding a secret from a partial ARN]: https://docs.aws.amazon.com/secretsmanager/latest/userguide/troubleshoot.html#ARN_secretnamehyphen
	//
	// This member is required.
	SecretId *string

	// A unique identifier for the new version of the secret.
	//
	// If you use the Amazon Web Services CLI or one of the Amazon Web Services SDKs
	// to call this operation, then you can leave this parameter empty. The CLI or SDK
	// generates a random UUID for you and includes it as the value for this parameter
	// in the request.
	//
	// If you generate a raw HTTP request to the Secrets Manager service endpoint,
	// then you must generate a ClientRequestToken and include it in the request.
	//
	// This value helps ensure idempotency. Secrets Manager uses this value to prevent
	// the accidental creation of duplicate versions if there are failures and retries
	// during a rotation. We recommend that you generate a [UUID-type]value to ensure uniqueness
	// of your versions within the specified secret.
	//
	//   - If the ClientRequestToken value isn't already associated with a version of
	//   the secret then a new version of the secret is created.
	//
	//   - If a version with this value already exists and that version's SecretString
	//   or SecretBinary values are the same as those in the request then the request
	//   is ignored. The operation is idempotent.
	//
	//   - If a version with this value already exists and the version of the
	//   SecretString and SecretBinary values are different from those in the request,
	//   then the request fails because you can't modify a secret version. You can only
	//   create new versions to store new secret values.
	//
	// This value becomes the VersionId of the new version.
	//
	// [UUID-type]: https://wikipedia.org/wiki/Universally_unique_identifier
	ClientRequestToken *string

	// A unique identifier that indicates the source of the request. Required for
	// secret rotations using an IAM assumed role or cross-account rotation, in which
	// you rotate a secret in one account by using a Lambda rotation function in
	// another account. In both cases, the rotation function assumes an IAM role to
	// call Secrets Manager, and then Secrets Manager validates the identity using the
	// token. For more information, see [How rotation works]and [Rotation by Lambda functions].
	//
	// Sensitive: This field contains sensitive information, so the service does not
	// include it in CloudTrail log entries. If you create your own log entries, you
	// must also avoid logging the information in this field.
	//
	// [Rotation by Lambda functions]: https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotate-secrets_lambda
	// [How rotation works]: https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets.html
	RotationToken *string

	// The binary data to encrypt and store in the new version of the secret. To use
	// this parameter in the command-line tools, we recommend that you store your
	// binary data in a file and then pass the contents of the file as a parameter.
	//
	// You must include SecretBinary or SecretString , but not both.
	//
	// You can't access this value from the Secrets Manager console.
	//
	// Sensitive: This field contains sensitive information, so the service does not
	// include it in CloudTrail log entries. If you create your own log entries, you
	// must also avoid logging the information in this field.
	SecretBinary []byte

	// The text to encrypt and store in the new version of the secret.
	//
	// You must include SecretBinary or SecretString , but not both.
	//
	// We recommend you create the secret string as JSON key/value pairs, as shown in
	// the example.
	//
	// Sensitive: This field contains sensitive information, so the service does not
	// include it in CloudTrail log entries. If you create your own log entries, you
	// must also avoid logging the information in this field.
	SecretString *string

	// A list of staging labels to attach to this version of the secret. Secrets
	// Manager uses staging labels to track versions of a secret through the rotation
	// process.
	//
	// If you specify a staging label that's already associated with a different
	// version of the same secret, then Secrets Manager removes the label from the
	// other version and attaches it to this version. If you specify AWSCURRENT , and
	// it is already attached to another version, then Secrets Manager also moves the
	// staging label AWSPREVIOUS to the version that AWSCURRENT was removed from.
	//
	// If you don't include VersionStages , then Secrets Manager automatically moves
	// the staging label AWSCURRENT to this version.
	VersionStages []string

	noSmithyDocumentSerde
}

type PutSecretValueOutput struct {

	// The ARN of the secret.
	ARN *string

	// The name of the secret.
	Name *string

	// The unique identifier of the version of the secret.
	VersionId *string

	// The list of staging labels that are currently attached to this version of the
	// secret. Secrets Manager uses staging labels to track a version as it progresses
	// through the secret rotation process.
	VersionStages []string

	// Metadata pertaining to the operation's result.
	ResultMetadata middleware.Metadata

	noSmithyDocumentSerde
}

func (c *Client) addOperationPutSecretValueMiddlewares(stack *middleware.Stack, options Options) (err error) {
	err = stack.Serialize.Add(&awsAwsjson11_serializeOpPutSecretValue{}, middleware.After)
	if err != nil {
		return err
	}
	err = stack.Deserialize.Add(&awsAwsjson11_deserializeOpPutSecretValue{}, middleware.After)
	if err != nil {
		return err
	}

	if err = addlegacyEndpointContextSetter(stack, options); err != nil {
		return err
	}
	if err = addComputeContentLength(stack); err != nil {
		return err
	}
	if err = addResolveEndpointMiddleware(stack, options); err != nil {
		return err
	}
	if err = addComputePayloadSHA256(stack); err != nil {
		return err
	}
	if err = addRecordResponseTiming(stack); err != nil {
		return err
	}
	if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil {
		return err
	}
	if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil {
		return err
	}
	if err = addCredentialSource(stack, options); err != nil {
		return err
	}
	if err = addIdempotencyToken_opPutSecretValueMiddleware(stack, options); err != nil {
		return err
	}
	if err = addOpPutSecretValueValidationMiddleware(stack); err != nil {
		return err
	}
	if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "PutSecretValue"), middleware.Before); err != nil {
		return err
	}
	if err = addRequestIDRetrieverMiddleware(stack); err != nil {
		return err
	}
	if err = addResponseErrorMiddleware(stack); err != nil {
		return err
	}
	if err = addRequestResponseLogging(stack, options); err != nil {
		return err
	}
	if err = addDisableHTTPSMiddleware(stack, options); err != nil {
		return err
	}
	if err = addInterceptors(stack, options); err != nil {
		return err
	}
	return nil
}

type idempotencyToken_initializeOpPutSecretValue struct {
	tokenProvider IdempotencyTokenProvider
}

func (*idempotencyToken_initializeOpPutSecretValue) ID() string {
	return "OperationIdempotencyTokenAutoFill"
}

func (m *idempotencyToken_initializeOpPutSecretValue) HandleInitialize(ctx context.Context, in middleware.InitializeInput, next middleware.InitializeHandler) (
	out middleware.InitializeOutput, metadata middleware.Metadata, err error,
) {
	if m.tokenProvider == nil {
		return next.HandleInitialize(ctx, in)
	}

	input, ok := in.Parameters.(*PutSecretValueInput)
	if !ok {
		return out, metadata, fmt.Errorf("expected middleware input to be of type *PutSecretValueInput ")
	}

	if input.ClientRequestToken == nil {
		t, err := m.tokenProvider.GetIdempotencyToken()
		if err != nil {
			return out, metadata, err
		}
		input.ClientRequestToken = &t
	}
	return next.HandleInitialize(ctx, in)
}
func addIdempotencyToken_opPutSecretValueMiddleware(stack *middleware.Stack, cfg Options) error {
	return stack.Initialize.Add(&idempotencyToken_initializeOpPutSecretValue{tokenProvider: cfg.IdempotencyTokenProvider}, middleware.Before)
}
