Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Self contained execution, without any dependencies #17

Merged
merged 2 commits into from
Sep 23, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
build
autospotting
coverage.out
lambda/GIT_SHA
lambda/autospotting_lambda
lambda/instances.json
2 changes: 0 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ go:
- tip

before_install:
- sudo apt-get -qq update
- sudo apt-get install -y upx
- go get github.com/mattn/goveralls
- go get golang.org/x/tools/cmd/cover

Expand Down
40 changes: 27 additions & 13 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,32 +1,46 @@
BINARY=autospotting
LAMBDA_BINARY=autospotting_lambda
LOCAL_PATH=build/s3/dv
BUCKET_NAME=cloudprowess

# upstream data
#INSTANCES_URL="https://raw.githubusercontent.com/powdahound/ec2instances.info/master/www/instances.json"
# my Github fork
INSTANCES_URL="https://raw.githubusercontent.com/cristim/ec2instances.info/master/www/instances.json"

all: build_local

release: upload

build_local:
check_deps:
./check_deps.sh

build_local: check_deps
go build $(GOFLAGS)

build_lambda:
build_lambda_binary: check_deps
GOOS=linux GOARCH=amd64 go build -o ${LAMBDA_BINARY}

strip: build_lambda
strip: build_lambda_binary
strip ${LAMBDA_BINARY}
upx --lzma --best ${LAMBDA_BINARY}

