-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
129 lines (116 loc) · 3.03 KB
/
main.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
package main
import (
"fmt"
"log"
"reflect"
"strconv"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ssm"
)
func getSSMClient() *ssm.SSM {
sess := session.Must(session.NewSessionWithOptions(session.Options{
SharedConfigState: session.SharedConfigEnable,
}))
client := ssm.New(sess)
return client
}
var (
ssmPath = "/Env/Application/"
client = getSSMClient()
)
// Name a person's name
type Name struct {
FirstName string `ssm:"Name/FirstName"`
LastName string `ssm:"Name/LastName"`
}
// Contact a person's contact info
type Contact struct {
Email string `ssm:"Contact/Email"`
Number string `ssm:"Contact/Number"`
}
// Person a person
type Person struct {
Name Name
Contact Contact
FavoriteNumber int `ssm:"FavoriteNumber"`
FavoriteInconvenientNumber float64 `ssm:"FavoriteInconvenientNumber"`
}
func getSSMParameter(name *string) (*string, error) {
withDecryption := true
input := ssm.GetParameterInput{
Name: name,
WithDecryption: &withDecryption,
}
value, err := client.GetParameter(&input)
if err != nil {
return nil, err
}
return value.Parameter.Value, nil
}
func handleSSMUpdate(field *reflect.Value, fieldType *reflect.StructField, ssmPath *string, ssm *string) error {
parameterPath := fmt.Sprintf("%s%s", *ssmPath, *ssm)
switch field.Kind() {
case reflect.String:
updatedValue, err := getSSMParameter(¶meterPath)
if err != nil {
return err
}
field.SetString(*updatedValue)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
updatedValue, err := getSSMParameter(¶meterPath)
if err != nil {
return err
}
ssmInt, err := strconv.ParseInt(*updatedValue, 0, 64)
if err != nil {
return err
}
field.SetInt(ssmInt)
case reflect.Float32, reflect.Float64:
updatedValue, err := getSSMParameter(¶meterPath)
if err != nil {
return err
}
ssmFloat, err := strconv.ParseFloat(*updatedValue, 64)
if err != nil {
return err
}
field.SetFloat(ssmFloat)
case reflect.Bool:
updatedValue, err := getSSMParameter(¶meterPath)
if err != nil {
return err
}
ssmBool, err := strconv.ParseBool(*updatedValue)
if err != nil {
return err
}
field.SetBool(ssmBool)
default:
return fmt.Errorf("Field %s is of a type that cannot be set", fieldType.Name)
}
return nil
}
// UpdateBySSM updates struct by SSM tag
func UpdateBySSM(generic interface{}, ssmPath *string) error {
valueOfGeneric := reflect.ValueOf(generic).Elem()
typeOfGeneric := valueOfGeneric.Type()
for i := 0; i < valueOfGeneric.NumField(); i++ {
field := valueOfGeneric.Field(i)
fieldType := typeOfGeneric.Field(i)
if field.Kind() == reflect.Struct {
UpdateBySSM(field.Addr().Interface(), ssmPath)
} else if ssm, ok := fieldType.Tag.Lookup("ssm"); ok {
handleSSMUpdate(&field, &fieldType, ssmPath, &ssm)
}
}
return nil
}
func main() {
person := Person{}
err := UpdateBySSM(&person, &ssmPath)
if err != nil {
log.Fatal(err)
}
fmt.Println("Updated person", person)
}