-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Thomas Orrick
committed
Aug 11, 2015
0 parents
commit ac097c2
Showing
8 changed files
with
394 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.DS_Store | ||
spyglass | ||
spyglass-* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
ARCH = amd64 | ||
.PHONY: all build_linux build_darwin build_windows | ||
|
||
all: build_linux build_darwin build_windows | ||
|
||
build_linux: | ||
./docker.sh linux $(arch) | ||
|
||
build_darwin: | ||
./docker.sh darwin $(arch) | ||
|
||
build_windows: | ||
./docker.sh windows $(arch) | ||
|
||
clean: | ||
rm -f spyglass-* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
Spyglass | ||
======== | ||
|
||
Build Server deployment CLI | ||
|
||
# Usage | ||
* Set `APERTURE_SERVER_URL` environment variable to your OpenAperture dns name. | ||
* Run `spyglass configure` to set your credentials or use `APERTURE_USERNAME` and `APERTURE_PASSWORD` environment variables. | ||
|
||
More usage and help information can be found by running `spyglass --help` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
#! /bin/bash | ||
|
||
go get | ||
go build -v -o spyglass-$GOOS-$GOARCH |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
package main | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"io/ioutil" | ||
"os" | ||
"path" | ||
"time" | ||
|
||
"github.com/codegangsta/cli" | ||
"github.com/segmentio/go-prompt" | ||
"github.com/torrick/spyglass/openaperture" | ||
) | ||
|
||
func main() { | ||
app := cli.NewApp() | ||
environmentFlag := cli.StringFlag{Name: "environment, e", Usage: "environment to build or deploy"} | ||
commitHashFlag := cli.StringFlag{Name: "commit, c", Usage: "commit hash or branch to build or deploy"} | ||
app.Name = "spyglass" | ||
app.Version = "0.2.5" | ||
app.Author = "Thomas Orrick" | ||
app.Email = "[email protected]" | ||
app.Flags = []cli.Flag{ | ||
cli.BoolFlag{Name: "follow, f", Usage: "continually check status of a build or deploy"}, | ||
cli.StringFlag{Name: "server, s", Usage: "build server url", EnvVar: "APERTURE_SERVER_URL"}, | ||
} | ||
app.Commands = []cli.Command{ | ||
{ | ||
Name: "deploy", | ||
Usage: "build and deploy a docker repository", | ||
Action: func(c *cli.Context) { | ||
validate(c) | ||
fmt.Printf("Sending deploy request for:\n Project: %s\n Environment: %s\n", c.Args().First(), c.String("environment")) | ||
project := deploy(openaperture.NewProject(c.Args().First(), c.String("environment"), c.String("commit"), c.GlobalString("server"), | ||
c.String("build-exchange"), c.String("deploy-exchange"), c.Bool("force"))) | ||
if c.GlobalBool("follow") { | ||
checkStatus(project) | ||
} | ||
}, | ||
Flags: []cli.Flag{ | ||
environmentFlag, | ||
commitHashFlag, | ||
cli.StringFlag{Name: "build-exchange", Usage: "Set the build exchange id"}, | ||
cli.StringFlag{Name: "deploy-exchange", Usage: "Set the deploy exchange id"}, | ||
cli.BoolFlag{Name: "force", Usage: "Force a docker build"}, | ||
}, | ||
}, | ||
{ | ||
Name: "configure", | ||
Usage: "set configuration options", | ||
Action: func(c *cli.Context) { | ||
configure(c) | ||
}, | ||
}, | ||
} | ||
app.Run(os.Args) | ||
} | ||
|
||
func configure(c *cli.Context) { | ||
username := prompt.String("Username") | ||
password := prompt.Password("Password") | ||
config := map[string]string{"username": username, "password": password} | ||
configJSON, _ := json.Marshal(config) | ||
ioutil.WriteFile(path.Join(os.Getenv("HOME"), ".aperturecfg"), configJSON, 0600) | ||
} | ||
|
||
func checkStatus(project *openaperture.Project) { | ||
auth, err := openaperture.GetAuth() | ||
if err != nil { | ||
panic(err.Error()) | ||
} | ||
ticker := time.NewTicker(5 * time.Second) | ||
quit := make(chan struct{}) | ||
for { | ||
select { | ||
case <-ticker.C: | ||
workflow, err := project.Status(auth) | ||
if err != nil { | ||
close(quit) | ||
fmt.Println(err.Error()) | ||
os.Exit(1) | ||
} else if workflow.WorkflowError { | ||
close(quit) | ||
fmt.Println("Workflow failed") | ||
fmt.Println(workflow.EventLog) | ||
os.Exit(1) | ||
} else if workflow.WorkflowCompleted { | ||
fmt.Printf("Workflow completed in %s\n", workflow.ElapsedWorkflowTime) | ||
close(quit) | ||
} else { | ||
fmt.Printf("Milestone: %s in progress\n", workflow.CurrentStep) | ||
} | ||
case <-quit: | ||
ticker.Stop() | ||
os.Exit(0) | ||
} | ||
} | ||
} | ||
|
||
func validate(c *cli.Context) { | ||
if c.String("environment") == "" { | ||
fmt.Printf("Environment was not set. Please specify an environment to %s\n", c.Command.Name) | ||
os.Exit(1) | ||
} | ||
if c.String("commit") == "" { | ||
fmt.Printf("Commit hash or branch was not set. Please specify a commit hash or branch to %s\n", c.Command.Name) | ||
os.Exit(1) | ||
} | ||
if c.Args().First() == "" { | ||
fmt.Printf("Project name was not set. Please specify a project to %s\n", c.Command.Name) | ||
os.Exit(1) | ||
} | ||
} | ||
|
||
func deploy(project *openaperture.Project) *openaperture.Project { | ||
operations := []string{"build", "deploy"} | ||
token, err := openaperture.GetAuth() | ||
if err != nil { | ||
panic(err.Error()) | ||
} | ||
resp, err := project.CreateWorkflow(token, operations) | ||
if err != nil { | ||
panic(err.Error()) | ||
} | ||
fmt.Printf("Workflow created: %s\n", resp.Location) | ||
err = project.ExecuteWorkflow(token, resp.Location) | ||
if err != nil { | ||
panic(err.Error()) | ||
} | ||
fmt.Println("Successfully sent deploy request") | ||
return project | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
docker run --rm -it -e GOOS=$1 -e GOARCH=amd64 -v $GOPATH:/go -w /go/src/github.com/torrick/spyglass golang:1.4-cross ./build.sh |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
package openaperture | ||
|
||
import ( | ||
"bytes" | ||
"encoding/json" | ||
"errors" | ||
"io/ioutil" | ||
"net/http" | ||
"os" | ||
"path" | ||
) | ||
|
||
//Auth struct | ||
type Auth struct { | ||
AccessToken string `json:"access_token"` | ||
TokenType string `json:"token_type"` | ||
ExpiresIn string `json:"expires_in"` | ||
Scope string `json:"scope"` | ||
} | ||
|
||
//GetAuthorizationHeader build a proper authorization header for all api calls | ||
func (oauth *Auth) GetAuthorizationHeader() string { | ||
return "Bearer access_token=" + oauth.AccessToken | ||
} | ||
|
||
// GetAuth returns authentication config from various sources | ||
func GetAuth() (*Auth, error) { | ||
if _, err := os.Stat(path.Join(os.Getenv("HOME"), ".aperturecfg")); os.IsNotExist(err) { | ||
return EnvAuth() | ||
} | ||
return SharedAuth() | ||
} | ||
|
||
// SharedAuth generates an authentication config from local json file | ||
func SharedAuth() (*Auth, error) { | ||
var config map[string]string | ||
configPath := path.Join(os.Getenv("HOME"), ".aperturecfg") | ||
configBytes, err := ioutil.ReadFile(configPath) | ||
if err != nil { | ||
return nil, err | ||
} | ||
json.Unmarshal(configBytes, &config) | ||
return NewAuth(config["username"], config["password"]) | ||
} | ||
|
||
// EnvAuth pulls authentication information from environment variables | ||
func EnvAuth() (*Auth, error) { | ||
username := os.Getenv("APERTURE_USERNAME") | ||
password := os.Getenv("APERTURE_PASSWORD") | ||
if username == "" || password == "" { | ||
return nil, errors.New("username or password is blank") | ||
} | ||
return NewAuth(username, password) | ||
} | ||
|
||
// NewAuth requests a new token from idp | ||
func NewAuth(username string, password string) (*Auth, error) { | ||
var auth Auth | ||
url := "https://auth.psft.co/oauth/token" | ||
credentials := map[string]string{ | ||
"grant_type": "password", | ||
"username": username, | ||
"password": password, | ||
} | ||
payload, _ := json.Marshal(credentials) | ||
req, err := http.NewRequest("POST", url, bytes.NewBuffer(payload)) | ||
req.Header.Set("Content-Type", "application/json") | ||
|
||
client := &http.Client{} | ||
resp, err := client.Do(req) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
defer resp.Body.Close() | ||
body, _ := ioutil.ReadAll(resp.Body) | ||
json.Unmarshal(body, &auth) | ||
return &auth, nil | ||
} |
Oops, something went wrong.