github.com/webonyx/up@v0.7.4-0.20180808230834-91b94e551323/platform/aws/runtime/runtime.go (about) 1 package runtime 2 3 import ( 4 "os" 5 "time" 6 7 "github.com/apex/log" 8 "github.com/apex/up" 9 "github.com/apex/up/internal/secret" 10 "github.com/apex/up/internal/util" 11 "github.com/aws/aws-sdk-go/aws" 12 "github.com/aws/aws-sdk-go/aws/session" 13 "github.com/aws/aws-sdk-go/service/cloudwatch" 14 "github.com/pkg/errors" 15 ) 16 17 // Runtime implementation. 18 type Runtime struct { 19 config *up.Config 20 log log.Interface 21 } 22 23 // Option function. 24 type Option func(*Runtime) 25 26 // New with the given options. 27 func New(c *up.Config, options ...Option) *Runtime { 28 var v Runtime 29 v.config = c 30 v.log = log.Log 31 for _, o := range options { 32 o(&v) 33 } 34 return &v 35 } 36 37 // WithLogger option. 38 func WithLogger(l log.Interface) Option { 39 return func(v *Runtime) { 40 v.log = l 41 } 42 } 43 44 // Init implementation. 45 func (r *Runtime) Init(stage string) error { 46 os.Setenv("UP_STAGE", stage) 47 48 if os.Getenv("NODE_ENV") == "" { 49 os.Setenv("NODE_ENV", stage) 50 } 51 52 r.log.Info("loading secrets") 53 if err := r.loadSecrets(stage); err != nil { 54 return errors.Wrap(err, "loading secrets") 55 } 56 57 return nil 58 } 59 60 // Metric records a metric value. 61 func (r *Runtime) Metric(name string, value float64) error { 62 // TODO: move 63 c := cloudwatch.New(session.New(aws.NewConfig())) 64 65 // TODO: conventions for Name? ByApp ? 66 // TODO: timeouts or delegate 67 // TODO: stage dim? 68 _, err := c.PutMetricData(&cloudwatch.PutMetricDataInput{ 69 Namespace: aws.String("up"), 70 MetricData: []*cloudwatch.MetricDatum{ 71 { 72 MetricName: &name, 73 Value: &value, 74 Dimensions: []*cloudwatch.Dimension{ 75 { 76 Name: aws.String("app"), 77 Value: &r.config.Name, 78 }, 79 }, 80 }, 81 }, 82 }) 83 84 return err 85 } 86 87 // loadSecrets loads secrets. 88 func (r *Runtime) loadSecrets(stage string) error { 89 start := time.Now() 90 initialEnv := util.EnvironMap() 91 92 r.log.Info("initializing secrets") 93 defer func() { 94 r.log.WithField("duration", util.MillisecondsSince(start)).Info("initialized secrets") 95 }() 96 97 // TODO: all regions 98 secrets, err := NewSecrets(r.config.Name, stage, r.config.Regions[0]).Load() 99 if err != nil { 100 return err 101 } 102 103 secrets = secret.FilterByApp(secrets, r.config.Name) 104 stages := secret.GroupByStage(secrets) 105 106 precedence := []string{ 107 "all", 108 stage, 109 } 110 111 for _, name := range precedence { 112 if secrets := stages[name]; len(secrets) > 0 { 113 r.log.WithFields(log.Fields{ 114 "name": name, 115 "count": len(secrets), 116 }).Info("initializing variables") 117 118 for _, s := range secrets { 119 ctx := r.log.WithFields(log.Fields{ 120 "name": s.Name, 121 "value": secret.String(s), 122 }) 123 124 // in development we allow existing vars to override `up env` 125 if _, ok := initialEnv[s.Name]; ok && stage == "development" { 126 ctx.Debug("variable already defined") 127 continue 128 } 129 130 ctx.Info("set variable") 131 os.Setenv(s.Name, s.Value) 132 } 133 } 134 } 135 136 return nil 137 }