install: strip
CHECKSUM=$$(sha256sum ${LAMBDA_BINARY} | cut -f1 -d " " ); \
FILENAME=${BINARY}_$$CHECKSUM ; \
mkdir -p ${LOCAL_PATH} ; \
mv ${LAMBDA_BINARY} ${LOCAL_PATH}/$$FILENAME ; \
echo $$FILENAME > ${LOCAL_PATH}/latest_agent
lambda: strip
git rev-parse HEAD | cut -c 1-8 > lambda/GIT_SHA
mv ${LAMBDA_BINARY} lambda/
curl ${INSTANCES_URL} --output lambda/instances.json
zip -9 -v -j lambda lambda/*
rm -rf ${LOCAL_PATH}
mkdir -p ${LOCAL_PATH}
mv lambda.zip ${LOCAL_PATH}

install: lambda

upload: install
aws s3 sync build/s3/ s3://cloudprowess/
aws s3 sync build/s3/ s3://${BUCKET_NAME}/

test: build_local
./autospotting -e core/test_data/event.json -c core/test_data/context.json
./autospotting core/test_data/json_instance/instances.json

cover:
go test -covermode=count -coverprofile=coverage.out ./core && go tool cover -html=coverage.out
go test -covermode=count -coverprofile=coverage.out ./core
go tool cover -html=coverage.out
16 changes: 9 additions & 7 deletions autospotting.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,24 @@ package main

import (
"fmt"
"log"
"os"

autospotting "github.com/cristim/autospotting/core"
)

// upstream data
// const instancesURL = "https://raw.githubusercontent.com/powdahound/ec2instances.info/master/www/instances.json"

// my Github fork
const instancesURL = "https://raw.githubusercontent.com/cristim/ec2instances.info/master/www/instances.json"

// Main intefaces with the lambda event handler wrapper written
// in javascript.
func main() {
fmt.Println("Starting agent...")

autospotting.Run(instancesURL)
if len(os.Args) != 2 {
log.Fatal("The program needs a command line argument: ",
os.Args[0], " <instances.json>")
}
instancesFile := os.Args[1]

autospotting.Run(instancesFile)

fmt.Println("Exiting main, nothing left to do")
}
18 changes: 18 additions & 0 deletions check_deps.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/bash

function check_dep {
command -v $1 >/dev/null 2>&1 || {
echo >&2 "The required dependency program '$1' is not installed. Aborting."
exit 1
}
}

DEPS="aws curl git go strip zip"

echo "Checking for the presence of the following dependencies: ${DEPS}"

for DEP in $DEPS
do
check_dep $DEP && echo "Found ${DEP}"
done
echo "All dependencies were successfully found, we're good to go!"
17 changes: 4 additions & 13 deletions core/json_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package autospotting
import (
"encoding/json"
"io/ioutil"
"net/http"
"log"
)

// AWS Instances JSON Structure Definitions
Expand Down Expand Up @@ -67,20 +67,11 @@ type regionPrices struct {

type jsonInstances []jsonInstance

func (i *jsonInstances) loadFromURL(url string) error {
func (i *jsonInstances) loadFromFile(fileName string) error {

response, err := http.Get(url)
contents, err := ioutil.ReadFile(fileName)
if err != nil {
logger.Println(err.Error())
return err
}

defer response.Body.Close()

contents, err := ioutil.ReadAll(response.Body)
if err != nil {
logger.Println(err.Error())
return err
log.Fatal(err.Error())
}

// logger.Println(string(contents))
Expand Down
4 changes: 2 additions & 2 deletions core/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package autospotting
// Run starts processing all AWS regions looking for AutoScaling groups
// enabled and taking action by replacing more pricy on-demand instances with
// compatible and cheaper spot instances.
func Run(instancesURL string) {
func Run(instancesFile string) {

initLogger()

Expand All @@ -13,7 +13,7 @@ func Run(instancesURL string) {
var jsonInst jsonInstances

logger.Println("Loading on-demand instance pricing information")
jsonInst.loadFromURL(instancesURL)
jsonInst.loadFromFile(instancesFile)

// logger.Println(spew.Sdump(jsonInst))

Expand Down
16 changes: 0 additions & 16 deletions lambda/Makefile

This file was deleted.

76 changes: 11 additions & 65 deletions lambda/wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,78 +5,24 @@
"""

import json
import os.path
import sys

from urlparse import urljoin
from urllib2 import URLError, urlopen
from subprocess import call, PIPE, STDOUT, check_output

URL_PATH = 'https://cdn.cloudprowess.com/dv/'
from subprocess import call, STDOUT

BINARY = './autospotting_lambda'
JSON_INSTANCES = 'instances.json'
GIT_SHA = 'GIT_SHA'

def lambda_handler(event, context):
""" Main entry point for Lambda """
print 'Received event: ' + json.dumps(event, indent=2)
print "Context log stream: " + context.log_stream_name

try:
filename = get_latest_agent_filename()
download_agent_if_missing(filename)
run_agent(filename)

except URLError as ex:
print 'Error: ', ex


def get_latest_agent_filename():
"""Determines the filename of the latest released agent golang binary"""
return urlopen(
urljoin(
URL_PATH,
'latest_agent'
)
).read().strip()


def download_agent_if_missing(filename):
""" Downloads the agent if missing from the current Lambda run """
if file_missing(filename):
print filename+'is missing, downloading it first'
download(filename)


def file_missing(filename):
"""Checks file for existence"""
return not os.path.isfile(filename)


def download(filename):
""" Downloads a file from the base URL path into /tmp/<filename> """
print "Downloading", filename
file_content = urlopen(
urljoin(URL_PATH, filename)
)
write_data_to_file(
file_content.read(),
os.path.join(
'/tmp',
filename
)
)


def write_data_to_file(data, filename):
""" Writes data to filename """
with open(filename, 'wb') as outfile:
outfile.write(data)
with open(GIT_SHA, 'r') as sha:
print 'Starting AutoSpotting, built from the git SHA', sha.read()

print 'Received event: ' + json.dumps(event, indent=2)

def run_agent(filename):
""" Runs the agent witn the required params """
print "Running", filename
print "Running", BINARY, JSON_INSTANCES
call([BINARY, JSON_INSTANCES], stderr=STDOUT)

binary_path = os.path.join('/tmp', filename)

os.chmod(binary_path, 0755)
call([binary_path], stderr=STDOUT)
if __name__ == '__main__':
lambda_handler(None, None)