diff --git a/.doc_gen/metadata/rds_metadata.yaml b/.doc_gen/metadata/rds_metadata.yaml index be8513d2dde..5e69c798358 100644 --- a/.doc_gen/metadata/rds_metadata.yaml +++ b/.doc_gen/metadata/rds_metadata.yaml @@ -14,6 +14,14 @@ rds_Hello: - description: snippet_tags: - RDS.dotnetv3.HelloRds + Go: + versions: + - sdk_version: 2 + github: gov2/rds + excerpts: + - description: + snippet_tags: + - gov2.rds.Hello services: rds: {DescribeDBInstances} rds_CreateDBInstance: @@ -31,6 +39,15 @@ rds_CreateDBInstance: - description: snippet_tags: - RDS.dotnetv3.CreateDBInstance + Go: + versions: + - sdk_version: 2 + github: gov2/rds + excerpts: + - description: + snippet_tags: + - gov2.rds.DbInstances.struct + - gov2.rds.CreateDBInstance Kotlin: versions: - sdk_version: 1 @@ -86,6 +103,15 @@ rds_DeleteDBInstance: - description: snippet_tags: - RDS.dotnetv3.DeleteDBInstance + Go: + versions: + - sdk_version: 2 + github: gov2/rds + excerpts: + - description: + snippet_tags: + - gov2.rds.DbInstances.struct + - gov2.rds.DeleteDBInstance Kotlin: versions: - sdk_version: 1 @@ -167,6 +193,15 @@ rds_DescribeDBInstances: - description: snippet_tags: - RDS.dotnetv3.DescribeDbInstances + Go: + versions: + - sdk_version: 2 + github: gov2/rds + excerpts: + - description: + snippet_tags: + - gov2.rds.DbInstances.struct + - gov2.rds.DescribeDBInstances Kotlin: versions: - sdk_version: 1 @@ -282,6 +317,15 @@ rds_DescribeDBParameterGroups: - description: snippet_tags: - RDS.dotnetv3.DescribeDBParameterGroups + Go: + versions: + - sdk_version: 2 + github: gov2/rds + excerpts: + - description: + snippet_tags: + - gov2.rds.DbInstances.struct + - gov2.rds.DescribeDBParameterGroups Python: versions: - sdk_version: 3 @@ -339,6 +383,15 @@ rds_CreateDBParameterGroup: - description: snippet_tags: - RDS.dotnetv3.CreateDBParameterGroup + Go: + versions: + - sdk_version: 2 + github: gov2/rds + excerpts: + - description: + snippet_tags: + - gov2.rds.DbInstances.struct + - gov2.rds.CreateDBParameterGroup Python: versions: - sdk_version: 3 @@ -386,6 +439,15 @@ rds_DeleteDBParameterGroup: - description: snippet_tags: - RDS.dotnetv3.DeleteDBParameterGroup + Go: + versions: + - sdk_version: 2 + github: gov2/rds + excerpts: + - description: + snippet_tags: + - gov2.rds.DbInstances.struct + - gov2.rds.DeleteDBParameterGroup Python: versions: - sdk_version: 3 @@ -433,6 +495,15 @@ rds_DescribeDBParameters: - description: snippet_tags: - RDS.dotnetv3.DescribeDBParameters + Go: + versions: + - sdk_version: 2 + github: gov2/rds + excerpts: + - description: + snippet_tags: + - gov2.rds.DbInstances.struct + - gov2.rds.DescribeDBParameters Python: versions: - sdk_version: 3 @@ -489,6 +560,15 @@ rds_ModifyDBParameterGroup: - description: snippet_tags: - RDS.dotnetv3.ModifyDBParameterGroup + Go: + versions: + - sdk_version: 2 + github: gov2/rds + excerpts: + - description: + snippet_tags: + - gov2.rds.DbInstances.struct + - gov2.rds.ModifyDBParameterGroup Python: versions: - sdk_version: 3 @@ -536,6 +616,15 @@ rds_CreateDBSnapshot: - description: snippet_tags: - RDS.dotnetv3.CreateDBSnapshot + Go: + versions: + - sdk_version: 2 + github: gov2/rds + excerpts: + - description: + snippet_tags: + - gov2.rds.DbInstances.struct + - gov2.rds.CreateDBSnapshot Python: versions: - sdk_version: 3 @@ -583,6 +672,15 @@ rds_DescribeDBSnapshots: - description: snippet_tags: - RDS.dotnetv3.DescribeDBSnapshots + Go: + versions: + - sdk_version: 2 + github: gov2/rds + excerpts: + - description: + snippet_tags: + - gov2.rds.DbInstances.struct + - gov2.rds.DescribeDBSnapshots Python: versions: - sdk_version: 3 @@ -639,6 +737,15 @@ rds_DescribeDBEngineVersions: - description: snippet_tags: - RDS.dotnetv3.DescribeDBEngineVersions + Go: + versions: + - sdk_version: 2 + github: gov2/rds + excerpts: + - description: + snippet_tags: + - gov2.rds.DbInstances.struct + - gov2.rds.DescribeDBEngineVersions Python: versions: - sdk_version: 3 @@ -686,6 +793,15 @@ rds_DescribeOrderableDBInstanceOptions: - description: snippet_tags: - RDS.dotnetv3.DescribeOrderableDBInstanceOptions + Go: + versions: + - sdk_version: 2 + github: gov2/rds + excerpts: + - description: + snippet_tags: + - gov2.rds.DbInstances.struct + - gov2.rds.DescribeOrderableDBInstanceOptions Python: versions: - sdk_version: 3 @@ -773,6 +889,18 @@ rds_Scenario_GetStartedInstances: - description: Wrapper methods used by the scenario for DB snapshot actions. snippet_tags: - RDS.dotnetv3.RdsInstanceWrapperSnapshots + Go: + versions: + - sdk_version: 2 + github: gov2/rds + excerpts: + - description: Run an interactive scenario at a command prompt. + snippet_tags: + - gov2.rds.Scenario_GetStartedInstances + - description: Define functions that are called by the scenario to + manage &RDS; actions. + snippet_tags: + - gov2.rds.DbInstances.complete Python: versions: - sdk_version: 3 diff --git a/gov2/rds/README.md b/gov2/rds/README.md new file mode 100644 index 00000000000..24f80c2fd0f --- /dev/null +++ b/gov2/rds/README.md @@ -0,0 +1,129 @@ + +# Amazon RDS code examples for the SDK for Go V2 + +## Overview + +Shows how to use the AWS SDK for Go V2 to work with Amazon Relational Database Service (Amazon RDS). + + + + +*Amazon RDS is a web service that makes it easier to set up, operate, and scale a relational database in the cloud.* + +## ⚠ Important + +* Running this code might result in charges to your AWS account. +* Running the tests might result in charges to your AWS account. +* We recommend that you grant your code least privilege. At most, grant only the minimum permissions required to perform the task. For more information, see [Grant least privilege](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege). +* This code is not tested in every AWS Region. For more information, see [AWS Regional Services](https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services). + + + + +## Code examples + +### Prerequisites + +For prerequisites, see the [README](../README.md#Prerequisites) in the `gov2` folder. + + + + + + +### Get started + +* [Hello Amazon RDS](hello/hello.go#L4) (`DescribeDBInstances`) + +### Single actions + +Code excerpts that show you how to call individual service functions. + +* [Create a DB instance](actions/instances.go#L172) (`CreateDBInstance`) +* [Create a DB parameter group](actions/instances.go#L46) (`CreateDBParameterGroup`) +* [Create a snapshot of a DB instance](actions/instances.go#L135) (`CreateDBSnapshot`) +* [Delete a DB instance](actions/instances.go#L226) (`DeleteDBInstance`) +* [Delete a DB parameter group](actions/instances.go#L70) (`DeleteDBParameterGroup`) +* [Describe DB instances](actions/instances.go#L201) (`DescribeDBInstances`) +* [Describe DB parameter groups](actions/instances.go#L21) (`DescribeDBParameterGroups`) +* [Describe database engine versions](actions/instances.go#L245) (`DescribeDBEngineVersions`) +* [Describe options for DB instances](actions/instances.go#L266) (`DescribeOrderableDBInstanceOptions`) +* [Describe parameters in a DB parameter group](actions/instances.go#L88) (`DescribeDBParameters`) +* [Describe snapshots of DB instances](actions/instances.go#L154) (`DescribeDBSnapshots`) +* [Update parameters in a DB parameter group](actions/instances.go#L116) (`ModifyDBParameterGroup`) + +### Scenarios + +Code examples that show you how to accomplish a specific task by calling multiple +functions within the same service. + +* [Get started with DB instances](scenarios/get_started_instances.go) + +## Run the examples + +### Instructions + + + + + +#### Hello Amazon RDS + +This example shows you how to get started using Amazon RDS. + +``` +go run ./hello +``` + +#### Run a scenario + +All scenarios can be run with the `cmd` runner. To get a list of scenarios +and to get help for running a scenario, use the following command: + +``` +go run ./cmd -h +``` + +#### Get started with DB instances + +This example shows you how to do the following: + +* Create a custom DB parameter group and set parameter values. +* Create a DB instance that's configured to use the parameter group. The DB instance also contains a database. +* Take a snapshot of the instance. +* Delete the instance and parameter group. + + + + + + + + +### Tests + +⚠ Running tests might result in charges to your AWS account. + + +To find instructions for running these tests, see the [README](../README.md#Tests) +in the `gov2` folder. + + + + + + +## Additional resources + +* [Amazon RDS User Guide](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Welcome.html) +* [Amazon RDS API Reference](https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/Welcome.html) +* [SDK for Go V2 Amazon RDS reference](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/rds) + + + + +--- + +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 \ No newline at end of file diff --git a/gov2/rds/actions/instances.go b/gov2/rds/actions/instances.go new file mode 100644 index 00000000000..4f240d7926f --- /dev/null +++ b/gov2/rds/actions/instances.go @@ -0,0 +1,297 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package actions + +import ( + "context" + "errors" + "log" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/rds" + "github.com/aws/aws-sdk-go-v2/service/rds/types" +) + +// snippet-start:[gov2.rds.DbInstances.complete] +// snippet-start:[gov2.rds.DbInstances.struct] + +type DbInstances struct { + RdsClient *rds.Client +} + +// snippet-end:[gov2.rds.DbInstances.struct] +// snippet-start:[gov2.rds.DescribeDBParameterGroups] + +// GetParameterGroup gets a DB parameter group by name. +func (instances *DbInstances) GetParameterGroup(parameterGroupName string) ( + *types.DBParameterGroup, error) { + output, err := instances.RdsClient.DescribeDBParameterGroups( + context.TODO(), &rds.DescribeDBParameterGroupsInput{ + DBParameterGroupName: aws.String(parameterGroupName), + }) + if err != nil { + var notFoundError *types.DBParameterGroupNotFoundFault + if errors.As(err, ¬FoundError) { + log.Printf("Parameter group %v does not exist.\n", parameterGroupName) + err = nil + } else { + log.Printf("Error getting parameter group %v: %v\n", parameterGroupName, err) + } + return nil, err + } else { + return &output.DBParameterGroups[0], err + } +} + +// snippet-end:[gov2.rds.DescribeDBParameterGroups] + +// snippet-start:[gov2.rds.CreateDBParameterGroup] + +// CreateParameterGroup creates a DB parameter group that is based on the specified +// parameter group family. +func (instances *DbInstances) CreateParameterGroup( + parameterGroupName string, parameterGroupFamily string, description string) ( + *types.DBParameterGroup, error) { + + output, err := instances.RdsClient.CreateDBParameterGroup(context.TODO(), + &rds.CreateDBParameterGroupInput{ + DBParameterGroupName: aws.String(parameterGroupName), + DBParameterGroupFamily: aws.String(parameterGroupFamily), + Description: aws.String(description), + }) + if err != nil { + log.Printf("Couldn't create parameter group %v: %v\n", parameterGroupName, err) + return nil, err + } else { + return output.DBParameterGroup, err + } +} + +// snippet-end:[gov2.rds.CreateDBParameterGroup] + +// snippet-start:[gov2.rds.DeleteDBParameterGroup] + +// DeleteParameterGroup deletes the named DB parameter group. +func (instances *DbInstances) DeleteParameterGroup(parameterGroupName string) error { + _, err := instances.RdsClient.DeleteDBParameterGroup(context.TODO(), + &rds.DeleteDBParameterGroupInput{ + DBParameterGroupName: aws.String(parameterGroupName), + }) + if err != nil { + log.Printf("Couldn't delete parameter group %v: %v\n", parameterGroupName, err) + return err + } else { + return nil + } +} + +// snippet-end:[gov2.rds.DeleteDBParameterGroup] + +// snippet-start:[gov2.rds.DescribeDBParameters] + +// GetParameters gets the parameters that are contained in a DB parameter group. +func (instances *DbInstances) GetParameters(parameterGroupName string, source string) ( + []types.Parameter, error) { + + var output *rds.DescribeDBParametersOutput + var params []types.Parameter + var err error + parameterPaginator := rds.NewDescribeDBParametersPaginator(instances.RdsClient, + &rds.DescribeDBParametersInput{ + DBParameterGroupName: aws.String(parameterGroupName), + Source: aws.String(source), + }) + for parameterPaginator.HasMorePages() { + output, err = parameterPaginator.NextPage(context.TODO()) + if err != nil { + log.Printf("Couldn't get parameters for %v: %v\n", parameterGroupName, err) + break + } else { + params = append(params, output.Parameters...) + } + } + return params, err +} + +// snippet-end:[gov2.rds.DescribeDBParameters] + +// snippet-start:[gov2.rds.ModifyDBParameterGroup] + +// UpdateParameters updates parameters in a named DB parameter group. +func (instances *DbInstances) UpdateParameters(parameterGroupName string, params []types.Parameter) error { + _, err := instances.RdsClient.ModifyDBParameterGroup(context.TODO(), + &rds.ModifyDBParameterGroupInput{ + DBParameterGroupName: aws.String(parameterGroupName), + Parameters: params, + }) + if err != nil { + log.Printf("Couldn't update parameters in %v: %v\n", parameterGroupName, err) + return err + } else { + return nil + } +} + +// snippet-end:[gov2.rds.ModifyDBParameterGroup] + +// snippet-start:[gov2.rds.CreateDBSnapshot] + +// CreateSnapshot creates a snapshot of a DB instance. +func (instances *DbInstances) CreateSnapshot(instanceName string, snapshotName string) ( + *types.DBSnapshot, error) { + output, err := instances.RdsClient.CreateDBSnapshot(context.TODO(), &rds.CreateDBSnapshotInput{ + DBInstanceIdentifier: aws.String(instanceName), + DBSnapshotIdentifier: aws.String(snapshotName), + }) + if err != nil { + log.Printf("Couldn't create snapshot %v: %v\n", snapshotName, err) + return nil, err + } else { + return output.DBSnapshot, nil + } +} + +// snippet-end:[gov2.rds.CreateDBSnapshot] + +// snippet-start:[gov2.rds.DescribeDBSnapshots] + +// GetSnapshot gets a DB instance snapshot. +func (instances *DbInstances) GetSnapshot(snapshotName string) (*types.DBSnapshot, error) { + output, err := instances.RdsClient.DescribeDBSnapshots(context.TODO(), + &rds.DescribeDBSnapshotsInput{ + DBSnapshotIdentifier: aws.String(snapshotName), + }) + if err != nil { + log.Printf("Couldn't get snapshot %v: %v\n", snapshotName, err) + return nil, err + } else { + return &output.DBSnapshots[0], nil + } +} + +// snippet-end:[gov2.rds.DescribeDBSnapshots] + +// snippet-start:[gov2.rds.CreateDBInstance] + +// CreateInstance creates a DB instance. +func (instances *DbInstances) CreateInstance(instanceName string, dbName string, + dbEngine string, dbEngineVersion string, parameterGroupName string, dbInstanceClass string, + storageType string, allocatedStorage int32, adminName string, adminPassword string) ( + *types.DBInstance, error) { + output, err := instances.RdsClient.CreateDBInstance(context.TODO(), &rds.CreateDBInstanceInput{ + DBInstanceIdentifier: aws.String(instanceName), + DBName: aws.String(dbName), + DBParameterGroupName: aws.String(parameterGroupName), + Engine: aws.String(dbEngine), + EngineVersion: aws.String(dbEngineVersion), + DBInstanceClass: aws.String(dbInstanceClass), + StorageType: aws.String(storageType), + AllocatedStorage: aws.Int32(allocatedStorage), + MasterUsername: aws.String(adminName), + MasterUserPassword: aws.String(adminPassword), + }) + if err != nil { + log.Printf("Couldn't create instance %v: %v\n", instanceName, err) + return nil, err + } else { + return output.DBInstance, nil + } +} + +// snippet-end:[gov2.rds.CreateDBInstance] + +// snippet-start:[gov2.rds.DescribeDBInstances] + +// GetInstance gets data about a DB instance. +func (instances *DbInstances) GetInstance(instanceName string) ( + *types.DBInstance, error) { + output, err := instances.RdsClient.DescribeDBInstances(context.TODO(), + &rds.DescribeDBInstancesInput{ + DBInstanceIdentifier: aws.String(instanceName), + }) + if err != nil { + var notFoundError *types.DBInstanceNotFoundFault + if errors.As(err, ¬FoundError) { + log.Printf("DB instance %v does not exist.\n", instanceName) + err = nil + } else { + log.Printf("Couldn't get instance %v: %v\n", instanceName, err) + } + return nil, err + } else { + return &output.DBInstances[0], nil + } +} + +// snippet-end:[gov2.rds.DescribeDBInstances] + +// snippet-start:[gov2.rds.DeleteDBInstance] + +// DeleteInstance deletes a DB instance. +func (instances *DbInstances) DeleteInstance(instanceName string) error { + _, err := instances.RdsClient.DeleteDBInstance(context.TODO(), &rds.DeleteDBInstanceInput{ + DBInstanceIdentifier: aws.String(instanceName), + SkipFinalSnapshot: true, + DeleteAutomatedBackups: aws.Bool(true), + }) + if err != nil { + log.Printf("Couldn't delete instance %v: %v\n", instanceName, err) + return err + } else { + return nil + } +} + +// snippet-end:[gov2.rds.DeleteDBInstance] + +// snippet-start:[gov2.rds.DescribeDBEngineVersions] + +// GetEngineVersions gets database engine versions that are available for the specified engine +// and parameter group family. +func (instances *DbInstances) GetEngineVersions(engine string, parameterGroupFamily string) ( + []types.DBEngineVersion, error) { + output, err := instances.RdsClient.DescribeDBEngineVersions(context.TODO(), + &rds.DescribeDBEngineVersionsInput{ + Engine: aws.String(engine), + DBParameterGroupFamily: aws.String(parameterGroupFamily), + }) + if err != nil { + log.Printf("Couldn't get engine versions for %v: %v\n", engine, err) + return nil, err + } else { + return output.DBEngineVersions, nil + } +} + +// snippet-end:[gov2.rds.DescribeDBEngineVersions] + +// snippet-start:[gov2.rds.DescribeOrderableDBInstanceOptions] + +// GetOrderableInstances uses a paginator to get DB instance options that can be used to create DB instances that are +// compatible with a set of specifications. +func (instances *DbInstances) GetOrderableInstances(engine string, engineVersion string) ( + []types.OrderableDBInstanceOption, error) { + + var output *rds.DescribeOrderableDBInstanceOptionsOutput + var instanceOptions []types.OrderableDBInstanceOption + var err error + orderablePaginator := rds.NewDescribeOrderableDBInstanceOptionsPaginator(instances.RdsClient, + &rds.DescribeOrderableDBInstanceOptionsInput{ + Engine: aws.String(engine), + EngineVersion: aws.String(engineVersion), + }) + for orderablePaginator.HasMorePages() { + output, err = orderablePaginator.NextPage(context.TODO()) + if err != nil { + log.Printf("Couldn't get orderable DB instance options: %v\n", err) + break + } else { + instanceOptions = append(instanceOptions, output.OrderableDBInstanceOptions...) + } + } + return instanceOptions, err +} + +// snippet-end:[gov2.rds.DescribeOrderableDBInstanceOptions] +// snippet-end:[gov2.rds.DbInstances.complete] diff --git a/gov2/rds/cmd/main.go b/gov2/rds/cmd/main.go new file mode 100644 index 00000000000..68af89cfa31 --- /dev/null +++ b/gov2/rds/cmd/main.go @@ -0,0 +1,57 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "context" + "flag" + "fmt" + "log" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/config" + "github.com/awsdocs/aws-doc-sdk-examples/gov2/demotools" + "github.com/awsdocs/aws-doc-sdk-examples/gov2/rds/scenarios" +) + +// main loads default AWS credentials and configuration from the ~/.aws folder and runs +// a scenario specified by the `-scenario` flag. +// +// `-scenario` can be one of the following: +// +// - `instances` - Runs the interactive DB instances scenario that shows you how to use +// Amazon Relational Database Service (Amazon RDS) commands to work with DB instances and databases. +func main() { + scenarioMap := map[string]func(sdkConfig aws.Config){ + "instances": runInstanceScenario, + } + choices := make([]string, len(scenarioMap)) + choiceIndex := 0 + for choice := range scenarioMap { + choices[choiceIndex] = choice + choiceIndex++ + } + scenario := flag.String( + "scenario", "", + fmt.Sprintf("The scenario to run. Must be one of %v.", choices)) + flag.Parse() + + if runScenario, ok := scenarioMap[*scenario]; !ok { + fmt.Printf("'%v' is not a valid scenario.\n", *scenario) + flag.Usage() + } else { + sdkConfig, err := config.LoadDefaultConfig(context.TODO()) + if err != nil { + log.Fatalf("unable to load SDK config, %v", err) + } + + log.SetFlags(0) + runScenario(sdkConfig) + } +} + +func runInstanceScenario(sdkConfig aws.Config) { + scenario := scenarios.NewGetStartedInstances(sdkConfig, demotools.NewQuestioner(), scenarios.ScenarioHelper{}) + scenario.Run("mysql", "doc-example-parameter-group", "doc-example-instance", "docexampledb") +} diff --git a/gov2/rds/go.mod b/gov2/rds/go.mod new file mode 100644 index 00000000000..fbb2ed568f1 --- /dev/null +++ b/gov2/rds/go.mod @@ -0,0 +1,28 @@ +module github.com/awsdocs/aws-doc-sdk-examples/gov2/rds + +go 1.20 + +require ( + github.com/aws/aws-sdk-go-v2 v1.18.0 + github.com/aws/aws-sdk-go-v2/config v1.18.25 + github.com/aws/aws-sdk-go-v2/service/rds v1.45.0 + github.com/awsdocs/aws-doc-sdk-examples/gov2/demotools v0.0.0-20230628212925-0fb6bee5ebdf + github.com/awsdocs/aws-doc-sdk-examples/gov2/testtools v0.0.0-20230607202440-f35a0a23ae1e + github.com/google/uuid v1.3.0 +) + +require ( + github.com/aws/aws-sdk-go-v2/credentials v1.13.24 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.3 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.33 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.27 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.3.34 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.27 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.12.10 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.10 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.19.0 // indirect + github.com/aws/smithy-go v1.13.5 // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect + golang.org/x/sys v0.9.0 // indirect + golang.org/x/term v0.9.0 // indirect +) diff --git a/gov2/rds/go.sum b/gov2/rds/go.sum new file mode 100644 index 00000000000..b9a77799e2d --- /dev/null +++ b/gov2/rds/go.sum @@ -0,0 +1,52 @@ +github.com/aws/aws-sdk-go-v2 v1.18.0 h1:882kkTpSFhdgYRKVZ/VCgf7sd0ru57p2JCxz4/oN5RY= +github.com/aws/aws-sdk-go-v2 v1.18.0/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= +github.com/aws/aws-sdk-go-v2/config v1.18.25 h1:JuYyZcnMPBiFqn87L2cRppo+rNwgah6YwD3VuyvaW6Q= +github.com/aws/aws-sdk-go-v2/config v1.18.25/go.mod h1:dZnYpD5wTW/dQF0rRNLVypB396zWCcPiBIvdvSWHEg4= +github.com/aws/aws-sdk-go-v2/credentials v1.13.24 h1:PjiYyls3QdCrzqUN35jMWtUK1vqVZ+zLfdOa/UPFDp0= +github.com/aws/aws-sdk-go-v2/credentials v1.13.24/go.mod h1:jYPYi99wUOPIFi0rhiOvXeSEReVOzBqFNOX5bXYoG2o= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.3 h1:jJPgroehGvjrde3XufFIJUZVK5A2L9a3KwSFgKy9n8w= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.3/go.mod h1:4Q0UFP0YJf0NrsEuEYHpM9fTSEVnD16Z3uyEF7J9JGM= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.33 h1:kG5eQilShqmJbv11XL1VpyDbaEJzWxd4zRiCG30GSn4= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.33/go.mod h1:7i0PF1ME/2eUPFcjkVIwq+DOygHEoK92t5cDqNgYbIw= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.27 h1:vFQlirhuM8lLlpI7imKOMsjdQLuN9CPi+k44F/OFVsk= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.27/go.mod h1:UrHnn3QV/d0pBZ6QBAEQcqFLf8FAzLmoUfPVIueOvoM= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.34 h1:gGLG7yKaXG02/jBlg210R7VgQIotiQntNhsCFejawx8= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.34/go.mod h1:Etz2dj6UHYuw+Xw830KfzCfWGMzqvUTCjUj5b76GVDc= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.27 h1:0iKliEXAcCa2qVtRs7Ot5hItA2MsufrphbRFlz1Owxo= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.27/go.mod h1:EOwBD4J4S5qYszS5/3DpkejfuK+Z5/1uzICfPaZLtqw= +github.com/aws/aws-sdk-go-v2/service/rds v1.45.0 h1:Yi23UNiGidNfT7tIW0lbE6JtRR1ZN+cNZGRTKLB+opk= +github.com/aws/aws-sdk-go-v2/service/rds v1.45.0/go.mod h1:rS6T0DrjdZ5LDr8ZC/J9iZdD1oSbie5reWWzqv5zLOw= +github.com/aws/aws-sdk-go-v2/service/sso v1.12.10 h1:UBQjaMTCKwyUYwiVnUt6toEJwGXsLBI6al083tpjJzY= +github.com/aws/aws-sdk-go-v2/service/sso v1.12.10/go.mod h1:ouy2P4z6sJN70fR3ka3wD3Ro3KezSxU6eKGQI2+2fjI= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.10 h1:PkHIIJs8qvq0e5QybnZoG1K/9QTrLr9OsqCIo59jOBA= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.10/go.mod h1:AFvkxc8xfBe8XA+5St5XIHHrQQtkxqrRincx4hmMHOk= +github.com/aws/aws-sdk-go-v2/service/sts v1.19.0 h1:2DQLAKDteoEDI8zpCzqBMaZlJuoE9iTYD0gFmXVax9E= +github.com/aws/aws-sdk-go-v2/service/sts v1.19.0/go.mod h1:BgQOMsg8av8jset59jelyPW7NoZcZXLVpDsXunGDrk8= +github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8= +github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= +github.com/awsdocs/aws-doc-sdk-examples/gov2/demotools v0.0.0-20230608210941-bf53c23f4b7c h1:G6/y3JOyzpSkmCPh+9AWFlXrBzT/9GnR8FKqxPz1Fz0= +github.com/awsdocs/aws-doc-sdk-examples/gov2/demotools v0.0.0-20230608210941-bf53c23f4b7c/go.mod h1:0r22nlw0YYkUMowQkNluzs2dc8kf6s2bg9Oema9TzlE= +github.com/awsdocs/aws-doc-sdk-examples/gov2/demotools v0.0.0-20230628212925-0fb6bee5ebdf h1:neH4MzDJWEsHKroLSuWMXon0nP+JGTscA05zYncU7Ms= +github.com/awsdocs/aws-doc-sdk-examples/gov2/demotools v0.0.0-20230628212925-0fb6bee5ebdf/go.mod h1:bcgBgQb+DUAGU6d0P3fokzUUhPz2pHhnsQ9Acj6aUcY= +github.com/awsdocs/aws-doc-sdk-examples/gov2/testtools v0.0.0-20230607202440-f35a0a23ae1e h1:OzVa50JLYmUgvOgW82VnMGXAzBQju/++drF4GDDBlNs= +github.com/awsdocs/aws-doc-sdk-examples/gov2/testtools v0.0.0-20230607202440-f35a0a23ae1e/go.mod h1:qcs782jWmSQW2exwfKW39rOvOJBZ4xzO8dVLoFF62Sc= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= +golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.9.0 h1:GRRCnKYhdQrD8kfRAdQ6Zcw1P0OcELxGLKJvtjVMZ28= +golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/gov2/rds/hello/hello.go b/gov2/rds/hello/hello.go new file mode 100644 index 00000000000..0e2bacdc8d9 --- /dev/null +++ b/gov2/rds/hello/hello.go @@ -0,0 +1,47 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// snippet-start:[gov2.rds.Hello] + +package main + +import ( + "context" + "fmt" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/service/rds" +) + +// main uses the AWS SDK for Go V2 to create an Amazon Relational Database Service (Amazon RDS) +// client and list up to 20 DB instances in your account. +// This example uses the default settings specified in your shared credentials +// and config files. +func main() { + sdkConfig, err := config.LoadDefaultConfig(context.TODO()) + if err != nil { + fmt.Println("Couldn't load default configuration. Have you set up your AWS account?") + fmt.Println(err) + return + } + rdsClient := rds.NewFromConfig(sdkConfig) + const maxInstances = 20 + fmt.Printf("Let's list up to %v DB instances.\n", maxInstances) + output, err := rdsClient.DescribeDBInstances(context.TODO(), + &rds.DescribeDBInstancesInput{MaxRecords: aws.Int32(maxInstances)}) + if err != nil { + fmt.Printf("Couldn't list DB instances: %v\n", err) + return + } + if len(output.DBInstances) == 0 { + fmt.Println("No DB instances found.") + } else { + for _, instance := range output.DBInstances { + fmt.Printf("DB instance %v has database %v.\n", *instance.DBInstanceIdentifier, + *instance.DBName) + } + } +} + +// snippet-end:[gov2.rds.Hello] diff --git a/gov2/rds/scenarios/get_started_instances.go b/gov2/rds/scenarios/get_started_instances.go new file mode 100644 index 00000000000..1d989f0a373 --- /dev/null +++ b/gov2/rds/scenarios/get_started_instances.go @@ -0,0 +1,341 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package scenarios + +import ( + "fmt" + "log" + "sort" + "strconv" + "strings" + "time" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/rds" + "github.com/aws/aws-sdk-go-v2/service/rds/types" + "github.com/awsdocs/aws-doc-sdk-examples/gov2/demotools" + "github.com/awsdocs/aws-doc-sdk-examples/gov2/rds/actions" + "github.com/google/uuid" +) + +// IScenarioHelper abstracts the function from a scenario so that it +// can be mocked for unit testing. +type IScenarioHelper interface { + Pause(secs int) + UniqueId() string +} +type ScenarioHelper struct{} + +// Pause waits for the specified number of seconds. +func (helper ScenarioHelper) Pause(secs int) { + time.Sleep(time.Duration(secs) * time.Second) +} + +// UniqueId returns a new UUID. +func (helper ScenarioHelper) UniqueId() string { + return uuid.New().String() +} + +// snippet-start:[gov2.rds.Scenario_GetStartedInstances] + +// GetStartedInstances is an interactive example that shows you how to use the AWS SDK for Go +// with Amazon Relation Database Service (Amazon RDS) to do the following: +// +// 1. Create a custom DB parameter group and set parameter values. +// 2. Create a DB instance that is configured to use the parameter group. The DB instance +// also contains a database. +// 3. Take a snapshot of the DB instance. +// 4. Delete the DB instance and parameter group. +type GetStartedInstances struct { + sdkConfig aws.Config + instances actions.DbInstances + questioner demotools.IQuestioner + helper IScenarioHelper + isTestRun bool +} + +// NewGetStartedInstances constructs a GetStartedInstances instance from a configuration. +// It uses the specified config to get an Amazon RDS +// client and create wrappers for the actions used in the scenario. +func NewGetStartedInstances(sdkConfig aws.Config, questioner demotools.IQuestioner, + helper IScenarioHelper) GetStartedInstances { + rdsClient := rds.NewFromConfig(sdkConfig) + return GetStartedInstances{ + sdkConfig: sdkConfig, + instances: actions.DbInstances{RdsClient: rdsClient}, + questioner: questioner, + helper: helper, + } +} + +// Run runs the interactive scenario. +func (scenario GetStartedInstances) Run(dbEngine string, parameterGroupName string, + instanceName string, dbName string) { + defer func() { + if r := recover(); r != nil { + log.Println("Something went wrong with the demo.") + } + }() + + log.Println(strings.Repeat("-", 88)) + log.Println("Welcome to the Amazon Relational Database Service (Amazon RDS) DB Instance demo.") + log.Println(strings.Repeat("-", 88)) + + parameterGroup := scenario.CreateParameterGroup(dbEngine, parameterGroupName) + scenario.SetUserParameters(parameterGroupName) + instance := scenario.CreateInstance(instanceName, dbEngine, dbName, parameterGroup) + scenario.DisplayConnection(instance) + scenario.CreateSnapshot(instance) + scenario.Cleanup(instance, parameterGroup) + + log.Println(strings.Repeat("-", 88)) + log.Println("Thanks for watching!") + log.Println(strings.Repeat("-", 88)) +} + +// CreateParameterGroup shows how to get available engine versions for a specified +// database engine and create a DB parameter group that is compatible with a +// selected engine family. +func (scenario GetStartedInstances) CreateParameterGroup(dbEngine string, + parameterGroupName string) *types.DBParameterGroup { + + log.Printf("Checking for an existing DB parameter group named %v.\n", + parameterGroupName) + parameterGroup, err := scenario.instances.GetParameterGroup(parameterGroupName) + if err != nil { + panic(err) + } + if parameterGroup == nil { + log.Printf("Getting available database engine versions for %v.\n", dbEngine) + engineVersions, err := scenario.instances.GetEngineVersions(dbEngine, "") + if err != nil { + panic(err) + } + + familySet := map[string]struct{}{} + for _, family := range engineVersions { + familySet[*family.DBParameterGroupFamily] = struct{}{} + } + var families []string + for family := range familySet { + families = append(families, family) + } + sort.Strings(families) + familyIndex := scenario.questioner.AskChoice("Which family do you want to use?\n", families) + log.Println("Creating a DB parameter group.") + _, err = scenario.instances.CreateParameterGroup( + parameterGroupName, families[familyIndex], "Example parameter group.") + if err != nil { + panic(err) + } + parameterGroup, err = scenario.instances.GetParameterGroup(parameterGroupName) + if err != nil { + panic(err) + } + } + log.Printf("Parameter group %v:\n", *parameterGroup.DBParameterGroupFamily) + log.Printf("\tName: %v\n", *parameterGroup.DBParameterGroupName) + log.Printf("\tARN: %v\n", *parameterGroup.DBParameterGroupArn) + log.Printf("\tFamily: %v\n", *parameterGroup.DBParameterGroupFamily) + log.Printf("\tDescription: %v\n", *parameterGroup.Description) + log.Println(strings.Repeat("-", 88)) + return parameterGroup +} + +// SetUserParameters shows how to get the parameters contained in a custom parameter +// group and update some of the parameter values in the group. +func (scenario GetStartedInstances) SetUserParameters(parameterGroupName string) { + log.Println("Let's set some parameter values in your parameter group.") + dbParameters, err := scenario.instances.GetParameters(parameterGroupName, "") + if err != nil { + panic(err) + } + var updateParams []types.Parameter + for _, dbParam := range dbParameters { + if strings.HasPrefix(*dbParam.ParameterName, "auto_increment") && + dbParam.IsModifiable && *dbParam.DataType == "integer" { + log.Printf("The %v parameter is described as:\n\t%v", + *dbParam.ParameterName, *dbParam.Description) + rangeSplit := strings.Split(*dbParam.AllowedValues, "-") + lower, _ := strconv.Atoi(rangeSplit[0]) + upper, _ := strconv.Atoi(rangeSplit[1]) + newValue := scenario.questioner.AskInt( + fmt.Sprintf("Enter a value between %v and %v:", lower, upper), + demotools.InIntRange{Lower: lower, Upper: upper}) + dbParam.ParameterValue = aws.String(strconv.Itoa(newValue)) + updateParams = append(updateParams, dbParam) + } + } + err = scenario.instances.UpdateParameters(parameterGroupName, updateParams) + if err != nil { + panic(err) + } + log.Println("To get a list of parameters that you set previously, specify a source of 'user'.") + userParameters, err := scenario.instances.GetParameters(parameterGroupName, "user") + if err != nil { + panic(err) + } + log.Println("Here are the parameters you set:") + for _, param := range userParameters { + log.Printf("\t%v: %v\n", *param.ParameterName, *param.ParameterValue) + } + log.Println(strings.Repeat("-", 88)) +} + +// CreateInstance shows how to create a DB instance that contains a database of a +// specified type. The database is also configured to use a custom DB parameter group. +func (scenario GetStartedInstances) CreateInstance(instanceName string, dbEngine string, + dbName string, parameterGroup *types.DBParameterGroup) *types.DBInstance { + + log.Println("Checking for an existing DB instance.") + instance, err := scenario.instances.GetInstance(instanceName) + if err != nil { + panic(err) + } + if instance == nil { + adminUsername := scenario.questioner.Ask( + "Enter an administrator username for the database: ", demotools.NotEmpty{}) + adminPassword := scenario.questioner.AskPassword( + "Enter a password for the administrator (at least 8 characters): ", 7) + engineVersions, err := scenario.instances.GetEngineVersions(dbEngine, + *parameterGroup.DBParameterGroupFamily) + if err != nil { + panic(err) + } + var engineChoices []string + for _, engine := range engineVersions { + engineChoices = append(engineChoices, *engine.EngineVersion) + } + engineIndex := scenario.questioner.AskChoice( + "The available engines for your parameter group are:\n", engineChoices) + engineSelection := engineVersions[engineIndex] + instOpts, err := scenario.instances.GetOrderableInstances(*engineSelection.Engine, + *engineSelection.EngineVersion) + if err != nil { + panic(err) + } + optSet := map[string]struct{}{} + for _, opt := range instOpts { + if strings.Contains(*opt.DBInstanceClass, "micro") { + optSet[*opt.DBInstanceClass] = struct{}{} + } + } + var optChoices []string + for opt := range optSet { + optChoices = append(optChoices, opt) + } + sort.Strings(optChoices) + optIndex := scenario.questioner.AskChoice( + "The available micro DB instance classes for your database engine are:\n", optChoices) + storageType := "standard" + allocatedStorage := int32(5) + log.Printf("Creating a DB instance named %v and database %v.\n"+ + "The DB instance is configured to use your custom parameter group %v,\n"+ + "selected engine %v,\n"+ + "selected DB instance class %v,"+ + "and %v GiB of %v storage.\n"+ + "This typically takes several minutes.", + instanceName, dbName, *parameterGroup.DBParameterGroupName, *engineSelection.EngineVersion, + optChoices[optIndex], allocatedStorage, storageType) + instance, err = scenario.instances.CreateInstance( + instanceName, dbName, *engineSelection.Engine, *engineSelection.EngineVersion, + *parameterGroup.DBParameterGroupName, optChoices[optIndex], storageType, + allocatedStorage, adminUsername, adminPassword) + if err != nil { + panic(err) + } + for *instance.DBInstanceStatus != "available" { + scenario.helper.Pause(30) + instance, err = scenario.instances.GetInstance(instanceName) + if err != nil { + panic(err) + } + } + log.Println("Instance created and available.") + } + log.Println("Instance data:") + log.Printf("\tDBInstanceIdentifier: %v\n", *instance.DBInstanceIdentifier) + log.Printf("\tARN: %v\n", *instance.DBInstanceArn) + log.Printf("\tStatus: %v\n", *instance.DBInstanceStatus) + log.Printf("\tEngine: %v\n", *instance.Engine) + log.Printf("\tEngine version: %v\n", *instance.EngineVersion) + log.Println(strings.Repeat("-", 88)) + return instance +} + +// DisplayConnection displays connection information about a DB instance and tips +// on how to connect to it. +func (scenario GetStartedInstances) DisplayConnection(instance *types.DBInstance) { + log.Println( + "You can now connect to your database by using your favorite MySQL client.\n" + + "One way to connect is by using the 'mysql' shell on an Amazon EC2 instance\n" + + "that is running in the same VPC as your DB instance. Pass the endpoint,\n" + + "port, and administrator username to 'mysql'. Then, enter your password\n" + + "when prompted:") + log.Printf("\n\tmysql -h %v -P %v -u %v -p\n", + *instance.Endpoint.Address, instance.Endpoint.Port, *instance.MasterUsername) + log.Println("For more information, see the User Guide for RDS:\n" + + "\thttps://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_GettingStarted.CreatingConnecting.MySQL.html#CHAP_GettingStarted.Connecting.MySQL") + log.Println(strings.Repeat("-", 88)) +} + +// CreateSnapshot shows how to create a DB instance snapshot and wait until it's available. +func (scenario GetStartedInstances) CreateSnapshot(instance *types.DBInstance) { + if scenario.questioner.AskBool( + "Do you want to create a snapshot of your DB instance (y/n)? ", "y") { + snapshotId := fmt.Sprintf("%v-%v", *instance.DBInstanceIdentifier, scenario.helper.UniqueId()) + log.Printf("Creating a snapshot named %v. This typically takes a few minutes.\n", snapshotId) + snapshot, err := scenario.instances.CreateSnapshot(*instance.DBInstanceIdentifier, snapshotId) + if err != nil { + panic(err) + } + for *snapshot.Status != "available" { + scenario.helper.Pause(30) + snapshot, err = scenario.instances.GetSnapshot(snapshotId) + if err != nil { + panic(err) + } + } + log.Println("Snapshot data:") + log.Printf("\tDBSnapshotIdentifier: %v\n", *snapshot.DBSnapshotIdentifier) + log.Printf("\tARN: %v\n", *snapshot.DBSnapshotArn) + log.Printf("\tStatus: %v\n", *snapshot.Status) + log.Printf("\tEngine: %v\n", *snapshot.Engine) + log.Printf("\tEngine version: %v\n", *snapshot.EngineVersion) + log.Printf("\tDBInstanceIdentifier: %v\n", *snapshot.DBInstanceIdentifier) + log.Printf("\tSnapshotCreateTime: %v\n", *snapshot.SnapshotCreateTime) + log.Println(strings.Repeat("-", 88)) + } +} + +// Cleanup shows how to clean up a DB instance and DB parameter group. +// Before the DB parameter group can be deleted, all associated DB instances must first be deleted. +func (scenario GetStartedInstances) Cleanup( + instance *types.DBInstance, parameterGroup *types.DBParameterGroup) { + + if scenario.questioner.AskBool( + "\nDo you want to delete the database instance and parameter group (y/n)? ", "y") { + log.Printf("Deleting database instance %v.\n", *instance.DBInstanceIdentifier) + err := scenario.instances.DeleteInstance(*instance.DBInstanceIdentifier) + if err != nil { + panic(err) + } + log.Println( + "Waiting for the DB instance to delete. This typically takes several minutes.") + for instance != nil { + scenario.helper.Pause(30) + instance, err = scenario.instances.GetInstance(*instance.DBInstanceIdentifier) + if err != nil { + panic(err) + } + } + log.Printf("Deleting parameter group %v.", *parameterGroup.DBParameterGroupName) + err = scenario.instances.DeleteParameterGroup(*parameterGroup.DBParameterGroupName) + if err != nil { + panic(err) + } + } +} + +// snippet-end:[gov2.rds.Scenario_GetStartedInstances] diff --git a/gov2/rds/scenarios/get_started_instances_integ_test.go b/gov2/rds/scenarios/get_started_instances_integ_test.go new file mode 100644 index 00000000000..a497aea8ada --- /dev/null +++ b/gov2/rds/scenarios/get_started_instances_integ_test.go @@ -0,0 +1,74 @@ +//go:build integration +// +build integration + +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package scenarios + +import ( + "bytes" + "context" + "fmt" + "log" + "os" + "strings" + "testing" + "time" + + "github.com/aws/aws-sdk-go-v2/config" + "github.com/awsdocs/aws-doc-sdk-examples/gov2/demotools" +) + +// IntegHelper adds functionality to a ScenarioHelper for integration tests. +type IntegHelper struct { + ScenarioHelper +} + +// Pause increases all pause durations by 5 seconds. This is needed during integration +// testing to make sure that AWS has enough time to create all resources. +func (helper IntegHelper) Pause(secs int) { + time.Sleep(time.Duration(secs+5) * time.Second) +} + +func TestRunGetStartedClustersScenario_Integration(t *testing.T) { + helper := IntegHelper{ + ScenarioHelper{}, + } + mockQuestioner := &demotools.MockQuestioner{ + Answers: []string{ + // CreateParameterGroup + "1", + // SetUserParameters + "2", "3", + // CreateInstance + "testadmin", fmt.Sprintf("pw-%v", helper.UniqueId()), "1", "1", + // CreateSnapshot + "y", + // Cleanup + "y", + }, + } + + sdkConfig, err := config.LoadDefaultConfig(context.TODO()) + if err != nil { + log.Fatalf("unable to load SDK config, %v", err) + } + + log.SetFlags(0) + var buf bytes.Buffer + log.SetOutput(&buf) + + scenario := NewGetStartedInstances(sdkConfig, mockQuestioner, &helper) + testId := time.Now().Unix() + scenario.Run( + "mysql", + fmt.Sprintf("doc-example-parameter-group-%v", testId), + fmt.Sprintf("doc-example-instance-%v", testId), + "docexampledbinteg") + + log.SetOutput(os.Stderr) + if !strings.Contains(buf.String(), "Thanks for watching") { + t.Errorf("didn't run to successful completion. Here's the log:\n%v", buf.String()) + } +} diff --git a/gov2/rds/scenarios/get_started_instances_test.go b/gov2/rds/scenarios/get_started_instances_test.go new file mode 100644 index 00000000000..b79c6a74beb --- /dev/null +++ b/gov2/rds/scenarios/get_started_instances_test.go @@ -0,0 +1,143 @@ +package scenarios + +import ( + "fmt" + "strconv" + "testing" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/rds/types" + "github.com/awsdocs/aws-doc-sdk-examples/gov2/demotools" + "github.com/awsdocs/aws-doc-sdk-examples/gov2/rds/stubs" + "github.com/awsdocs/aws-doc-sdk-examples/gov2/testtools" +) + +// TestRunScenario runs the scenario multiple times. The first time, it runs with no +// errors. In subsequent runs, it specifies that each stub in the sequence should +// raise an error and verifies the results. +func TestRunScenario(t *testing.T) { + scenTest := GetStartedInstancesTest{} + testtools.RunScenarioTests(&scenTest, t) +} + +// GetStartedInstancesTest encapsulates data for a scenario test. +type GetStartedInstancesTest struct { + Answers []string + helper instancesTestHelper + dbEngine string + parameterGroupName string + instanceName string + dbName string +} + +// SetupDataAndStubs sets up test data and builds the stubs that are used to return +// mocked data. +func (scenTest *GetStartedInstancesTest) SetupDataAndStubs() []testtools.Stub { + scenTest.dbEngine = "test-engine" + scenTest.parameterGroupName = "test-parameter-group" + scenTest.instanceName = "test-instance" + scenTest.dbName = "test-database" + + families := []string{"family-1", "family-2", "family-3"} + familyChoice := 1 + params := []types.Parameter{{ + ParameterName: aws.String("auto_increment_param1"), ParameterValue: aws.String("1"), + AllowedValues: aws.String("1-10"), Description: aws.String("Test desc"), IsModifiable: true, + DataType: aws.String("integer"), + }, { + ParameterName: aws.String("auto_increment_param2"), ParameterValue: aws.String("2"), + AllowedValues: aws.String("1-10"), Description: aws.String("Test desc"), IsModifiable: true, + DataType: aws.String("integer"), + }, { + ParameterName: aws.String("another_param"), ParameterValue: aws.String("3"), + AllowedValues: aws.String("1-10"), Description: aws.String("Test desc"), IsModifiable: true, + DataType: aws.String("integer"), + }} + updateParams := make([]types.Parameter, 2) + copy(updateParams, params[:2]) + updateParams[0].ParameterValue = aws.String("4") + updateParams[1].ParameterValue = aws.String("5") + adminName := "admin" + adminPassword := "password" + engineVersionChoice := 1 + engineVersion := fmt.Sprintf("%v-%v", scenTest.dbEngine, engineVersionChoice) + instanceClasses := []string{"micro-1", "micro-2", "micro-3"} + instanceChoice := 1 + snapshotId := fmt.Sprintf("%v-%v", scenTest.instanceName, scenTest.helper.UniqueId()) + + scenTest.helper = instancesTestHelper{} + scenTest.Answers = []string{ + // CreateParameterGroup + strconv.Itoa(familyChoice), + // SetUserParameters + *updateParams[0].ParameterValue, *updateParams[1].ParameterValue, + // CreateInstance + adminName, adminPassword, strconv.Itoa(engineVersionChoice), strconv.Itoa(instanceChoice), + // CreateSnapshot + "y", + // Cleanup + "y", + } + + var stubList []testtools.Stub + + // CreateParameterGroup + stubList = append(stubList, stubs.StubGetParameterGroup(scenTest.parameterGroupName, families[familyChoice], + &testtools.StubError{Err: &types.DBParameterGroupNotFoundFault{}, ContinueAfter: true})) + stubList = append(stubList, stubs.StubGetEngineVersions(scenTest.dbEngine, "", families, nil)) + stubList = append(stubList, stubs.StubCreateParameterGroup(scenTest.parameterGroupName, + families[familyChoice], "Example parameter group.", nil)) + stubList = append(stubList, stubs.StubGetParameterGroup(scenTest.parameterGroupName, families[familyChoice], nil)) + + // SetUserParameters + stubList = append(stubList, stubs.StubGetParameters(scenTest.parameterGroupName, "", params, nil)) + stubList = append(stubList, stubs.StubUpdateParameters(scenTest.parameterGroupName, updateParams, nil)) + stubList = append(stubList, stubs.StubGetParameters(scenTest.parameterGroupName, "user", updateParams, nil)) + + // CreateInstance + stubList = append(stubList, stubs.StubGetInstance(scenTest.dbName, "", + &testtools.StubError{Err: &types.DBInstanceNotFoundFault{}, ContinueAfter: true})) + stubList = append(stubList, stubs.StubGetEngineVersions(scenTest.dbEngine, families[familyChoice], families, nil)) + stubList = append(stubList, stubs.StubGetOrderableInstances(scenTest.dbEngine, engineVersion, instanceClasses, nil)) + stubList = append(stubList, stubs.StubCreateInstance(scenTest.instanceName, scenTest.dbName, + scenTest.dbEngine, engineVersion, scenTest.parameterGroupName, instanceClasses[instanceChoice], + "standard", int32(5), adminName, adminPassword, nil)) + stubList = append(stubList, stubs.StubGetInstance(scenTest.instanceName, "available", nil)) + + // DisplayConnection - No stubs needed. + + // CreateSnapshot + stubList = append(stubList, stubs.StubCreateSnapshot(scenTest.instanceName, snapshotId, nil)) + stubList = append(stubList, stubs.StubGetSnapshot(snapshotId, "available", nil)) + + // Cleanup + stubList = append(stubList, stubs.StubDeleteInstance(scenTest.instanceName, nil)) + stubList = append(stubList, stubs.StubGetInstance(scenTest.instanceName, "", + &testtools.StubError{Err: &types.DBInstanceNotFoundFault{}, ContinueAfter: true})) + stubList = append(stubList, stubs.StubDeleteParameterGroup(scenTest.parameterGroupName, nil)) + + return stubList +} + +// RunSubTest performs a single test run with a set of stubs set up to run with +// or without errors. +func (scenTest *GetStartedInstancesTest) RunSubTest(stubber *testtools.AwsmStubber) { + mockQuestioner := demotools.MockQuestioner{Answers: scenTest.Answers} + scenario := NewGetStartedInstances(*stubber.SdkConfig, &mockQuestioner, &scenTest.helper) + scenario.isTestRun = true + scenario.Run(scenTest.dbEngine, scenTest.parameterGroupName, scenTest.instanceName, scenTest.dbName) +} + +func (scenTest *GetStartedInstancesTest) Cleanup() {} + +// instancesTestHelper implements IScenarioHelper for unit testing. +type instancesTestHelper struct { +} + +// Pause does nothing during unit testing. +func (helper *instancesTestHelper) Pause(secs int) {} + +// UniqueId returns a known unique ID for unit testing. +func (helper *instancesTestHelper) UniqueId() string { + return "test-id" +} diff --git a/gov2/rds/stubs/instances_stubs.go b/gov2/rds/stubs/instances_stubs.go new file mode 100644 index 00000000000..1a8f4c8bb03 --- /dev/null +++ b/gov2/rds/stubs/instances_stubs.go @@ -0,0 +1,249 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Package stubs defines service action stubs that are used by both the action and +// scenario unit tests. +// +// Each stub expects specific data as input and returns specific data as an output. +// If an error is specified, it is raised by the stubber. +package stubs + +import ( + "fmt" + "time" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/rds" + "github.com/aws/aws-sdk-go-v2/service/rds/types" + "github.com/awsdocs/aws-doc-sdk-examples/gov2/testtools" +) + +func StubGetParameterGroup(parameterGroupName string, parameterGroupFamily string, + raiseErr *testtools.StubError) testtools.Stub { + return testtools.Stub{ + OperationName: "DescribeDBParameterGroups", + Input: &rds.DescribeDBParameterGroupsInput{ + DBParameterGroupName: aws.String(parameterGroupName), + }, + Output: &rds.DescribeDBParameterGroupsOutput{ + DBParameterGroups: []types.DBParameterGroup{ + { + DBParameterGroupName: aws.String(parameterGroupName), + DBParameterGroupFamily: aws.String(parameterGroupFamily), + DBParameterGroupArn: aws.String("0000000000000000000000000000000000:param-group:test"), + Description: aws.String("test"), + }, + }, + }, + Error: raiseErr, + } +} + +func StubCreateParameterGroup(parameterGroupName string, familyName string, description string, + raiseErr *testtools.StubError) testtools.Stub { + return testtools.Stub{ + OperationName: "CreateDBParameterGroup", + Input: &rds.CreateDBParameterGroupInput{ + DBParameterGroupName: aws.String(parameterGroupName), + DBParameterGroupFamily: aws.String(familyName), + Description: aws.String(description), + }, + Output: &rds.CreateDBParameterGroupOutput{ + DBParameterGroup: &types.DBParameterGroup{ + DBParameterGroupName: aws.String(parameterGroupName), + }, + }, + Error: raiseErr, + } +} + +func StubDeleteParameterGroup(parameterGroupName string, raiseErr *testtools.StubError) testtools.Stub { + return testtools.Stub{ + OperationName: "DeleteDBParameterGroup", + Input: &rds.DeleteDBParameterGroupInput{ + DBParameterGroupName: aws.String(parameterGroupName), + }, + Output: &rds.DeleteDBParameterGroupOutput{}, + Error: raiseErr, + } +} + +func StubGetParameters(parameterGroupName string, source string, outParams []types.Parameter, + raiseErr *testtools.StubError) testtools.Stub { + return testtools.Stub{ + OperationName: "DescribeDBParameters", + Input: &rds.DescribeDBParametersInput{ + DBParameterGroupName: aws.String(parameterGroupName), + Source: aws.String(source), + }, + Output: &rds.DescribeDBParametersOutput{ + Parameters: outParams, + }, + Error: raiseErr, + } +} + +func StubUpdateParameters(parameterGroupName string, updateParams []types.Parameter, raiseErr *testtools.StubError) testtools.Stub { + return testtools.Stub{ + OperationName: "ModifyDBParameterGroup", + Input: &rds.ModifyDBParameterGroupInput{ + DBParameterGroupName: aws.String(parameterGroupName), + Parameters: updateParams, + }, + Output: &rds.ModifyDBParameterGroupOutput{}, + Error: raiseErr, + } +} + +func StubCreateSnapshot(instanceIdentifier string, snapshotIdentifier string, raiseErr *testtools.StubError) testtools.Stub { + return testtools.Stub{ + OperationName: "CreateDBSnapshot", + Input: &rds.CreateDBSnapshotInput{ + DBInstanceIdentifier: aws.String(instanceIdentifier), + DBSnapshotIdentifier: aws.String(snapshotIdentifier), + }, + Output: &rds.CreateDBSnapshotOutput{ + DBSnapshot: &types.DBSnapshot{ + DBSnapshotIdentifier: aws.String(snapshotIdentifier), + Status: aws.String("creating"), + }, + }, + Error: raiseErr, + } +} + +func StubGetSnapshot(snapshotIdentifier string, status string, raiseErr *testtools.StubError) testtools.Stub { + return testtools.Stub{ + OperationName: "DescribeDBSnapshots", + Input: &rds.DescribeDBSnapshotsInput{ + DBSnapshotIdentifier: aws.String(snapshotIdentifier), + }, + Output: &rds.DescribeDBSnapshotsOutput{ + DBSnapshots: []types.DBSnapshot{ + { + DBSnapshotIdentifier: aws.String(snapshotIdentifier), + Status: aws.String(status), + DBSnapshotArn: aws.String("0000000000000000000000000000000000:snapshot:test"), + Engine: aws.String("test-engine"), + EngineVersion: aws.String("test-engine-version"), + DBInstanceIdentifier: aws.String("test"), + SnapshotCreateTime: aws.Time(time.Now()), + }, + }, + }, + Error: raiseErr, + } +} + +func StubCreateInstance(instanceName string, dbName string, + dbEngine string, dbEngineVersion string, parameterGroupName string, dbInstanceClass string, + storageType string, allocatedStorage int32, adminName string, adminPassword string, + raiseErr *testtools.StubError) testtools.Stub { + return testtools.Stub{ + OperationName: "CreateDBInstance", + Input: &rds.CreateDBInstanceInput{ + DBInstanceIdentifier: aws.String(instanceName), + DBName: aws.String(dbName), + DBParameterGroupName: aws.String(parameterGroupName), + Engine: aws.String(dbEngine), + EngineVersion: aws.String(dbEngineVersion), + DBInstanceClass: aws.String(dbInstanceClass), + StorageType: aws.String(storageType), + AllocatedStorage: aws.Int32(allocatedStorage), + MasterUsername: aws.String(adminName), + MasterUserPassword: aws.String(adminPassword), + }, + Output: &rds.CreateDBInstanceOutput{ + DBInstance: &types.DBInstance{ + DBInstanceIdentifier: aws.String(instanceName), + Engine: aws.String(dbEngine), + DBInstanceClass: aws.String(dbInstanceClass), + DBInstanceStatus: aws.String("starting"), + }, + }, + Error: raiseErr, + } +} + +func StubGetInstance(instanceIdentifier string, status string, raiseErr *testtools.StubError) testtools.Stub { + return testtools.Stub{ + OperationName: "DescribeDBInstances", + Input: &rds.DescribeDBInstancesInput{ + DBInstanceIdentifier: aws.String(instanceIdentifier), + }, + Output: &rds.DescribeDBInstancesOutput{ + DBInstances: []types.DBInstance{ + { + DBInstanceIdentifier: aws.String(instanceIdentifier), + DBInstanceStatus: aws.String(status), + DBInstanceArn: aws.String("0000000000000000000000000000000000:instance:test"), + Engine: aws.String("test-engine"), + EngineVersion: aws.String("test-engine-version"), + Endpoint: &types.Endpoint{ + Address: aws.String("test-address"), + Port: 13, + }, + MasterUsername: aws.String("test-user"), + }, + }, + }, + Error: raiseErr, + } +} + +func StubDeleteInstance(instanceIdentifier string, raiseErr *testtools.StubError) testtools.Stub { + return testtools.Stub{ + OperationName: "DeleteDBInstance", + Input: &rds.DeleteDBInstanceInput{ + DBInstanceIdentifier: aws.String(instanceIdentifier), + DeleteAutomatedBackups: aws.Bool(true), + SkipFinalSnapshot: true, + }, + Output: &rds.DeleteDBInstanceOutput{}, + Error: raiseErr, + } +} + +func StubGetEngineVersions(engine string, family string, families []string, raiseErr *testtools.StubError) testtools.Stub { + var outVersions []types.DBEngineVersion + for index, family := range families { + outVersions = append(outVersions, types.DBEngineVersion{ + Engine: aws.String(engine), + EngineVersion: aws.String(fmt.Sprintf("%v-%v", engine, index)), + DBParameterGroupFamily: aws.String(family), + }) + } + return testtools.Stub{ + OperationName: "DescribeDBEngineVersions", + Input: &rds.DescribeDBEngineVersionsInput{ + Engine: aws.String(engine), + DBParameterGroupFamily: aws.String(family), + }, + Output: &rds.DescribeDBEngineVersionsOutput{ + DBEngineVersions: outVersions, + }, + Error: raiseErr, + } +} + +func StubGetOrderableInstances(engine string, engineVersion string, instanceClasses []string, raiseErr *testtools.StubError) testtools.Stub { + var outInstances []types.OrderableDBInstanceOption + for _, instanceClass := range instanceClasses { + outInstances = append(outInstances, types.OrderableDBInstanceOption{ + Engine: aws.String(engine), + EngineVersion: aws.String(engineVersion), + DBInstanceClass: aws.String(instanceClass), + }) + } + return testtools.Stub{ + OperationName: "DescribeOrderableDBInstanceOptions", + Input: &rds.DescribeOrderableDBInstanceOptionsInput{ + Engine: aws.String(engine), + EngineVersion: aws.String(engineVersion), + }, + Output: &rds.DescribeOrderableDBInstanceOptionsOutput{ + OrderableDBInstanceOptions: outInstances, + }, + Error: raiseErr, + } +} diff --git a/gov2/run_all_tests.bat b/gov2/run_all_tests.bat index 9264eb92a47..ad4cdedc887 100644 --- a/gov2/run_all_tests.bat +++ b/gov2/run_all_tests.bat @@ -2,6 +2,6 @@ Rem Run this batch script with no arguments to run unit tests or with 'integrati for /d %%a in (*) do ( cd %%a - call go test -tags=%1 ./... + call go test -tags=%1 -timeout=60m ./... cd .. ) diff --git a/gov2/run_all_tests.sh b/gov2/run_all_tests.sh index bbcea7780f3..d7eaf78e550 100644 --- a/gov2/run_all_tests.sh +++ b/gov2/run_all_tests.sh @@ -9,7 +9,7 @@ function runCommand() { kind='unit' fi echo Running $kind tests... - for d in ./*/ ; do /bin/bash -c "(cd '$d' && go test -tags=$@ ./...)"; done + for d in ./*/ ; do /bin/bash -c "(cd '$d' && go test -tags=$@ -timeout=60m ./...)"; done } runCommand $1