Browse Source

Removed unnecessary calls to AWS API and created a ticker based function

master
Darshil Chanpura 2 years ago
parent
commit
a6f820ca40
  1. 63
      awsasg/init.go
  2. 114
      main.go

63
awsasg/init.go

@ -1,58 +1,61 @@
package awsasg
import (
"net/http"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/autoscaling"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/dtchanpura/nginx-org-asg/models"
)
var (
awssession *session.Session
err error
ec2svc *ec2.EC2
)
// Run for running the task
func Run(region, profile, asg string) ([]models.Instance, error) {
awsconfig := aws.NewConfig().WithRegion(region)
httpClient := &http.Client{Timeout: 5 * time.Second}
awsconfig := aws.Config{
HTTPClient: httpClient,
Region: aws.String(region),
}
opts := session.Options{
Profile: profile,
Config: *awsconfig,
Config: awsconfig,
}
awssession, err := session.NewSessionWithOptions(opts)
awssession, err = session.NewSessionWithOptions(opts)
if err != nil {
return nil, err
}
svc := autoscaling.New(awssession)
ec2svc := ec2.New(awssession)
first := true
result := &autoscaling.DescribeAutoScalingInstancesOutput{}
instances := []*string{}
for first || result.NextToken != nil {
first = false
input := &autoscaling.DescribeAutoScalingInstancesInput{
NextToken: result.NextToken,
}
result, err = svc.DescribeAutoScalingInstances(input)
if err != nil {
return nil, err
}
ec2svc = ec2.New(awssession)
for _, instance := range result.AutoScalingInstances {
if *instance.AutoScalingGroupName == asg && *instance.LifecycleState == autoscaling.LifecycleStateInService {
instances = append(instances, instance.InstanceId)
}
}
}
if len(instances) == 0 {
return []models.Instance{}, nil
}
input := &ec2.DescribeInstancesInput{
InstanceIds: instances,
Filters: []*ec2.Filter{
{
Name: aws.String("tag:aws:autoscaling:groupName"),
Values: []*string{
aws.String(asg),
},
}, {
Name: aws.String("instance-state-code"),
Values: []*string{
aws.String("16"),
},
},
},
}
output, err := ec2svc.DescribeInstances(input)
if err != nil {
return nil, err
}
insts := []models.Instance{}
for _, o := range output.Reservations {
for _, i := range o.Instances {
for _, r := range output.Reservations {
for _, i := range r.Instances {
insts = append(insts, models.Instance{InstanceID: *i.InstanceId, PrivateIPAddress: *i.PrivateIpAddress})
}
}

114
main.go

@ -3,30 +3,38 @@ package main
import (
"encoding/json"
"flag"
"fmt"
"log"
"os"
"os/signal"
"reflect"
"sort"
"sync"
"syscall"
"text/template"
"time"
hookutils "github.com/dtchanpura/deployment-agent/utils"
"github.com/dtchanpura/nginx-org-asg/awsasg"
"github.com/dtchanpura/nginx-org-asg/models"
"github.com/dtchanpura/nginx-org-asg/utils"
)
var (
profile string
region string
asg string
referenceFile string
outputFile string
format string
period PeriodValue
tmpl *template.Template
err error
profile string
region string
asg string
referenceFile string
outputFile string
format string
period PeriodValue
tmpl *template.Template
err error
quit chan os.Signal
// existingInstances []models.Instance
currentInstances []models.Instance
debug bool
ticker *time.Ticker
logger *log.Logger
)
// PeriodValue as flag
@ -50,30 +58,32 @@ func (p *PeriodValue) String() string {
}
func init() {
logger = log.New(os.Stdout, "nginx-org-asg", log.Llongfile|log.Ltime|log.Ldate)
flag.StringVar(&profile, "profile", "default", "Profile to use for from ~/.aws/credentials")
flag.StringVar(&region, "region", "us-east-1", "AWS Region")
flag.StringVar(&asg, "asg", "autoscaling-group", "Autoscaling Group name to be matched")
flag.StringVar(&outputFile, "out", "~/output.txt", "Output file for extracting IP addresses")
flag.StringVar(&referenceFile, "ref", "~/reference.json", "Output file for reference of IP addresses")
flag.StringVar(&format, "format", "{{.PrivateIPAddress}}:8080;", "Format to print out with.")
flag.BoolVar(&debug, "debug", false, "Debug output.")
flag.Var(&period, "period", "Period to repeat it at")
flag.Parse()
tmpl, err = template.New("instances").Parse("{{range .}}" + format + "\n{{end}}")
if err != nil {
log.Fatal("Problem parsing template", err)
logger.Fatal("Problem parsing template", err)
}
}
func main() {
func mainold() {
ref, err := os.OpenFile(referenceFile, os.O_CREATE|os.O_RDWR, 0644)
if err != nil {
log.Println("Problem in opening file", err)
logger.Println("Problem in opening file", err)
currentInstances = []models.Instance{}
}
// Get current instances from referenceFile
currentInstances, err = utils.GetInstances(ref)
if err != nil {
log.Println("Problem in getting instances", err)
logger.Println("Problem in getting instances", err)
return
}
@ -86,14 +96,14 @@ func main() {
// Sort the instances from AWS API
sort.Sort(models.ByIP(instances))
if reflect.DeepEqual(currentInstances, instances) {
fmt.Println("no changes detected.")
logger.Println("no changes detected.")
return
}
// Truncate file if there are changes and seek to start of file
err = utils.TruncateFile(ref)
if err != nil {
log.Println("Error in trucating file", err)
logger.Println("Error in trucating file", err)
return
}
@ -113,7 +123,7 @@ func main() {
// Truncate outputFile
err = utils.TruncateFile(of)
if err != nil {
log.Println("Error in trucating file", err)
logger.Println("Error in trucating file", err)
return
}
// Write in outputFile with format specified
@ -123,62 +133,96 @@ func main() {
}
}
func mainpart() {
func main() {
quit = make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGTERM)
existingInstances := fetchInstancesFromFile()
if period.Duration > 0 {
ticker = time.NewTicker(period.Duration)
} else {
ticker = time.NewTicker(30 * time.Second)
}
var mutex = &sync.Mutex{}
//
for {
select {
case <-ticker.C:
mutex.Lock()
existingInstances = checkChange(existingInstances)
if debug {
log.Printf("[DEBUG] Instances: %d\n", len(existingInstances))
}
mutex.Unlock()
case <-quit:
ticker.Stop()
return
// break loop
}
}
// ticker part
}
func checkChange(existingInstances []models.Instance) []models.Instance {
newInstances := fetchInstancesFromAWS()
if reflect.DeepEqual(existingInstances, newInstances) {
fmt.Println("no changes detected.")
} else {
// Update the in-memory copy of instances
copy(existingInstances, newInstances)
// Truncate outputFile
if !reflect.DeepEqual(existingInstances, newInstances) {
err := utils.TruncateFileR(outputFile)
if err != nil {
log.Println("Problem with truncating output file", err)
return
logger.Println("Problem with truncating output file", err)
return existingInstances
}
// Update outputFile with latest changes
of, err := os.OpenFile(outputFile, os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Fatal("Problem with file", err)
logger.Println("Problem with file", err)
return existingInstances
}
defer of.Close()
err = tmpl.Execute(of, newInstances)
if err != nil {
log.Fatal("Problem executing template", err)
logger.Println("Problem executing template", err)
return existingInstances
}
// Update referenceFile for consistency
err = utils.TruncateFileR(referenceFile)
if err != nil {
logger.Println("Problem with truncating reference file", err)
return existingInstances
}
rf, err := os.OpenFile(referenceFile, os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Fatal("Problem with file", err)
logger.Println("Problem with file", err)
return existingInstances
}
defer rf.Close()
encoder := json.NewEncoder(rf)
encoder.Encode(newInstances)
if err != nil {
log.Fatal("Problem executing template", err)
logger.Println("Problem executing template", err)
return existingInstances
}
existingInstances = make([]models.Instance, len(newInstances))
copy(existingInstances, newInstances)
// Run Hooks
logger.Println(hookutils.ExecuteScript(".", "/Users/darshil/Projects/go/src/github.com/dtchanpura/nginx-org-asg/test.sh"))
}
return existingInstances
}
func fetchInstancesFromFile() []models.Instance {
ref, err := os.OpenFile(referenceFile, os.O_CREATE|os.O_RDWR, 0644)
var instances []models.Instance
if err != nil {
log.Println("Problem in opening file", err)
logger.Println("Problem in opening file", err)
}
defer ref.Close()
// Get current instances from referenceFile
instances, err = utils.GetInstances(ref)
if err != nil {
log.Println("Problem in getting instances", err)
logger.Println("Problem in getting instances", err)
return []models.Instance{}
}
// sort the instances by their IP
@ -190,7 +234,7 @@ func fetchInstancesFromFile() []models.Instance {
func fetchInstancesFromAWS() []models.Instance {
instances, err := awsasg.Run(region, profile, asg)
if err != nil {
log.Println("Problem in awsasg.Run", err)
logger.Println("Problem in awsasg.Run", err)
return []models.Instance{}
}
// sort the instances by their IP

Loading…
Cancel
Save