Browse Source

using aws-sdk-go-v2

master
Darshil Chanpura 4 months ago
parent
commit
cea8d6c364
  1. 42
      awsutils/cloudwatch.go
  2. 3
      awsutils/cloudwatch_test.go
  3. 35
      awsutils/email.go
  4. 3
      awsutils/email_test.go
  5. 52
      awsutils/init.go
  6. 4
      awsutils/utils.go
  7. 6
      go.mod
  8. 45
      go.sum
  9. 15
      tracker/ticker.go

42
awsutils/cloudwatch.go

@ -1,30 +1,32 @@
package awsutils
import (
"context"
"fmt"
"log"
"strconv"
"strings"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/cloudwatch"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/cloudwatch"
"github.com/aws/aws-sdk-go-v2/service/cloudwatch/types"
)
// GetMetrics for getting metrics based on time range and Metric with period
func (a *AWS) GetMetrics(start, end time.Time, metrics []Metric, period time.Duration) ([]MetricResult, error) {
queries := []*cloudwatch.MetricDataQuery{}
func (a *AWS) GetMetrics(ctx context.Context, start, end time.Time, metrics []Metric, period time.Duration) ([]MetricResult, error) {
queries := []types.MetricDataQuery{}
for i, metric := range metrics {
for j, stat := range metric.Stats {
queries = append(queries, &cloudwatch.MetricDataQuery{
queries = append(queries, types.MetricDataQuery{
Id: aws.String(fmt.Sprintf("m%d_%d", i, j)),
MetricStat: &cloudwatch.MetricStat{
Period: aws.Int64(int64(period.Seconds())),
MetricStat: &types.MetricStat{
Period: aws.Int32(int32(period.Seconds())),
Stat: aws.String(stat),
Metric: &cloudwatch.Metric{
Metric: &types.Metric{
Namespace: aws.String("AWS/EC2"),
MetricName: aws.String("CPUUtilization"),
Dimensions: []*cloudwatch.Dimension{
Dimensions: []types.Dimension{
{
Name: aws.String("InstanceId"),
Value: aws.String(metric.InstanceID),
@ -35,7 +37,7 @@ func (a *AWS) GetMetrics(start, end time.Time, metrics []Metric, period time.Dur
})
}
}
output, err := a.cwsvc.GetMetricData(&cloudwatch.GetMetricDataInput{
output, err := a.cwsvc.GetMetricData(ctx, &cloudwatch.GetMetricDataInput{
StartTime: &start,
EndTime: &end,
MetricDataQueries: queries,
@ -57,12 +59,12 @@ func (a *AWS) GetMetrics(start, end time.Time, metrics []Metric, period time.Dur
}
m = results[i]
if m.Timestamps == nil {
m.Timestamps = getTimeSlice(result.Timestamps)
m.Timestamps = result.Timestamps
}
if m.Results == nil {
m.Results = make([][]float64, len(metrics[i].Stats))
}
m.Results[j] = getFloatSlice(result.Values)
m.Results[j] = result.Values
results[i] = m
}
return results, nil
@ -86,19 +88,3 @@ func getIndex(id string) (int, int) {
}
return int(i), int(j)
}
func getFloatSlice(values []*float64) []float64 {
vals := make([]float64, len(values))
for i := range values {
vals[i] = *values[i]
}
return vals
}
func getTimeSlice(values []*time.Time) []time.Time {
vals := make([]time.Time, len(values))
for i := range values {
vals[i] = *values[i]
}
return vals
}

3
awsutils/cloudwatch_test.go

@ -1,6 +1,7 @@
package awsutils
import (
"context"
"testing"
"time"
)
@ -12,7 +13,7 @@ func TestGetMetrics(t *testing.T) {
if err != nil {
t.Errorf("error parsing time %v", err)
}
d, err := a.GetMetrics(tm, time.Now(),
d, err := a.GetMetrics(context.Background(), tm, time.Now(),
[]Metric{
{
InstanceID: "i-123",

35
awsutils/email.go

@ -1,44 +1,37 @@
package awsutils
import (
"context"
"errors"
"log"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ses"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/ses"
"github.com/aws/aws-sdk-go-v2/service/ses/types"
)
// SendEmail for sending email while with required details
func (a *AWS) SendEmail(subject, from string, to []string, cc []string, html string, text string) error {
// initSvc()
func (a *AWS) SendEmail(ctx context.Context, subject, from string, to []string, cc []string, html string, text string) error {
if html == "" {
return errors.New("invalid html and text content")
}
toaddrs := []*string{}
ccaddrs := []*string{}
for _, addr := range to {
toaddrs = append(toaddrs, aws.String(addr))
}
for _, addr := range cc {
ccaddrs = append(ccaddrs, aws.String(addr))
}
sesoutput, err := a.sessvc.SendEmail(&ses.SendEmailInput{
sesoutput, err := a.sessvc.SendEmail(ctx, &ses.SendEmailInput{
Source: aws.String(from),
Destination: &ses.Destination{
ToAddresses: toaddrs,
CcAddresses: ccaddrs,
Destination: &types.Destination{
ToAddresses: to,
CcAddresses: cc,
},
Message: &ses.Message{
Subject: &ses.Content{
Message: &types.Message{
Subject: &types.Content{
Charset: aws.String("UTF-8"),
Data: aws.String(subject),
},
Body: &ses.Body{
Html: &ses.Content{
Body: &types.Body{
Html: &types.Content{
Charset: aws.String("UTF-8"),
Data: aws.String(html),
},
Text: &ses.Content{
Text: &types.Content{
Charset: aws.String("UTF-8"),
Data: aws.String(text),
},

3
awsutils/email_test.go

@ -1,6 +1,7 @@
package awsutils
import (
"context"
"testing"
)
@ -9,7 +10,7 @@ func TestSendEmail(t *testing.T) {
profile := "personal"
region := "ap-south-1"
a := New(region, profile, false)
err := a.SendEmail("Test Email", "dtchanpura@gmail.com", []string{"dtchanpura@gmail.com"}, []string{}, `<!doctype html><html><body><p>hello <b>world</b></p></body></html>`, "hello world")
err := a.SendEmail(context.Background(), "Test Email", "dtchanpura@gmail.com", []string{"dtchanpura@gmail.com"}, []string{}, `<!doctype html><html><body><p>hello <b>world</b></p></body></html>`, "hello world")
if err != nil {
t.Errorf("error sending email %v", err)
}

52
awsutils/init.go

@ -1,53 +1,45 @@
package awsutils
import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/cloudwatch"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/ses"
"context"
"log"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/cloudwatch"
"github.com/aws/aws-sdk-go-v2/service/ec2"
"github.com/aws/aws-sdk-go-v2/service/ses"
)
type AWS struct {
ec2svc *ec2.EC2
sessvc *ses.SES
cwsvc *cloudwatch.CloudWatch
ec2svc *ec2.Client
sessvc *ses.Client
cwsvc *cloudwatch.Client
}
func New(region, profile string, force bool) AWS {
a := AWS{}
cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion(region), config.WithSharedConfigProfile(profile))
if err != nil {
log.Fatal(err)
}
if a.ec2svc == nil || force {
sess := session.Must(session.NewSessionWithOptions(session.Options{
Profile: profile,
}))
a.ec2svc = ec2.New(sess, &aws.Config{
Region: aws.String(region),
})
a.ec2svc = ec2.NewFromConfig(cfg)
}
if a.sessvc == nil || force {
sess := session.Must(session.NewSessionWithOptions(session.Options{
Profile: profile,
}))
a.sessvc = ses.New(sess, &aws.Config{
Region: aws.String(region),
})
a.sessvc = ses.NewFromConfig(cfg)
}
if a.cwsvc == nil || force {
sess := session.Must(session.NewSessionWithOptions(session.Options{
Profile: profile,
}))
a.cwsvc = cloudwatch.New(sess, &aws.Config{
Region: aws.String(region),
})
a.cwsvc = cloudwatch.NewFromConfig(cfg)
}
return a
}
// GetInstances for getting all instances in this format
func (a *AWS) GetInstances() ([]*Instance, error) {
// initSvc()
var instances []*Instance
output, err := a.ec2svc.DescribeInstances(&ec2.DescribeInstancesInput{})
output, err := a.ec2svc.DescribeInstances(context.Background(), &ec2.DescribeInstancesInput{})
if err != nil {
return nil, err
}
@ -56,8 +48,8 @@ func (a *AWS) GetInstances() ([]*Instance, error) {
inst := &Instance{
ID: *i.InstanceId,
LaunchTime: *i.LaunchTime,
State: *i.State.Name,
Type: *i.InstanceType,
State: string(i.State.Name),
Type: string(i.InstanceType),
Tags: getMapFromTags(i.Tags),
}
instances = append(instances, inst)

4
awsutils/utils.go

@ -1,10 +1,10 @@
package awsutils
import (
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go-v2/service/ec2/types"
)
func getMapFromTags(tags []*ec2.Tag) map[string]string {
func getMapFromTags(tags []types.Tag) map[string]string {
tagmap := map[string]string{}
for _, t := range tags {
tagmap[*t.Key] = *t.Value

6
go.mod

@ -3,7 +3,11 @@ module git.dcpri.me/dtchanpura/track-instances
go 1.16
require (
github.com/aws/aws-sdk-go v1.38.60
github.com/aws/aws-sdk-go-v2 v1.6.0
github.com/aws/aws-sdk-go-v2/config v1.3.0
github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.4.1
github.com/aws/aws-sdk-go-v2/service/ec2 v1.9.0
github.com/aws/aws-sdk-go-v2/service/ses v1.3.1
github.com/magefile/mage v1.11.0
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
)

45
go.sum

@ -1,31 +1,42 @@
github.com/aws/aws-sdk-go v1.38.51 h1:aKQmbVbwOCuQSd8+fm/MR3bq0QOsu9Q7S+/QEND36oQ=
github.com/aws/aws-sdk-go v1.38.51/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go v1.38.52 h1:7NKcUyTG/CyDX835kq04DDNe8vXaJhbGW8ThemHb18A=
github.com/aws/aws-sdk-go v1.38.52/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go v1.38.60 h1:MgyEsX0IMwivwth1VwEnesBpH0vxbjp5a0w1lurMOXY=
github.com/aws/aws-sdk-go v1.38.60/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go-v2 v1.6.0 h1:r20hdhm8wZmKkClREfacXrKfX0Y7/s0aOoeraFbf/sY=
github.com/aws/aws-sdk-go-v2 v1.6.0/go.mod h1:tI4KhsR5VkzlUa2DZAdwx7wCAYGwkZZ1H31PYrBFx1w=
github.com/aws/aws-sdk-go-v2/config v1.3.0 h1:0JAnp0WcsgKilFLiZEScUTKIvTKa2LkicadZADza+u0=
github.com/aws/aws-sdk-go-v2/config v1.3.0/go.mod h1:lOxzHWDt/k7MMidA/K8DgXL4+ynnZYsDq65Qhs/l3dg=
github.com/aws/aws-sdk-go-v2/credentials v1.2.1 h1:AqQ8PzWll1wegNUOfIKcbp/JspTbJl54gNonrO6VUsY=
github.com/aws/aws-sdk-go-v2/credentials v1.2.1/go.mod h1:Rfvim1eZTC9W5s8YJyYYtl1KMk6e8fHv+wMRQGO4Ru0=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.1.1 h1:w1ocBIhQkLgupEB3d0uOuBddqVYl0xpubz7HSTzWG8A=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.1.1/go.mod h1:GTXAhrxHQOj9N+J5tYVjwt+rpRyy/42qLjlgw9pz1a0=
github.com/aws/aws-sdk-go-v2/internal/ini v1.0.0 h1:k7I9E6tyVWBo7H9ffpnxDWudtjau6Qt9rnOYgV+ciEQ=
github.com/aws/aws-sdk-go-v2/internal/ini v1.0.0/go.mod h1:g3XMXuxvqSMUjnsXXp/960152w0wFS4CXVYgQaSVOHE=
github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.4.1 h1:Mt2+LnGKQQyncULtRrx+oJkIwnrfy5XKb96Rvsml30U=
github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.4.1/go.mod h1:dWC4cWmhO3NI8sDqWSPU587mlTLhxCFdS/o3ym/QgMU=
github.com/aws/aws-sdk-go-v2/service/ec2 v1.9.0 h1:SF0h/HR4zUDBbGv6Hf/fbbG6ywTVi9r2DmpIhfZMckI=
github.com/aws/aws-sdk-go-v2/service/ec2 v1.9.0/go.mod h1:XzzkrryeCoPUd9jxcdDnI2/UmlfIp13nBSpjl2SDSCM=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.1.1 h1:l7pDLsmOGrnR8LT+3gIv8NlHpUhs7220E457KEC2UM0=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.1.1/go.mod h1:2+ehJPkdIdl46VCj67Emz/EH2hpebHZtaLdzqg+sWOI=
github.com/aws/aws-sdk-go-v2/service/ses v1.3.1 h1:eVBxtmEeVVCzWpbx1PtRijqEL2is3SPaaCpKq/Np92U=
github.com/aws/aws-sdk-go-v2/service/ses v1.3.1/go.mod h1:6WbvZTnH6a1YzeMZDi/hSjTbPB3RekFw5aQKSwKTksk=
github.com/aws/aws-sdk-go-v2/service/sso v1.2.1 h1:alpXc5UG7al7QnttHe/9hfvUfitV8r3w0onPpPkGzi0=
github.com/aws/aws-sdk-go-v2/service/sso v1.2.1/go.mod h1:VimPFPltQ/920i1X0Sb0VJBROLIHkDg2MNP10D46OGs=
github.com/aws/aws-sdk-go-v2/service/sts v1.4.1 h1:9Z00tExoaLutWVDmY6LyvIAcKjHetkbdmpRt4JN/FN0=
github.com/aws/aws-sdk-go-v2/service/sts v1.4.1/go.mod h1:G9osDWA52WQ38BDcj65VY1cNmcAQXAXTsE8IWH8j81w=
github.com/aws/smithy-go v1.4.0 h1:3rsQpgRe+OoQgJhEwGNpIkosl0fJLdmQqF4gSFRjg+4=
github.com/aws/smithy-go v1.4.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
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.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
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/magefile/mage v1.11.0 h1:C/55Ywp9BpgVVclD3lRnSYCwXTYxmSppIgLeDYlNuls=
github.com/magefile/mage v1.11.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=

15
tracker/ticker.go

@ -1,6 +1,7 @@
package tracker
import (
"context"
"log"
"os"
"time"
@ -21,7 +22,7 @@ func (t *Tracker) StartTicker() error {
return err
}
t.check()
t.check(context.Background())
t.ticker = time.NewTicker(config.CheckInterval)
@ -30,12 +31,12 @@ func (t *Tracker) StartTicker() error {
case <-done:
return nil
case <-t.ticker.C:
t.check()
t.check(context.Background())
}
}
}
func (t *Tracker) check() {
func (t *Tracker) check(ctx context.Context) {
instances, err := t.aws.GetInstances()
if err != nil {
log.Println(err)
@ -56,13 +57,13 @@ func (t *Tracker) check() {
}
// Updating the slice to have averages available in them
t.updateAverages(staleinstances)
t.updateAverages(ctx, staleinstances)
t.server.dataHTML = generateHTML(staleinstances)
t.server.dataTXT = generateText(staleinstances)
if len(staleinstances) > 0 {
if err := t.aws.SendEmail(
if err := t.aws.SendEmail(ctx,
config.Email.Subject,
config.Email.From,
config.Email.To,
@ -89,9 +90,9 @@ func checkOvertime(instance *awsutils.Instance) int {
return -1
}
func (t *Tracker) updateAverages(instances []*awsutils.Instance) {
func (t *Tracker) updateAverages(ctx context.Context, instances []*awsutils.Instance) {
for _, instance := range instances {
results, err := t.aws.GetMetrics(instance.LaunchTime, time.Now().Truncate(time.Hour),
results, err := t.aws.GetMetrics(ctx, instance.LaunchTime, time.Now().Truncate(time.Hour),
[]awsutils.Metric{
{
InstanceID: instance.ID,

Loading…
Cancel
Save