Browse Source

Modified the code to avoid using global variables

master
Darshil Chanpura 4 months ago
parent
commit
4c764f05eb
  1. 5
      awsutils/cloudwatch.go
  2. 4
      awsutils/cloudwatch_test.go
  3. 6
      awsutils/email.go
  4. 7
      awsutils/email_test.go
  5. 39
      awsutils/init.go
  6. 22
      cmd/track-instances/main.go
  7. 28
      tracker/init.go
  8. 40
      tracker/server.go
  9. 42
      tracker/ticker.go

5
awsutils/cloudwatch.go

@ -12,8 +12,7 @@ import (
)
// GetMetrics for getting metrics based on time range and Metric with period
func GetMetrics(start, end time.Time, metrics []Metric, period time.Duration) ([]MetricResult, error) {
initSvc()
func (a *AWS) GetMetrics(start, end time.Time, metrics []Metric, period time.Duration) ([]MetricResult, error) {
queries := []*cloudwatch.MetricDataQuery{}
for i, metric := range metrics {
for j, stat := range metric.Stats {
@ -36,7 +35,7 @@ func GetMetrics(start, end time.Time, metrics []Metric, period time.Duration) ([
})
}
}
output, err := cwsvc.GetMetricData(&cloudwatch.GetMetricDataInput{
output, err := a.cwsvc.GetMetricData(&cloudwatch.GetMetricDataInput{
StartTime: &start,
EndTime: &end,
MetricDataQueries: queries,

4
awsutils/cloudwatch_test.go

@ -7,12 +7,12 @@ import (
func TestGetMetrics(t *testing.T) {
t.SkipNow()
profile = "personal"
a := New("us-east-1", "personal", false)
tm, err := time.Parse("2006-01-02", "2020-06-19")
if err != nil {
t.Errorf("error parsing time %v", err)
}
d, err := GetMetrics(tm, time.Now(),
d, err := a.GetMetrics(tm, time.Now(),
[]Metric{
{
InstanceID: "i-123",

6
awsutils/email.go

@ -9,8 +9,8 @@ import (
)
// SendEmail for sending email while with required details
func SendEmail(subject, from string, to []string, cc []string, html string, text string) error {
initSvc()
func (a *AWS) SendEmail(subject, from string, to []string, cc []string, html string, text string) error {
// initSvc()
if html == "" {
return errors.New("invalid html and text content")
}
@ -22,7 +22,7 @@ func SendEmail(subject, from string, to []string, cc []string, html string, text
for _, addr := range cc {
ccaddrs = append(ccaddrs, aws.String(addr))
}
sesoutput, err := sessvc.SendEmail(&ses.SendEmailInput{
sesoutput, err := a.sessvc.SendEmail(&ses.SendEmailInput{
Source: aws.String(from),
Destination: &ses.Destination{
ToAddresses: toaddrs,

7
awsutils/email_test.go

@ -6,9 +6,10 @@ import (
func TestSendEmail(t *testing.T) {
t.SkipNow()
profile = "personal"
region = "ap-south-1"
err := 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")
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")
if err != nil {
t.Errorf("error sending email %v", err)
}

39
awsutils/init.go

@ -1,8 +1,6 @@
package awsutils
import (
"flag"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/cloudwatch"
@ -10,51 +8,46 @@ import (
"github.com/aws/aws-sdk-go/service/ses"
)
var (
region string
profile string
ec2svc *ec2.EC2
sessvc *ses.SES
cwsvc *cloudwatch.CloudWatch
)
func init() {
flag.StringVar(&region, "region", "us-east-1", "Region to use")
flag.StringVar(&profile, "profile", "default", "Profile to use")
type AWS struct {
ec2svc *ec2.EC2
sessvc *ses.SES
cwsvc *cloudwatch.CloudWatch
}
func initSvc() {
if ec2svc == nil {
func New(region, profile string, force bool) AWS {
a := AWS{}
if a.ec2svc == nil || force {
sess := session.Must(session.NewSessionWithOptions(session.Options{
Profile: profile,
}))
ec2svc = ec2.New(sess, &aws.Config{
a.ec2svc = ec2.New(sess, &aws.Config{
Region: aws.String(region),
})
}
if sessvc == nil {
if a.sessvc == nil || force {
sess := session.Must(session.NewSessionWithOptions(session.Options{
Profile: profile,
}))
sessvc = ses.New(sess, &aws.Config{
a.sessvc = ses.New(sess, &aws.Config{
Region: aws.String(region),
})
}
if cwsvc == nil {
if a.cwsvc == nil || force {
sess := session.Must(session.NewSessionWithOptions(session.Options{
Profile: profile,
}))
cwsvc = cloudwatch.New(sess, &aws.Config{
a.cwsvc = cloudwatch.New(sess, &aws.Config{
Region: aws.String(region),
})
}
return a
}
// GetInstances for getting all instances in this format
func GetInstances() ([]*Instance, error) {
initSvc()
func (a *AWS) GetInstances() ([]*Instance, error) {
// initSvc()
var instances []*Instance
output, err := ec2svc.DescribeInstances(&ec2.DescribeInstancesInput{})
output, err := a.ec2svc.DescribeInstances(&ec2.DescribeInstancesInput{})
if err != nil {
return nil, err
}

22
cmd/track-instances/main.go

@ -3,18 +3,36 @@ package main
import (
"flag"
"log"
"os"
"path/filepath"
"git.dcpri.me/dtchanpura/track-instances/tracker"
)
var ()
var (
addr = flag.String("addr", "", "Address to show page on")
region = flag.String("region", "us-east-1", "Region to use")
profile = flag.String("profile", "default", "Profile to use")
configfile *string
)
func init() {
dir, err := os.UserConfigDir()
if err != nil {
log.Fatal(err)
}
// flag.Var(&checkInterval, "interval", "Interval to check the instances")
configfile = flag.String("config", filepath.Join(dir, "track-instances.yaml"), "Config File Path")
}
func main() {
flag.Parse()
err := tracker.StartTicker()
t := tracker.New(*configfile, *region, *profile)
if *addr != "" {
go t.StartServer(*addr)
}
err := t.StartTicker()
if err != nil {
log.Fatal(err)
}

28
tracker/init.go

@ -1,25 +1,29 @@
package tracker
import (
"flag"
"log"
"os"
"path/filepath"
"time"
"git.dcpri.me/dtchanpura/track-instances/awsutils"
// Static Files packaged in
)
var (
config Config
// checkInterval Duration
configfile string
done = make(chan bool)
done = make(chan bool)
)
func init() {
dir, err := os.UserConfigDir()
if err != nil {
log.Fatal(err)
type Tracker struct {
configFile string
server Server
ticker *time.Ticker
aws awsutils.AWS
}
func New(configFile, region, profile string) Tracker {
return Tracker{
configFile: configFile,
server: NewServer(),
aws: awsutils.New(region, profile, false),
}
// flag.Var(&checkInterval, "interval", "Interval to check the instances")
flag.StringVar(&configfile, "config", filepath.Join(dir, "track-instances.yaml"), "Config File Path")
}

40
tracker/server.go

@ -0,0 +1,40 @@
package tracker
import (
"fmt"
"log"
"net/http"
)
type Server struct {
mux *http.ServeMux
dataHTML string
dataTXT string
}
func NewServer() Server {
return Server{
mux: http.NewServeMux(),
}
}
func (s *Server) routes() {
s.mux.HandleFunc("/", s.handleIndex)
}
func (s *Server) handleIndex(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("Accept") == "" {
w.Header().Set("Content-Type", "text/plain")
fmt.Fprint(w, s.dataTXT)
return
}
w.Header().Set("Context-Type", "text/html")
fmt.Fprint(w, s.dataHTML)
}
func (t *Tracker) StartServer(addr string) {
t.server.routes()
if err := http.ListenAndServe(addr, t.server.mux); err != nil {
log.Println("error running server:", err)
}
}

42
tracker/ticker.go

@ -9,35 +9,34 @@ import (
"gopkg.in/yaml.v3"
)
var (
ticker *time.Ticker
)
// StartTicker to start the ticker and send mail with details.
func StartTicker() error {
f, err := os.Open(configfile)
func (t *Tracker) StartTicker() error {
f, err := os.Open(t.configFile)
if err != nil {
return err
}
decoder := yaml.NewDecoder(f)
err = decoder.Decode(&config)
err = yaml.NewDecoder(f).Decode(&config)
if err != nil {
return err
}
check(time.Now())
ticker = time.NewTicker(config.CheckInterval)
t.check()
t.ticker = time.NewTicker(config.CheckInterval)
for {
select {
case <-done:
return nil
case t := <-ticker.C:
check(t)
case <-t.ticker.C:
t.check()
}
}
}
func check(t time.Time) {
instances, err := awsutils.GetInstances()
func (t *Tracker) check() {
instances, err := t.aws.GetInstances()
if err != nil {
log.Println(err)
return
@ -57,16 +56,19 @@ func check(t time.Time) {
}
// Updating the slice to have averages available in them
updateAverages(staleinstances)
t.updateAverages(staleinstances)
t.server.dataHTML = generateHTML(staleinstances)
t.server.dataTXT = generateText(staleinstances)
if len(staleinstances) > 0 {
if err := awsutils.SendEmail(
if err := t.aws.SendEmail(
config.Email.Subject,
config.Email.From,
config.Email.To,
config.Email.CC,
generateHTML(staleinstances),
generateText(staleinstances),
t.server.dataHTML,
t.server.dataTXT,
); err != nil {
log.Println("Error occurred while sending email:", err)
}
@ -87,9 +89,9 @@ func checkOvertime(instance *awsutils.Instance) int {
return -1
}
func updateAverages(instances []*awsutils.Instance) {
func (t *Tracker) updateAverages(instances []*awsutils.Instance) {
for _, instance := range instances {
results, err := awsutils.GetMetrics(instance.LaunchTime, time.Now().Truncate(time.Hour),
results, err := t.aws.GetMetrics(instance.LaunchTime, time.Now().Truncate(time.Hour),
[]awsutils.Metric{
{
InstanceID: instance.ID,

Loading…
Cancel
Save