forked from gruntwork-io/terratest
-
Notifications
You must be signed in to change notification settings - Fork 0
/
rds.go
326 lines (286 loc) · 13.8 KB
/
rds.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
package aws
import (
"database/sql"
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/rds"
_ "github.com/go-sql-driver/mysql"
"github.com/gruntwork-io/terratest/modules/testing"
"github.com/stretchr/testify/require"
)
// GetAddressOfRdsInstance gets the address of the given RDS Instance in the given region.
func GetAddressOfRdsInstance(t testing.TestingT, dbInstanceID string, awsRegion string) string {
address, err := GetAddressOfRdsInstanceE(t, dbInstanceID, awsRegion)
if err != nil {
t.Fatal(err)
}
return address
}
// GetAddressOfRdsInstanceE gets the address of the given RDS Instance in the given region.
func GetAddressOfRdsInstanceE(t testing.TestingT, dbInstanceID string, awsRegion string) (string, error) {
dbInstance, err := GetRdsInstanceDetailsE(t, dbInstanceID, awsRegion)
if err != nil {
return "", err
}
return aws.StringValue(dbInstance.Endpoint.Address), nil
}
// GetPortOfRdsInstance gets the address of the given RDS Instance in the given region.
func GetPortOfRdsInstance(t testing.TestingT, dbInstanceID string, awsRegion string) int64 {
port, err := GetPortOfRdsInstanceE(t, dbInstanceID, awsRegion)
if err != nil {
t.Fatal(err)
}
return port
}
// GetPortOfRdsInstanceE gets the address of the given RDS Instance in the given region.
func GetPortOfRdsInstanceE(t testing.TestingT, dbInstanceID string, awsRegion string) (int64, error) {
dbInstance, err := GetRdsInstanceDetailsE(t, dbInstanceID, awsRegion)
if err != nil {
return -1, err
}
return *dbInstance.Endpoint.Port, nil
}
// GetWhetherSchemaExistsInRdsMySqlInstance checks whether the specified schema/table name exists in the RDS instance
func GetWhetherSchemaExistsInRdsMySqlInstance(t testing.TestingT, dbUrl string, dbPort int64, dbUsername string, dbPassword string, expectedSchemaName string) bool {
output, err := GetWhetherSchemaExistsInRdsMySqlInstanceE(t, dbUrl, dbPort, dbUsername, dbPassword, expectedSchemaName)
if err != nil {
t.Fatal(err)
}
return output
}
// GetWhetherSchemaExistsInRdsMySqlInstanceE checks whether the specified schema/table name exists in the RDS instance
func GetWhetherSchemaExistsInRdsMySqlInstanceE(t testing.TestingT, dbUrl string, dbPort int64, dbUsername string, dbPassword string, expectedSchemaName string) (bool, error) {
connectionString := fmt.Sprintf("%s:%s@tcp(%s:%d)/", dbUsername, dbPassword, dbUrl, dbPort)
db, connErr := sql.Open("mysql", connectionString)
if connErr != nil {
return false, connErr
}
defer db.Close()
var (
schemaName string
)
sqlStatement := "SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME=?;"
row := db.QueryRow(sqlStatement, expectedSchemaName)
scanErr := row.Scan(&schemaName)
if scanErr != nil {
return false, scanErr
}
return true, nil
}
// GetParameterValueForParameterOfRdsInstance gets the value of the parameter name specified for the RDS instance in the given region.
func GetParameterValueForParameterOfRdsInstance(t testing.TestingT, parameterName string, dbInstanceID string, awsRegion string) string {
parameterValue, err := GetParameterValueForParameterOfRdsInstanceE(t, parameterName, dbInstanceID, awsRegion)
if err != nil {
t.Fatal(err)
}
return parameterValue
}
// GetParameterValueForParameterOfRdsInstanceE gets the value of the parameter name specified for the RDS instance in the given region.
func GetParameterValueForParameterOfRdsInstanceE(t testing.TestingT, parameterName string, dbInstanceID string, awsRegion string) (string, error) {
output := GetAllParametersOfRdsInstance(t, dbInstanceID, awsRegion)
for _, parameter := range output {
if aws.StringValue(parameter.ParameterName) == parameterName {
return aws.StringValue(parameter.ParameterValue), nil
}
}
return "", ParameterForDbInstanceNotFound{ParameterName: parameterName, DbInstanceID: dbInstanceID, AwsRegion: awsRegion}
}
// GetOptionSettingForOfRdsInstance gets the value of the option name in the option group specified for the RDS instance in the given region.
func GetOptionSettingForOfRdsInstance(t testing.TestingT, optionName string, optionSettingName string, dbInstanceID, awsRegion string) string {
optionValue, err := GetOptionSettingForOfRdsInstanceE(t, optionName, optionSettingName, dbInstanceID, awsRegion)
if err != nil {
t.Fatal(err)
}
return optionValue
}
// GetOptionSettingForOfRdsInstanceE gets the value of the option name in the option group specified for the RDS instance in the given region.
func GetOptionSettingForOfRdsInstanceE(t testing.TestingT, optionName string, optionSettingName string, dbInstanceID, awsRegion string) (string, error) {
optionGroupName := GetOptionGroupNameOfRdsInstance(t, dbInstanceID, awsRegion)
options := GetOptionsOfOptionGroup(t, optionGroupName, awsRegion)
for _, option := range options {
if aws.StringValue(option.OptionName) == optionName {
for _, optionSetting := range option.OptionSettings {
if aws.StringValue(optionSetting.Name) == optionSettingName {
return aws.StringValue(optionSetting.Value), nil
}
}
}
}
return "", OptionGroupOptionSettingForDbInstanceNotFound{OptionName: optionName, OptionSettingName: optionSettingName, DbInstanceID: dbInstanceID, AwsRegion: awsRegion}
}
// GetOptionGroupNameOfRdsInstance gets the name of the option group associated with the RDS instance
func GetOptionGroupNameOfRdsInstance(t testing.TestingT, dbInstanceID string, awsRegion string) string {
dbInstance, err := GetOptionGroupNameOfRdsInstanceE(t, dbInstanceID, awsRegion)
if err != nil {
t.Fatal(err)
}
return dbInstance
}
// GetOptionGroupNameOfRdsInstanceE gets the name of the option group associated with the RDS instance
func GetOptionGroupNameOfRdsInstanceE(t testing.TestingT, dbInstanceID string, awsRegion string) (string, error) {
dbInstance, err := GetRdsInstanceDetailsE(t, dbInstanceID, awsRegion)
if err != nil {
return "", err
}
return aws.StringValue(dbInstance.OptionGroupMemberships[0].OptionGroupName), nil
}
// GetOptionsOfOptionGroup gets the options of the option group specified
func GetOptionsOfOptionGroup(t testing.TestingT, optionGroupName string, awsRegion string) []*rds.Option {
output, err := GetOptionsOfOptionGroupE(t, optionGroupName, awsRegion)
if err != nil {
t.Fatal(err)
}
return output
}
// GetOptionsOfOptionGroupE gets the options of the option group specified
func GetOptionsOfOptionGroupE(t testing.TestingT, optionGroupName string, awsRegion string) ([]*rds.Option, error) {
rdsClient := NewRdsClient(t, awsRegion)
input := rds.DescribeOptionGroupsInput{OptionGroupName: aws.String(optionGroupName)}
output, err := rdsClient.DescribeOptionGroups(&input)
if err != nil {
return []*rds.Option{}, err
}
return output.OptionGroupsList[0].Options, nil
}
// GetAllParametersOfRdsInstance gets all the parameters defined in the parameter group for the RDS instance in the given region.
func GetAllParametersOfRdsInstance(t testing.TestingT, dbInstanceID string, awsRegion string) []*rds.Parameter {
parameters, err := GetAllParametersOfRdsInstanceE(t, dbInstanceID, awsRegion)
if err != nil {
t.Fatal(err)
}
return parameters
}
// GetAllParametersOfRdsInstanceE gets all the parameters defined in the parameter group for the RDS instance in the given region.
func GetAllParametersOfRdsInstanceE(t testing.TestingT, dbInstanceID string, awsRegion string) ([]*rds.Parameter, error) {
dbInstance, dbInstanceErr := GetRdsInstanceDetailsE(t, dbInstanceID, awsRegion)
if dbInstanceErr != nil {
return []*rds.Parameter{}, dbInstanceErr
}
parameterGroupName := aws.StringValue(dbInstance.DBParameterGroups[0].DBParameterGroupName)
rdsClient := NewRdsClient(t, awsRegion)
input := rds.DescribeDBParametersInput{DBParameterGroupName: aws.String(parameterGroupName)}
output, err := rdsClient.DescribeDBParameters(&input)
if err != nil {
return []*rds.Parameter{}, err
}
return output.Parameters, nil
}
// GetRdsInstanceDetailsE gets the details of a single DB instance whose identifier is passed.
func GetRdsInstanceDetailsE(t testing.TestingT, dbInstanceID string, awsRegion string) (*rds.DBInstance, error) {
rdsClient := NewRdsClient(t, awsRegion)
input := rds.DescribeDBInstancesInput{DBInstanceIdentifier: aws.String(dbInstanceID)}
output, err := rdsClient.DescribeDBInstances(&input)
if err != nil {
return nil, err
}
return output.DBInstances[0], nil
}
// NewRdsClient creates an RDS client.
func NewRdsClient(t testing.TestingT, region string) *rds.RDS {
client, err := NewRdsClientE(t, region)
if err != nil {
t.Fatal(err)
}
return client
}
// NewRdsClientE creates an RDS client.
func NewRdsClientE(t testing.TestingT, region string) (*rds.RDS, error) {
sess, err := NewAuthenticatedSession(region)
if err != nil {
return nil, err
}
return rds.New(sess), nil
}
// GetRecommendedRdsInstanceType takes in a list of RDS instance types (e.g., "db.t2.micro", "db.t3.micro") and returns the
// first instance type in the list that is available in the given region and for the given database engine type.
// If none of the instances provided are avaiable for your combination of region and database engine, this function will exit with an error.
func GetRecommendedRdsInstanceType(t testing.TestingT, region string, engine string, engineVersion string, instanceTypeOptions []string) string {
out, err := GetRecommendedRdsInstanceTypeE(t, region, engine, engineVersion, instanceTypeOptions)
require.NoError(t, err)
return out
}
// GetRecommendedRdsInstanceTypeE takes in a list of RDS instance types (e.g., "db.t2.micro", "db.t3.micro") and returns the
// first instance type in the list that is available in the given region and for the given database engine type.
// If none of the instances provided are avaiable for your combination of region and database engine, this function will return an error.
func GetRecommendedRdsInstanceTypeE(t testing.TestingT, region string, engine string, engineVersion string, instanceTypeOptions []string) (string, error) {
client, err := NewRdsClientE(t, region)
if err != nil {
return "", err
}
return GetRecommendedRdsInstanceTypeWithClientE(t, client, engine, engineVersion, instanceTypeOptions)
}
// GetRecommendedRdsInstanceTypeWithClientE takes in a list of RDS instance types (e.g., "db.t2.micro", "db.t3.micro") and returns the
// first instance type in the list that is available in the given region and for the given database engine type.
// If none of the instances provided are avaiable for your combination of region and database engine, this function will return an error.
// This function expects an authenticated RDS client from the AWS SDK Go library.
func GetRecommendedRdsInstanceTypeWithClientE(t testing.TestingT, rdsClient *rds.RDS, engine string, engineVersion string, instanceTypeOptions []string) (string, error) {
for _, instanceTypeOption := range instanceTypeOptions {
instanceTypeExists, err := instanceTypeExistsForEngineAndRegionE(rdsClient, engine, engineVersion, instanceTypeOption)
if err != nil {
return "", err
}
if instanceTypeExists {
return instanceTypeOption, nil
}
}
return "", NoRdsInstanceTypeError{InstanceTypeOptions: instanceTypeOptions, DatabaseEngine: engine, DatabaseEngineVersion: engineVersion}
}
// instanceTypeExistsForEngineAndRegionE returns a boolean that represents whether the provided instance type (e.g. db.t2.micro) exists for the given region and db engine type
// This function will return an error if the RDS AWS SDK call fails.
func instanceTypeExistsForEngineAndRegionE(client *rds.RDS, engine string, engineVersion string, instanceType string) (bool, error) {
input := rds.DescribeOrderableDBInstanceOptionsInput{
Engine: aws.String(engine),
EngineVersion: aws.String(engineVersion),
DBInstanceClass: aws.String(instanceType),
}
out, err := client.DescribeOrderableDBInstanceOptions(&input)
if err != nil {
return false, err
}
if len(out.OrderableDBInstanceOptions) > 0 {
return true, nil
}
return false, nil
}
// GetValidEngineVersion returns a string containing a valid RDS engine version for the provided region and engine type.
// This function will fail the test if no valid engine is found.
func GetValidEngineVersion(t testing.TestingT, region string, engine string, majorVersion string) string {
out, err := GetValidEngineVersionE(t, region, engine, majorVersion)
require.NoError(t, err)
return out
}
// GetValidEngineVersionE returns a string containing a valid RDS engine version or an error if no valid version is found.
func GetValidEngineVersionE(t testing.TestingT, region string, engine string, majorVersion string) (string, error) {
client, err := NewRdsClientE(t, region)
if err != nil {
return "", err
}
input := rds.DescribeDBEngineVersionsInput{
Engine: aws.String(engine),
EngineVersion: aws.String(majorVersion),
}
out, err := client.DescribeDBEngineVersions(&input)
if err != nil || len(out.DBEngineVersions) == 0 {
return "", err
}
return *out.DBEngineVersions[0].EngineVersion, nil
}
// ParameterForDbInstanceNotFound is an error that occurs when the parameter group specified is not found for the DB instance
type ParameterForDbInstanceNotFound struct {
ParameterName string
DbInstanceID string
AwsRegion string
}
func (err ParameterForDbInstanceNotFound) Error() string {
return fmt.Sprintf("Could not find a parameter %s in parameter group of database %s in %s", err.ParameterName, err.DbInstanceID, err.AwsRegion)
}
// OptionGroupOptionSettingForDbInstanceNotFound is an error that occurs when the option setting specified is not found in the option group of the DB instance
type OptionGroupOptionSettingForDbInstanceNotFound struct {
OptionName string
OptionSettingName string
DbInstanceID string
AwsRegion string
}
func (err OptionGroupOptionSettingForDbInstanceNotFound) Error() string {
return fmt.Sprintf("Could not find a option setting %s in option name %s of database %s in %s", err.OptionName, err.OptionSettingName, err.DbInstanceID, err.AwsRegion)
}