<commit_before>package GoSDK

import (
	"encoding/base64"
	"fmt"
)

const (
	_ADAPTOR_HEADER_KEY    = "ClearBlade-DeviceToken"
	_ADAPTORS_DEV_PREAMBLE = "/admin/"
)

func (d *DevClient) GetAdaptors(systemKey string) ([]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}
	resp, err := get(d, _ADAPTORS_DEV_PREAMBLE+systemKey+"/adaptors", nil, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.([]interface{}), nil
}

func (u *UserClient) GetAdaptors(systemKey string) ([]interface{}, error) {
	return nil, fmt.Errorf("User client cannot get adaptors")
}

func (d *DeviceClient) GetAdaptors(systemKey string) ([]interface{}, error) {
	return nil, fmt.Errorf("Device client cannot get adaptors")
}

func (d *DevClient) GetAdaptor(systemKey, name string) (map[string]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}
	resp, err := get(d, _ADAPTORS_DEV_PREAMBLE+systemKey+"/adaptors/"+name, nil, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.(map[string]interface{}), nil
}

func (u *UserClient) GetAdaptor(systemKey, name string) (map[string]interface{}, error) {
	return nil, fmt.Errorf("User client cannot get adaptor")
}

func (d *DeviceClient) GetAdaptor(systemKey, name string) (map[string]interface{}, error) {
	return nil, fmt.Errorf("Device client cannot get adaptor")
}

func (d *DevClient) CreateAdaptor(systemKey, name string,
	data map[string]interface{}) (map[string]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}
	data["name"] = name
	resp, err := post(d, _ADAPTORS_DEV_PREAMBLE+systemKey+"/adaptors", data, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.(map[string]interface{}), nil
}

func (u *UserClient) CreateAdaptor(systemKey, name string, data map[string]interface{}) (map[string]interface{}, error) {
	return nil, fmt.Errorf("User client cannot create an adaptor")
}

func (d *DeviceClient) CreateAdaptor(systemKey, name string, data map[string]interface{}) (map[string]interface{}, error) {
	return nil, fmt.Errorf("Device client cannot create an adaptor")
}

func (d *DevClient) DeleteAdaptor(systemKey, name string) error {
	creds, err := d.credentials()
	if err != nil {
		return err
	}
	resp, err := delete(d, _ADAPTORS_DEV_PREAMBLE+systemKey+"/adaptors/"+name, nil, creds, nil)
	_, err = mapResponse(resp, err)
	return err
}

func (u *UserClient) DeleteAdaptor(systemKey, name string) error {
	return fmt.Errorf("User client cannot delete an adaptor")
}

func (d *DeviceClient) DeleteAdaptor(systemKey, name string) error {
	return fmt.Errorf("Device client cannot delete an adaptor")
}

func (d *DevClient) UpdateAdaptor(systemKey, name string, data map[string]interface{}) (map[string]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}
	resp, err := put(d, _ADAPTORS_DEV_PREAMBLE+systemKey+"/adaptors/"+name, data, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.(map[string]interface{}), nil
}

func (u *UserClient) UpdateAdaptor(systemKey, name string, data map[string]interface{}) (map[string]interface{}, error) {
	return nil, fmt.Errorf("User client cannot update an adaptor")
}

func (d *DeviceClient) UpdateAdaptor(systemKey, name string, data map[string]interface{}) (map[string]interface{}, error) {
	return nil, fmt.Errorf("Device client cannot update an adaptor")
}

func (d *DevClient) GetAdaptorFiles(systemKey, adaptorName string) ([]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}
	resp, err := get(d, _ADAPTORS_DEV_PREAMBLE+systemKey+"/adaptors/"+adaptorName+"/files", nil, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.([]interface{}), nil
}

func (u *UserClient) GetAdaptorFiles(systemKey, adaptorName string) ([]interface{}, error) {
	return nil, fmt.Errorf("User client cannot get adaptor files")
}

func (d *DeviceClient) GetAdaptorFiles(systemKey, adaptorName string) ([]interface{}, error) {
	return nil, fmt.Errorf("Device client cannot get adaptor files")
}

func (d *DevClient) GetAdaptorFile(systemKey, adaptorName, fileName string) (map[string]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}
	resp, err := get(d, _ADAPTORS_DEV_PREAMBLE+systemKey+"/adaptors/"+adaptorName+"/files/"+fileName, nil, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.(map[string]interface{}), nil
}

func (u *UserClient) GetAdaptorFile(systemKey, adaptorName, fileName string) (map[string]interface{}, error) {
	return nil, fmt.Errorf("User client cannot get adaptor file")
}

func (d *DeviceClient) GetAdaptorFile(systemKey, adaptorName, fileName string) (map[string]interface{}, error) {
	return nil, fmt.Errorf("Device client cannot get adaptor file")
}

func (d *DevClient) CreateAdaptorFile(systemKey, adaptorName, fileName string,
	data map[string]interface{}) (map[string]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}

	contentsIF, exists := data["file"]
	if !exists {
		return nil, fmt.Errorf("'file' key/value pair missing in CreateAdaptorFile")
	}

	// if a user sends us a byte array (probably an executable file) we need to base64 encode it
	// if a user sends us a string we assume it's base64 encoded
	var fileContents string
	switch contentsIF.(type) {
	case []byte:
		fileContents = base64.StdEncoding.EncodeToString(contentsIF.([]byte))
	case string:
		fileContents = contentsIF.(string)
	default:
		return nil, fmt.Errorf("Bad type for 'file' k/v pair in CreateAdaptorFile: %T: (%+v)", contentsIF, contentsIF)
	}

	data["file"] = fileContents
	data["name"] = fileName
	data["adaptor_name"] = adaptorName

	resp, err := post(d, _ADAPTORS_DEV_PREAMBLE+systemKey+"/adaptors/"+adaptorName+"/files", data, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.(map[string]interface{}), nil
}

func (u *UserClient) CreateAdaptorFile(systemKey, adaptorName, fileName string, data map[string]interface{}) (map[string]interface{}, error) {
	return nil, fmt.Errorf("User client cannot create an adaptor file")
}

func (d *DeviceClient) CreateAdaptorFile(systemKey, adaptorName, fileName string, data map[string]interface{}) (map[string]interface{}, error) {
	return nil, fmt.Errorf("Device client cannot create an adaptor file")
}

func (d *DevClient) DeleteAdaptorFile(systemKey, adaptorName, fileName string) error {
	creds, err := d.credentials()
	if err != nil {
		return err
	}
	resp, err := delete(d, _ADAPTORS_DEV_PREAMBLE+systemKey+"/adaptors/"+adaptorName+"/files/"+fileName, nil, creds, nil)
	_, err = mapResponse(resp, err)
	return err
}

func (u *UserClient) DeleteAdaptorFile(systemKey, adaptorName, fileName string) error {
	return fmt.Errorf("User client cannot delete an adaptor file")
}

func (d *DeviceClient) DeleteAdaptorFile(systemKey, adaptorName, fileName string) error {
	return fmt.Errorf("Device client cannot delete an adaptor file")
}

func (d *DevClient) UpdateAdaptorFile(systemKey, adaptorName, fileName string, data map[string]interface{}) (map[string]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}
	contentsIF, exists := data["file"]
	if !exists {
		return nil, fmt.Errorf("'file' key/value pair missing in UpdateAdaptorFile")
	}
	byts, ok := contentsIF.([]byte)
	if !ok {
		return nil, fmt.Errorf("Bad type for 'file' k/v pair in CreateAdaptorFile: %T: (%+v)", contentsIF, contentsIF)
	}
	data["file"] = base64.StdEncoding.EncodeToString(byts)
	data["name"] = fileName
	resp, err := put(d, _ADAPTORS_DEV_PREAMBLE+systemKey+"/adaptors/"+adaptorName+"/files/"+fileName, data, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.(map[string]interface{}), nil
}

func (u *UserClient) UpdateAdaptorFile(systemKey, adaptorName, fileName string, data map[string]interface{}) (map[string]interface{}, error) {
	return nil, fmt.Errorf("User client cannot update an adaptor file")
}

func (d *DeviceClient) UpdateAdaptorFile(systemKey, adaptorName, fileName string, data map[string]interface{}) (map[string]interface{}, error) {
	return nil, fmt.Errorf("Device client cannot update an adaptor file")
}

func (d *DevClient) DeployAdaptor(systemKey, adaptorName string, deploySpec map[string]interface{}) (map[string]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}
	resp, err := put(d, _ADAPTORS_DEV_PREAMBLE+systemKey+"/adaptors/"+adaptorName+"/deploy", deploySpec, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.(map[string]interface{}), nil
}

func (u *UserClient) DeployAdaptor(systemKey, adaptorName string, deploySpec map[string]interface{}) (map[string]interface{}, error) {
	return nil, fmt.Errorf("User client cannot deploy an adaptor")
}

func (d *DeviceClient) DeployAdaptor(systemKey, adaptorName string, deploySpec map[string]interface{}) (map[string]interface{}, error) {
	return nil, fmt.Errorf("Device client cannot deploy an adaptor")
}

func (d *DevClient) ControlAdaptor(systemKey, adaptorName string, controlSpec map[string]interface{}) (map[string]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}
	resp, err := put(d, _ADAPTORS_DEV_PREAMBLE+systemKey+"/adaptors/"+adaptorName+"/control", controlSpec, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.(map[string]interface{}), nil
}

func (u *UserClient) ControlAdaptor(systemKey, adaptorName string, controlSpec map[string]interface{}) (map[string]interface{}, error) {
	return nil, fmt.Errorf("User client cannot control an adaptor")
}

func (d *DeviceClient) ControlAdaptor(systemKey, adaptorName string, controlSpec map[string]interface{}) (map[string]interface{}, error) {
	return nil, fmt.Errorf("Device client cannot control an adaptor")
}
<commit_msg>moved get contents for file to separate function<commit_after>package GoSDK

import (
	"encoding/base64"
	"fmt"
)

const (
	_ADAPTOR_HEADER_KEY    = "ClearBlade-DeviceToken"
	_ADAPTORS_DEV_PREAMBLE = "/admin/"
)

func (d *DevClient) GetAdaptors(systemKey string) ([]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}
	resp, err := get(d, _ADAPTORS_DEV_PREAMBLE+systemKey+"/adaptors", nil, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.([]interface{}), nil
}

func (u *UserClient) GetAdaptors(systemKey string) ([]interface{}, error) {
	return nil, fmt.Errorf("User client cannot get adaptors")
}

func (d *DeviceClient) GetAdaptors(systemKey string) ([]interface{}, error) {
	return nil, fmt.Errorf("Device client cannot get adaptors")
}

func (d *DevClient) GetAdaptor(systemKey, name string) (map[string]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}
	resp, err := get(d, _ADAPTORS_DEV_PREAMBLE+systemKey+"/adaptors/"+name, nil, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.(map[string]interface{}), nil
}

func (u *UserClient) GetAdaptor(systemKey, name string) (map[string]interface{}, error) {
	return nil, fmt.Errorf("User client cannot get adaptor")
}

func (d *DeviceClient) GetAdaptor(systemKey, name string) (map[string]interface{}, error) {
	return nil, fmt.Errorf("Device client cannot get adaptor")
}

func (d *DevClient) CreateAdaptor(systemKey, name string,
	data map[string]interface{}) (map[string]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}
	data["name"] = name
	resp, err := post(d, _ADAPTORS_DEV_PREAMBLE+systemKey+"/adaptors", data, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.(map[string]interface{}), nil
}

func (u *UserClient) CreateAdaptor(systemKey, name string, data map[string]interface{}) (map[string]interface{}, error) {
	return nil, fmt.Errorf("User client cannot create an adaptor")
}

func (d *DeviceClient) CreateAdaptor(systemKey, name string, data map[string]interface{}) (map[string]interface{}, error) {
	return nil, fmt.Errorf("Device client cannot create an adaptor")
}

func (d *DevClient) DeleteAdaptor(systemKey, name string) error {
	creds, err := d.credentials()
	if err != nil {
		return err
	}
	resp, err := delete(d, _ADAPTORS_DEV_PREAMBLE+systemKey+"/adaptors/"+name, nil, creds, nil)
	_, err = mapResponse(resp, err)
	return err
}

func (u *UserClient) DeleteAdaptor(systemKey, name string) error {
	return fmt.Errorf("User client cannot delete an adaptor")
}

func (d *DeviceClient) DeleteAdaptor(systemKey, name string) error {
	return fmt.Errorf("Device client cannot delete an adaptor")
}

func (d *DevClient) UpdateAdaptor(systemKey, name string, data map[string]interface{}) (map[string]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}
	resp, err := put(d, _ADAPTORS_DEV_PREAMBLE+systemKey+"/adaptors/"+name, data, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.(map[string]interface{}), nil
}

func (u *UserClient) UpdateAdaptor(systemKey, name string, data map[string]interface{}) (map[string]interface{}, error) {
	return nil, fmt.Errorf("User client cannot update an adaptor")
}

func (d *DeviceClient) UpdateAdaptor(systemKey, name string, data map[string]interface{}) (map[string]interface{}, error) {
	return nil, fmt.Errorf("Device client cannot update an adaptor")
}

func (d *DevClient) GetAdaptorFiles(systemKey, adaptorName string) ([]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}
	resp, err := get(d, _ADAPTORS_DEV_PREAMBLE+systemKey+"/adaptors/"+adaptorName+"/files", nil, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.([]interface{}), nil
}

func (u *UserClient) GetAdaptorFiles(systemKey, adaptorName string) ([]interface{}, error) {
	return nil, fmt.Errorf("User client cannot get adaptor files")
}

func (d *DeviceClient) GetAdaptorFiles(systemKey, adaptorName string) ([]interface{}, error) {
	return nil, fmt.Errorf("Device client cannot get adaptor files")
}

func (d *DevClient) GetAdaptorFile(systemKey, adaptorName, fileName string) (map[string]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}
	resp, err := get(d, _ADAPTORS_DEV_PREAMBLE+systemKey+"/adaptors/"+adaptorName+"/files/"+fileName, nil, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.(map[string]interface{}), nil
}

func (u *UserClient) GetAdaptorFile(systemKey, adaptorName, fileName string) (map[string]interface{}, error) {
	return nil, fmt.Errorf("User client cannot get adaptor file")
}

func (d *DeviceClient) GetAdaptorFile(systemKey, adaptorName, fileName string) (map[string]interface{}, error) {
	return nil, fmt.Errorf("Device client cannot get adaptor file")
}

func getContentsForFile(fileValue interface{}) (string, error) {
	// if a user sends us a byte array (probably an executable file) we need to base64 encode it
	// if a user sends us a string we assume it's base64 encoded
	var fileContents string
	switch fileValue.(type) {
	case []byte:
		fileContents = base64.StdEncoding.EncodeToString(fileValue.([]byte))
	case string:
		fileContents = fileValue.(string)
	default:
		return "", fmt.Errorf("Bad type for 'file' k/v pair in CreateAdaptorFile: %T: (%+v)", fileValue, fileValue)
	}
	return fileContents, nil
}

func (d *DevClient) CreateAdaptorFile(systemKey, adaptorName, fileName string,
	data map[string]interface{}) (map[string]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}

	contentsIF, exists := data["file"]
	if !exists {
		return nil, fmt.Errorf("'file' key/value pair missing in CreateAdaptorFile")
	}

	if fileContents, err := getContentsForFile(contentsIF); err != nil {
		return nil, err
	} else {
		data["file"] = fileContents
	}

	data["name"] = fileName
	data["adaptor_name"] = adaptorName

	resp, err := post(d, _ADAPTORS_DEV_PREAMBLE+systemKey+"/adaptors/"+adaptorName+"/files", data, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.(map[string]interface{}), nil
}

func (u *UserClient) CreateAdaptorFile(systemKey, adaptorName, fileName string, data map[string]interface{}) (map[string]interface{}, error) {
	return nil, fmt.Errorf("User client cannot create an adaptor file")
}

func (d *DeviceClient) CreateAdaptorFile(systemKey, adaptorName, fileName string, data map[string]interface{}) (map[string]interface{}, error) {
	return nil, fmt.Errorf("Device client cannot create an adaptor file")
}

func (d *DevClient) DeleteAdaptorFile(systemKey, adaptorName, fileName string) error {
	creds, err := d.credentials()
	if err != nil {
		return err
	}
	resp, err := delete(d, _ADAPTORS_DEV_PREAMBLE+systemKey+"/adaptors/"+adaptorName+"/files/"+fileName, nil, creds, nil)
	_, err = mapResponse(resp, err)
	return err
}

func (u *UserClient) DeleteAdaptorFile(systemKey, adaptorName, fileName string) error {
	return fmt.Errorf("User client cannot delete an adaptor file")
}

func (d *DeviceClient) DeleteAdaptorFile(systemKey, adaptorName, fileName string) error {
	return fmt.Errorf("Device client cannot delete an adaptor file")
}

func (d *DevClient) UpdateAdaptorFile(systemKey, adaptorName, fileName string, data map[string]interface{}) (map[string]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}
	contentsIF, exists := data["file"]
	if !exists {
		return nil, fmt.Errorf("'file' key/value pair missing in UpdateAdaptorFile")
	}

	if fileContents, err := getContentsForFile(contentsIF); err != nil {
		return nil, err
	} else {
		data["file"] = fileContents
	}
	data["name"] = fileName
	resp, err := put(d, _ADAPTORS_DEV_PREAMBLE+systemKey+"/adaptors/"+adaptorName+"/files/"+fileName, data, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.(map[string]interface{}), nil
}

func (u *UserClient) UpdateAdaptorFile(systemKey, adaptorName, fileName string, data map[string]interface{}) (map[string]interface{}, error) {
	return nil, fmt.Errorf("User client cannot update an adaptor file")
}

func (d *DeviceClient) UpdateAdaptorFile(systemKey, adaptorName, fileName string, data map[string]interface{}) (map[string]interface{}, error) {
	return nil, fmt.Errorf("Device client cannot update an adaptor file")
}

func (d *DevClient) DeployAdaptor(systemKey, adaptorName string, deploySpec map[string]interface{}) (map[string]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}
	resp, err := put(d, _ADAPTORS_DEV_PREAMBLE+systemKey+"/adaptors/"+adaptorName+"/deploy", deploySpec, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.(map[string]interface{}), nil
}

func (u *UserClient) DeployAdaptor(systemKey, adaptorName string, deploySpec map[string]interface{}) (map[string]interface{}, error) {
	return nil, fmt.Errorf("User client cannot deploy an adaptor")
}

func (d *DeviceClient) DeployAdaptor(systemKey, adaptorName string, deploySpec map[string]interface{}) (map[string]interface{}, error) {
	return nil, fmt.Errorf("Device client cannot deploy an adaptor")
}

func (d *DevClient) ControlAdaptor(systemKey, adaptorName string, controlSpec map[string]interface{}) (map[string]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}
	resp, err := put(d, _ADAPTORS_DEV_PREAMBLE+systemKey+"/adaptors/"+adaptorName+"/control", controlSpec, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.(map[string]interface{}), nil
}

func (u *UserClient) ControlAdaptor(systemKey, adaptorName string, controlSpec map[string]interface{}) (map[string]interface{}, error) {
	return nil, fmt.Errorf("User client cannot control an adaptor")
}

func (d *DeviceClient) ControlAdaptor(systemKey, adaptorName string, controlSpec map[string]interface{}) (map[string]interface{}, error) {
	return nil, fmt.Errorf("Device client cannot control an adaptor")
}
<|endoftext|>


<commit_before>/*
Package goat provides the back-end implementation of a BitTorrent tracker.
*/
package main
<commit_msg>package main -> goat<commit_after>/*
Package goat provides the back-end implementation of a BitTorrent tracker.
*/
package goat
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"strconv"

	ratingsController "hermes/ratings/controller"
	ratingsHandler "hermes/ratings/handler"
	statsController "hermes/stats/controller"
	statsHandler "hermes/stats/handler"

	"github.com/alecthomas/kingpin"
	"github.com/facebookgo/grace/gracehttp"
	"github.com/labstack/echo"
)

var (
	app            = kingpin.New("hermes", "GCBA product ratings APIs.")
	startCommand   = kingpin.Command("start", "Start an Hermes API.")
	ratingsCommand = startCommand.Command("ratings", "Start the ratings API.")
	statsCommand   = startCommand.Command("stats", "Start the statistics API.")
	ratingsPort    = getPort("HERMES_RATINGS_PORT", 5000)
	statsPort      = getPort("HERMES_STATS_PORT", 7000)
	noCursor       = "\n\n\033[?25l"
	banner         = `
 _  _ ____ ____ _  _ ____ ____
 |__| |___ |__/ |\/| |___ [__
 |  | |___ |  \ |  | |___ ___] `
)

func main() {
	kingpin.Version("0.0.1")
	fmt.Println("\n", banner)

	switch kingpin.Parse() {
	case "start ratings":
		fmt.Print("	               ratings", "\n\n\n")
		startRatingsAPI()
	case "start stats":
		fmt.Print("	                 stats", "\n\n\n")
		startStatsAPI()
	}
}

func startRatingsAPI() {
	routes := map[string]echo.HandlerFunc{
		"OptionsRoot":    ratingsController.OptionsRoot,
		"OptionsRatings": ratingsController.OptionsRatings,
		"PostRatings":    ratingsController.PostRatings}

	handler, castOk := ratingsHandler.Handler(ratingsPort, routes).(*echo.Echo)

	if !castOk {
		handler.Logger.Fatal("Could not start server")
	}

	fmt.Println("✅  Ratings server started on port", strconv.Itoa(ratingsPort))
	fmt.Print(noCursor)

	handler.Logger.Fatal(gracehttp.Serve(handler.Server))
}

func startStatsAPI() {
	routes := map[string]echo.HandlerFunc{"PostStats": statsController.PostStats}
	handler, castOk := statsHandler.Handler(statsPort, routes).(*echo.Echo)

	if !castOk {
		handler.Logger.Fatal("Could not start server")
	}

	fmt.Println("✅  Stats server started on port", strconv.Itoa(statsPort))
	fmt.Print(noCursor)

	handler.Logger.Fatal(gracehttp.Serve(handler.Server))
}

func getPort(env string, defaultPort int) int {
	port, portErr := strconv.Atoi(os.Getenv(env))

	if portErr != nil {
		return defaultPort
	}

	return port
}
<commit_msg>Style fix<commit_after>package main

import (
	"fmt"
	"os"
	"strconv"

	ratingsController "hermes/ratings/controller"
	ratingsHandler "hermes/ratings/handler"
	statsController "hermes/stats/controller"
	statsHandler "hermes/stats/handler"

	"github.com/alecthomas/kingpin"
	"github.com/facebookgo/grace/gracehttp"
	"github.com/labstack/echo"
)

var (
	app            = kingpin.New("hermes", "GCBA product ratings APIs.")
	startCommand   = kingpin.Command("start", "Start an Hermes API.")
	ratingsCommand = startCommand.Command("ratings", "Start the ratings API.")
	statsCommand   = startCommand.Command("stats", "Start the statistics API.")
	ratingsPort    = getPort("HERMES_RATINGS_PORT", 5000)
	statsPort      = getPort("HERMES_STATS_PORT", 7000)
	noCursor       = "\n\n\033[?25l"
	banner         = `
 _  _ ____ ____ _  _ ____ ____
 |__| |___ |__/ |\/| |___ [__
 |  | |___ |  \ |  | |___ ___] `
)

func main() {
	kingpin.Version("0.0.1")
	fmt.Print("\n", banner, "\n\n\n")

	switch kingpin.Parse() {
	case ratingsCommand.FullCommand():
		startRatingsAPI()
	case statsCommand.FullCommand():
		startStatsAPI()
	}
}

func startRatingsAPI() {
	routes := map[string]echo.HandlerFunc{
		"OptionsRoot":    ratingsController.OptionsRoot,
		"OptionsRatings": ratingsController.OptionsRatings,
		"PostRatings":    ratingsController.PostRatings}

	handler, castOk := ratingsHandler.Handler(ratingsPort, routes).(*echo.Echo)

	if !castOk {
		handler.Logger.Fatal("Could not start server")
	}

	fmt.Println("✅  Ratings server started on port", strconv.Itoa(ratingsPort))
	fmt.Print(noCursor)

	handler.Logger.Fatal(gracehttp.Serve(handler.Server))
}

func startStatsAPI() {
	routes := map[string]echo.HandlerFunc{"PostStats": statsController.PostStats}
	handler, castOk := statsHandler.Handler(statsPort, routes).(*echo.Echo)

	if !castOk {
		handler.Logger.Fatal("Could not start server")
	}

	fmt.Println("✅  Stats server started on port", strconv.Itoa(statsPort))
	fmt.Print(noCursor)

	handler.Logger.Fatal(gracehttp.Serve(handler.Server))
}

func getPort(env string, defaultPort int) int {
	port, portErr := strconv.Atoi(os.Getenv(env))

	if portErr != nil {
		return defaultPort
	}

	return port
}
<|endoftext|>


<commit_before>/*
Package granitic provides methods for starting an instance of Granitic.
*/
package granitic

import (
	"github.com/graniticio/granitic/config"
	"github.com/graniticio/granitic/facility"
	"github.com/graniticio/granitic/instance"
	"github.com/graniticio/granitic/ioc"
	"github.com/graniticio/granitic/logging"
	"os"
	"os/signal"
	"runtime"
	"syscall"
	"time"
)

const (
	initiatorComponentName string = instance.FrameworkPrefix + "Init"
	systemPath                    = "System"
)

func StartGranitic(customComponents *ioc.ProtoComponents) {
	i := new(initiator)

	is := config.InitialSettingsFromEnvironment()

	i.Start(customComponents, is)
}

type initiator struct {
	logger logging.Logger
}

func (i *initiator) Start(customComponents *ioc.ProtoComponents, is *config.InitialSettings) {

	container := i.buildContainer(customComponents, is)
	customComponents.Clear()

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	signal.Notify(c, syscall.SIGTERM)

	go func() {
		<-c
		i.shutdown(container)
		instance.ExitNormal()
	}()

	for {
		time.Sleep(10 * time.Second)
	}
}

// Creates and populate a Granitic IoC container using the user components and configuration files provided
func (i *initiator) buildContainer(ac *ioc.ProtoComponents, is *config.InitialSettings) *ioc.ComponentContainer {

	//Bootstrap the logging framework
	frameworkLoggingManager, logManageProto := facility.BootstrapFrameworkLogging(is.FrameworkLogLevel)
	i.logger = frameworkLoggingManager.CreateLogger(initiatorComponentName)

	l := i.logger
	l.LogInfof("Starting components")

	//Merge all configuration files and create a container
	ca := i.createConfigAccessor(is.Configuration, frameworkLoggingManager)

	//Load system settings from config
	ss := i.loadSystemsSettings(ca)

	//Create the IoC container
	cc := ioc.NewComponentContainer(frameworkLoggingManager, ca, ss)
	cc.AddProto(logManageProto)

	//Assign an identity to this instance of the application
	i.createInstanceIdentifier(is, cc)

	//Register user components with container
	cc.AddProtos(ac.Components)
	cc.AddModifiers(ac.FrameworkDependencies)

	//Instantiate those facilities required by user and register as components in container
	fi := facility.NewFacilitiesInitialisor(cc, frameworkLoggingManager)

	err := fi.Initialise(ca)
	i.shutdownIfError(err, cc)

	//Inject configuration and dependencies into all components
	err = cc.Populate()
	i.shutdownIfError(err, cc)

	//Proto components no longer needed
	if ss.FlushMergedConfig {
		ca.Flush()
	}

	if ss.GCAfterConfigure {
		runtime.GC()
	}

	//Start all startable components
	err = cc.Lifecycle.StartAll()
	i.shutdownIfError(err, cc)

	elapsed := time.Since(is.StartTime)
	l.LogInfof("Ready (startup time %s)", elapsed)

	return cc
}

func (i *initiator) createInstanceIdentifier(is *config.InitialSettings, cc *ioc.ComponentContainer) {
	id := is.InstanceID

	if id != "" {
		ii := new(instance.InstanceIdentifier)
		ii.ID = id
		cc.WrapAndAddProto(instance.InstanceIDComponent, ii)

		iidd := new(facility.InstanceIDDecorator)
		iidd.InstanceID = ii
		cc.WrapAndAddProto(facility.InstanceIDDecoratorName, iidd)

		i.logger.LogInfof("Instance ID: %s", id)
	}

}

// Cleanly stop the container and any running components in the event of an error
// during startup.
func (i *initiator) shutdownIfError(err error, cc *ioc.ComponentContainer) {

	if err != nil {
		i.logger.LogFatalf(err.Error())
		i.shutdown(cc)
		instance.ExitError()
	}

}

// Log that the container is stopping and let the container stop its
// components gracefully
func (i *initiator) shutdown(cc *ioc.ComponentContainer) {
	i.logger.LogInfof("Shutting down (system signal)")

	cc.Lifecycle.StopAll()
}

// Merge together all of the local and remote JSON configuration files and wrap them in a *config.ConfigAccessor
// which allows programmatic access to the merged config.
func (i *initiator) createConfigAccessor(configPaths []string, flm *logging.ComponentLoggerManager) *config.ConfigAccessor {

	i.logConfigLocations(configPaths)

	fl := flm.CreateLogger(config.ConfigAccessorComponentName)

	jm := config.NewJSONMerger(flm)

	mergedJson, err := jm.LoadAndMergeConfig(configPaths)

	if err != nil {
		i.logger.LogFatalf(err.Error())
		instance.ExitError()
	}

	return &config.ConfigAccessor{mergedJson, fl}
}

// Record the files and URLs used to create a merged configuration (in the order in which they will be merged)
func (i *initiator) logConfigLocations(configPaths []string) {
	if i.logger.IsLevelEnabled(logging.Debug) {

		i.logger.LogDebugf("Loading configuration from: ")

		for _, fileName := range configPaths {
			i.logger.LogDebugf(fileName)
		}
	}
}

// Load system settings covering memory management and start/stop behaviour from configuration
func (i *initiator) loadSystemsSettings(ca *config.ConfigAccessor) *instance.System {

	s := new(instance.System)
	l := i.logger

	if ca.PathExists(systemPath) {

		if err := ca.Populate(systemPath, s); err != nil {
			l.LogFatalf("Problem loading system settings from config: " + err.Error())
			instance.ExitError()
		}

	} else {
		l.LogFatalf("Cannot find path %s in configuration.", systemPath)
		instance.ExitError()
	}

	return s
}
<commit_msg>Godoc<commit_after>/*
Package granitic provides methods for configuring and starting a Granitic application.

This package provides entry point functions for your application to hand control over to Granitic. Typically your application
will have a single, minimal file in its main package similar to:

	package main

	import "github.com/graniticio/granitic"
	import "github.com/yourUser/yourPackage/bindings"

	func main() {
		granitic.StartGranitic(bindings.Components())
	}

You can build a skeleton Granitic application by running the grnc-project tool, which will generate a main file, empty
configuration file and empty component definition file. The uses and syntax of these files are outside of the scope of
a GoDoc page, but are described in detail at http://granitic.io/1.0/ref/components and http://granitic.io/1.0/ref/config

A Granitic application needs two things to start:

1. A list of components to host in its IoC container.

2. One or more JSON configuration files containing environment-specific settings for your application (passwords, hostnames etc.)

The components in this example are in defined in a file called bindings.go which was generated by running the grnc-bind command
against a JSON component definition file. Refer to the documentation for grnc-bind for more information on this process.

Folders and files containing configuration are by default expected to be stored in

	resource/config

This folder can contain any number of files or sub-directories. This location can be overridden by using the -c argument
when starting your application from the command line. This argument is expected to be a comma separated list of file paths,
directories or HTTP URI to JSON files or any mixture of the above.

As you may have concluded, when starting your application from the command, Granitic takes control of processing command line arguments. By
default your application will support the following arguments.

	-c A comma separated list of files, directories or HTTP URIs in any combination (default resource/config)
	-l The level of messages that will be logged by the framework while bootstrapping (before logging configuration is loaded; default INFO)
	-i An optional string that can be used to uniquely identify this instance of your application

If your application needs to perform command line processing and you want to prevent Granitic from attempting to parse command line arguments,
you should start Granitic using the alternative:

	StartGraniticWithSettings(cs *ioc.ProtoComponents, is *config.InitialSettings)

where you are expected to programatically define the initial settings.

*/
package granitic

import (
	"github.com/graniticio/granitic/config"
	"github.com/graniticio/granitic/facility"
	"github.com/graniticio/granitic/instance"
	"github.com/graniticio/granitic/ioc"
	"github.com/graniticio/granitic/logging"
	"os"
	"os/signal"
	"runtime"
	"syscall"
	"time"
)

const (
	initiatorComponentName string = instance.FrameworkPrefix + "Init"
	systemPath                    = "System"
)

// StartGranitic starts the IoC container and populates it with the supplied list of prototype components. Any settings
// required during the initial startup of the container are expected to be provided via command line arguments (see
// this page's header for more details). This function will run until the application is halted by an interrupt (ctrl+c) or
// a runtime control shutdown command.
func StartGranitic(cs *ioc.ProtoComponents) {

	is := config.InitialSettingsFromEnvironment()

	StartGraniticWithSettings(cs, is)
}

// StartGraniticWithSettings starts the IoC container and populates it with the supplied list of prototype components and using the
// provided intial settings. This function will run until the application is halted by an interrupt (ctrl+c) or
// a runtime control shutdown command.
func StartGraniticWithSettings(cs *ioc.ProtoComponents, is *config.InitialSettings) {
	i := new(initiator)
	i.Start(cs, is)
}

type initiator struct {
	logger logging.Logger
}

func (i *initiator) Start(customComponents *ioc.ProtoComponents, is *config.InitialSettings) {

	container := i.buildContainer(customComponents, is)
	customComponents.Clear()

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	signal.Notify(c, syscall.SIGTERM)

	go func() {
		<-c
		i.shutdown(container)
		instance.ExitNormal()
	}()

	for {
		time.Sleep(10 * time.Second)
	}
}

// Creates and populate a Granitic IoC container using the user components and configuration files provided
func (i *initiator) buildContainer(ac *ioc.ProtoComponents, is *config.InitialSettings) *ioc.ComponentContainer {

	//Bootstrap the logging framework
	frameworkLoggingManager, logManageProto := facility.BootstrapFrameworkLogging(is.FrameworkLogLevel)
	i.logger = frameworkLoggingManager.CreateLogger(initiatorComponentName)

	l := i.logger
	l.LogInfof("Starting components")

	//Merge all configuration files and create a container
	ca := i.createConfigAccessor(is.Configuration, frameworkLoggingManager)

	//Load system settings from config
	ss := i.loadSystemsSettings(ca)

	//Create the IoC container
	cc := ioc.NewComponentContainer(frameworkLoggingManager, ca, ss)
	cc.AddProto(logManageProto)

	//Assign an identity to this instance of the application
	i.createInstanceIdentifier(is, cc)

	//Register user components with container
	cc.AddProtos(ac.Components)
	cc.AddModifiers(ac.FrameworkDependencies)

	//Instantiate those facilities required by user and register as components in container
	fi := facility.NewFacilitiesInitialisor(cc, frameworkLoggingManager)

	err := fi.Initialise(ca)
	i.shutdownIfError(err, cc)

	//Inject configuration and dependencies into all components
	err = cc.Populate()
	i.shutdownIfError(err, cc)

	//Proto components no longer needed
	if ss.FlushMergedConfig {
		ca.Flush()
	}

	if ss.GCAfterConfigure {
		runtime.GC()
	}

	//Start all startable components
	err = cc.Lifecycle.StartAll()
	i.shutdownIfError(err, cc)

	elapsed := time.Since(is.StartTime)
	l.LogInfof("Ready (startup time %s)", elapsed)

	return cc
}

func (i *initiator) createInstanceIdentifier(is *config.InitialSettings, cc *ioc.ComponentContainer) {
	id := is.InstanceID

	if id != "" {
		ii := new(instance.InstanceIdentifier)
		ii.ID = id
		cc.WrapAndAddProto(instance.InstanceIDComponent, ii)

		iidd := new(facility.InstanceIDDecorator)
		iidd.InstanceID = ii
		cc.WrapAndAddProto(facility.InstanceIDDecoratorName, iidd)

		i.logger.LogInfof("Instance ID: %s", id)
	}

}

// Cleanly stop the container and any running components in the event of an error
// during startup.
func (i *initiator) shutdownIfError(err error, cc *ioc.ComponentContainer) {

	if err != nil {
		i.logger.LogFatalf(err.Error())
		i.shutdown(cc)
		instance.ExitError()
	}

}

// Log that the container is stopping and let the container stop its
// components gracefully
func (i *initiator) shutdown(cc *ioc.ComponentContainer) {
	i.logger.LogInfof("Shutting down (system signal)")

	cc.Lifecycle.StopAll()
}

// Merge together all of the local and remote JSON configuration files and wrap them in a *config.ConfigAccessor
// which allows programmatic access to the merged config.
func (i *initiator) createConfigAccessor(configPaths []string, flm *logging.ComponentLoggerManager) *config.ConfigAccessor {

	i.logConfigLocations(configPaths)

	fl := flm.CreateLogger(config.ConfigAccessorComponentName)

	jm := config.NewJSONMerger(flm)

	mergedJson, err := jm.LoadAndMergeConfig(configPaths)

	if err != nil {
		i.logger.LogFatalf(err.Error())
		instance.ExitError()
	}

	return &config.ConfigAccessor{mergedJson, fl}
}

// Record the files and URLs used to create a merged configuration (in the order in which they will be merged)
func (i *initiator) logConfigLocations(configPaths []string) {
	if i.logger.IsLevelEnabled(logging.Debug) {

		i.logger.LogDebugf("Loading configuration from: ")

		for _, fileName := range configPaths {
			i.logger.LogDebugf(fileName)
		}
	}
}

// Load system settings covering memory management and start/stop behaviour from configuration
func (i *initiator) loadSystemsSettings(ca *config.ConfigAccessor) *instance.System {

	s := new(instance.System)
	l := i.logger

	if ca.PathExists(systemPath) {

		if err := ca.Populate(systemPath, s); err != nil {
			l.LogFatalf("Problem loading system settings from config: " + err.Error())
			instance.ExitError()
		}

	} else {
		l.LogFatalf("Cannot find path %s in configuration.", systemPath)
		instance.ExitError()
	}

	return s
}
<|endoftext|>


<commit_before>package agent

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"strings"
	"time"

	"github.com/ActiveState/tail"
	"github.com/tutumcloud/tutum-agent/utils"
)

type TunnelPatchForm struct {
	Tunnel  string `json:"tunnel"`
	Version string `json:"agent_version"`
}

func NatTunnel(url, ngrokPath, ngrokLogPath, ngrokConfPath string) {
	if !utils.FileExist(ngrokPath) {
		Logger.Printf("Cannot find ngrok binary(%s), skipping NAT tunnel\n", ngrokPath)
		return
	}

	if !isNodeNated() {
		return
	}

	updateNgrokHost(url)
	createNgrokConfFile(ngrokConfPath)

	var cmd *exec.Cmd
	if *FlagNgrokToken != "" {
		Logger.Println("About to tunnel to public ngrok service")
		cmd = exec.Command(ngrokPath,
			"-log", "stdout",
			"-authtoken", *FlagNgrokToken,
			"-proto", "tcp",
			DockerHostPort)
	} else {
		Logger.Println("About to tunnel to private ngrok service")
		if !utils.FileExist(ngrokConfPath) {
			Logger.Println("Cannot find ngrok conf, skipping NAT tunnel")
			return
		}
		cmd = exec.Command(ngrokPath,
			"-config", ngrokConfPath,
			"-log", "stdout",
			"-proto", "tcp",
			DockerHostPort)
	}

	os.RemoveAll(ngrokLogPath)
	logFile, err := os.OpenFile(ngrokLogPath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		Logger.Println(err)
	} else {
		defer logFile.Close()
		cmd.Stdout = logFile
	}

	Logger.Println("Starting montoring tunnel:", cmd.Args)
	go monitorTunnels(url, ngrokLogPath)
	Logger.Println("Starting NAT tunnel:", cmd.Args)

	for {
		runGronk(cmd)
		time.Sleep(10 * time.Second)
		Logger.Println("Restarting NAT tunnel:", cmd.Args)
	}
}

func runGronk(cmd *exec.Cmd) bool {
	if err := cmd.Start(); err != nil {
		return true
	}
	cmd.Wait()
	return true
}

func monitorTunnels(url, ngrokLogPath string) {
	update, _ := tail.TailFile(ngrokLogPath, tail.Config{
		Follow: true,
		ReOpen: true})
	for line := range update.Lines {
		if strings.Contains(line.Text, "[INFO] [client] Tunnel established at") {
			terms := strings.Split(line.Text, " ")
			tunnel := terms[len(terms)-1]
			Logger.Printf("Found new tunnel:%s\n", tunnel)
			patchTunnelToTutum(url, tunnel)
		}
	}
}

func patchTunnelToTutum(url, tunnel string) {
	Logger.Println("Patching tunnel address to Tutum")
	form := TunnelPatchForm{}
	form.Version = VERSION
	form.Tunnel = tunnel
	data, err := json.Marshal(form)
	if err != nil {
		Logger.Printf("Cannot marshal the TunnelPatch form:%s\f", err)
	}

	headers := []string{"Authorization TutumAgentToken " + Conf.TutumToken,
		"Content-Type", "application/json"}
	_, err = SendRequest("PATCH", utils.JoinURL(url, Conf.TutumUUID), data, headers)
	if err != nil {
		Logger.Println("Failed to patch tunnel address to Tutum,", err.Error())
	} else {
		Logger.Println("Successfully Patched tunnel address to Tutum")
	}
}

func DownloadNgrok(url, ngrokBinPath string) {
	if utils.FileExist(ngrokBinPath) {
		Logger.Printf("Found ngrok locally(%s), skip downloading\n", ngrokBinPath)
	} else {
		Logger.Println("No ngrok binary is found locally. Starting to download ngrok...")
		downloadFile(url, ngrokBinPath, "gnrok")
	}
}

func createNgrokConfFile(ngrokConfPath string) {
	ngrokConfStr := fmt.Sprintf("server_addr: %s\ntrust_host_root_certs: false", NgrokHost)
	Logger.Printf("Creating ngrok config file in %s ...\n", ngrokConfPath)
	if err := ioutil.WriteFile(ngrokConfPath, []byte(ngrokConfStr), 0666); err != nil {
		Logger.Println("Cannot create ngrok config file:", err.Error())
	}
}

func updateNgrokHost(url string) {
	if NgrokHost != "" {
		return
	}

	headers := []string{"Authorization TutumAgentToken " + Conf.TutumToken,
		"Content-Type application/json"}
	body, err := SendRequest("GET", utils.JoinURL(url, Conf.TutumUUID), nil, headers)
	if err != nil {
		Logger.Printf("Get registration info error, %s\n", err.Error())
	} else {
		var form RegGetForm
		if err = json.Unmarshal(body, &form); err != nil {
			Logger.Println("Cannot unmarshal the response, ", err.Error())
		} else {
			if form.NgrokHost != "" {
				NgrokHost = form.NgrokHost
				Logger.Println("Set ngrok server address to", NgrokHost)
			}
		}
	}
}

func isNodeNated() bool {
	counter := 0
	for {
		if counter > 10 {
			break
		}
		if DockerProcess == nil {
			time.Sleep(2 * time.Second)
			counter += 1
		} else {
			break
		}
	}
	Logger.Printf("Testing if port %s is publicly reachable ...\n", DockerHostPort)
	commandStr := fmt.Sprintf("nc %s %s < /dev/null", Conf.CertCommonName, DockerHostPort)
	Logger.Println(commandStr)
	command := exec.Command("/bin/sh", "-c", commandStr)
	command.Start()
	if err := command.Wait(); err != nil {
		Logger.Printf("Port %s is not publicly reachable", DockerHostPort)
		return true
	} else {
		Logger.Printf("Port %s is publicly reachable, skipping NAT tunnle", DockerHostPort)
		return false
	}
}
<commit_msg>added 10 seconds timeout to nc command<commit_after>package agent

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"strings"
	"time"

	"github.com/ActiveState/tail"
	"github.com/tutumcloud/tutum-agent/utils"
)

type TunnelPatchForm struct {
	Tunnel  string `json:"tunnel"`
	Version string `json:"agent_version"`
}

func NatTunnel(url, ngrokPath, ngrokLogPath, ngrokConfPath string) {
	if !utils.FileExist(ngrokPath) {
		Logger.Printf("Cannot find ngrok binary(%s), skipping NAT tunnel\n", ngrokPath)
		return
	}

	if !isNodeNated() {
		return
	}

	updateNgrokHost(url)
	createNgrokConfFile(ngrokConfPath)

	var cmd *exec.Cmd
	if *FlagNgrokToken != "" {
		Logger.Println("About to tunnel to public ngrok service")
		cmd = exec.Command(ngrokPath,
			"-log", "stdout",
			"-authtoken", *FlagNgrokToken,
			"-proto", "tcp",
			DockerHostPort)
	} else {
		Logger.Println("About to tunnel to private ngrok service")
		if !utils.FileExist(ngrokConfPath) {
			Logger.Println("Cannot find ngrok conf, skipping NAT tunnel")
			return
		}
		cmd = exec.Command(ngrokPath,
			"-config", ngrokConfPath,
			"-log", "stdout",
			"-proto", "tcp",
			DockerHostPort)
	}

	os.RemoveAll(ngrokLogPath)
	logFile, err := os.OpenFile(ngrokLogPath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		Logger.Println(err)
	} else {
		defer logFile.Close()
		cmd.Stdout = logFile
	}

	Logger.Println("Starting montoring tunnel:", cmd.Args)
	go monitorTunnels(url, ngrokLogPath)
	Logger.Println("Starting NAT tunnel:", cmd.Args)

	for {
		runGronk(cmd)
		time.Sleep(10 * time.Second)
		Logger.Println("Restarting NAT tunnel:", cmd.Args)
	}
}

func runGronk(cmd *exec.Cmd) bool {
	if err := cmd.Start(); err != nil {
		return true
	}
	cmd.Wait()
	return true
}

func monitorTunnels(url, ngrokLogPath string) {
	update, _ := tail.TailFile(ngrokLogPath, tail.Config{
		Follow: true,
		ReOpen: true})
	for line := range update.Lines {
		if strings.Contains(line.Text, "[INFO] [client] Tunnel established at") {
			terms := strings.Split(line.Text, " ")
			tunnel := terms[len(terms)-1]
			Logger.Printf("Found new tunnel:%s\n", tunnel)
			patchTunnelToTutum(url, tunnel)
		}
	}
}

func patchTunnelToTutum(url, tunnel string) {
	Logger.Println("Patching tunnel address to Tutum")
	form := TunnelPatchForm{}
	form.Version = VERSION
	form.Tunnel = tunnel
	data, err := json.Marshal(form)
	if err != nil {
		Logger.Printf("Cannot marshal the TunnelPatch form:%s\f", err)
	}

	headers := []string{"Authorization TutumAgentToken " + Conf.TutumToken,
		"Content-Type", "application/json"}
	_, err = SendRequest("PATCH", utils.JoinURL(url, Conf.TutumUUID), data, headers)
	if err != nil {
		Logger.Println("Failed to patch tunnel address to Tutum,", err.Error())
	} else {
		Logger.Println("Successfully Patched tunnel address to Tutum")
	}
}

func DownloadNgrok(url, ngrokBinPath string) {
	if utils.FileExist(ngrokBinPath) {
		Logger.Printf("Found ngrok locally(%s), skip downloading\n", ngrokBinPath)
	} else {
		Logger.Println("No ngrok binary is found locally. Starting to download ngrok...")
		downloadFile(url, ngrokBinPath, "gnrok")
	}
}

func createNgrokConfFile(ngrokConfPath string) {
	ngrokConfStr := fmt.Sprintf("server_addr: %s\ntrust_host_root_certs: false", NgrokHost)
	Logger.Printf("Creating ngrok config file in %s ...\n", ngrokConfPath)
	if err := ioutil.WriteFile(ngrokConfPath, []byte(ngrokConfStr), 0666); err != nil {
		Logger.Println("Cannot create ngrok config file:", err.Error())
	}
}

func updateNgrokHost(url string) {
	if NgrokHost != "" {
		return
	}

	headers := []string{"Authorization TutumAgentToken " + Conf.TutumToken,
		"Content-Type application/json"}
	body, err := SendRequest("GET", utils.JoinURL(url, Conf.TutumUUID), nil, headers)
	if err != nil {
		Logger.Printf("Get registration info error, %s\n", err.Error())
	} else {
		var form RegGetForm
		if err = json.Unmarshal(body, &form); err != nil {
			Logger.Println("Cannot unmarshal the response, ", err.Error())
		} else {
			if form.NgrokHost != "" {
				NgrokHost = form.NgrokHost
				Logger.Println("Set ngrok server address to", NgrokHost)
			}
		}
	}
}

func isNodeNated() bool {
	counter := 0
	for {
		if counter > 10 {
			break
		}
		if DockerProcess == nil {
			time.Sleep(2 * time.Second)
			counter += 1
		} else {
			break
		}
	}
	Logger.Printf("Testing if port %s is publicly reachable ...\n", DockerHostPort)
	commandStr := fmt.Sprintf("nc -w 10 %s %s < /dev/null", Conf.CertCommonName, DockerHostPort)
	Logger.Println(commandStr)
	command := exec.Command("/bin/sh", "-c", commandStr)
	command.Start()
	if err := command.Wait(); err != nil {
		Logger.Printf("Port %s is not publicly reachable", DockerHostPort)
		return true
	} else {
		Logger.Printf("Port %s is publicly reachable, skipping NAT tunnle", DockerHostPort)
		return false
	}
}
<|endoftext|>


<commit_before>package kubernetes

import (
	"reflect"
	"testing"

	"github.com/rusenask/keel/types"
	"github.com/rusenask/keel/util/version"

	meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/pkg/api/v1"
	"k8s.io/client-go/pkg/apis/extensions/v1beta1"
)

func unsafeGetVersion(ver string) *types.Version {
	v, err := version.GetVersion(ver)
	if err != nil {
		panic(err)
	}
	return v
}

func TestProvider_checkVersionedDeployment(t *testing.T) {
	type fields struct {
		implementer Implementer
		events      chan *types.Event
		stop        chan struct{}
	}
	type args struct {
		newVersion *types.Version
		policy     types.PolicyType
		repo       *types.Repository
		deployment v1beta1.Deployment
	}
	tests := []struct {
		name                       string
		fields                     fields
		args                       args
		wantUpdated                v1beta1.Deployment
		wantShouldUpdateDeployment bool
		wantErr                    bool
	}{
		{
			name: "standard version bump",
			args: args{
				newVersion: unsafeGetVersion("1.1.2"),
				policy:     types.PolicyTypeAll,
				repo:       &types.Repository{Name: "gcr.io/v2-namespace/hello-world", Tag: "1.1.2"},
				deployment: v1beta1.Deployment{
					meta_v1.TypeMeta{},
					meta_v1.ObjectMeta{
						Name:        "dep-1",
						Namespace:   "xxxx",
						Annotations: map[string]string{},
						Labels:      map[string]string{types.KeelPolicyLabel: "all"},
					},
					v1beta1.DeploymentSpec{
						Template: v1.PodTemplateSpec{
							Spec: v1.PodSpec{
								Containers: []v1.Container{
									v1.Container{
										Image: "gcr.io/v2-namespace/hello-world:1.1.1",
									},
								},
							},
						},
					},
					v1beta1.DeploymentStatus{},
				},
			},
			wantUpdated: v1beta1.Deployment{
				meta_v1.TypeMeta{},
				meta_v1.ObjectMeta{
					Name:        "dep-1",
					Namespace:   "xxxx",
					Annotations: map[string]string{},
					Labels:      map[string]string{types.KeelPolicyLabel: "all"},
				},
				v1beta1.DeploymentSpec{
					Template: v1.PodTemplateSpec{
						Spec: v1.PodSpec{
							Containers: []v1.Container{
								v1.Container{
									Image: "gcr.io/v2-namespace/hello-world:1.1.2",
								},
							},
						},
					},
				},
				v1beta1.DeploymentStatus{},
			},
			wantShouldUpdateDeployment: true,
			wantErr:                    false,
		},
		{
			name: "standard ignore version bump",
			args: args{
				newVersion: unsafeGetVersion("1.1.1"),
				policy:     types.PolicyTypeAll,
				repo:       &types.Repository{Name: "gcr.io/v2-namespace/hello-world", Tag: "1.1.1"},
				deployment: v1beta1.Deployment{
					meta_v1.TypeMeta{},
					meta_v1.ObjectMeta{
						Name:        "dep-1",
						Namespace:   "xxxx",
						Annotations: map[string]string{},
						Labels:      map[string]string{types.KeelPolicyLabel: "all"},
					},
					v1beta1.DeploymentSpec{
						Template: v1.PodTemplateSpec{
							Spec: v1.PodSpec{
								Containers: []v1.Container{
									v1.Container{
										Image: "gcr.io/v2-namespace/hello-world:1.1.1",
									},
								},
							},
						},
					},
					v1beta1.DeploymentStatus{},
				},
			},
			wantUpdated: v1beta1.Deployment{
				meta_v1.TypeMeta{},
				meta_v1.ObjectMeta{
					Name:        "dep-1",
					Namespace:   "xxxx",
					Annotations: map[string]string{},
					Labels:      map[string]string{types.KeelPolicyLabel: "all"},
				},
				v1beta1.DeploymentSpec{
					Template: v1.PodTemplateSpec{
						Spec: v1.PodSpec{
							Containers: []v1.Container{
								v1.Container{
									Image: "gcr.io/v2-namespace/hello-world:1.1.1",
								},
							},
						},
					},
				},
				v1beta1.DeploymentStatus{},
			},
			wantShouldUpdateDeployment: false,
			wantErr:                    false,
		},
		{
			name: "multiple containers, version bump one",
			args: args{
				newVersion: unsafeGetVersion("1.1.2"),
				policy:     types.PolicyTypeAll,
				repo:       &types.Repository{Name: "gcr.io/v2-namespace/hello-world", Tag: "1.1.2"},
				deployment: v1beta1.Deployment{
					meta_v1.TypeMeta{},
					meta_v1.ObjectMeta{
						Name:        "dep-1",
						Namespace:   "xxxx",
						Annotations: map[string]string{},
						Labels:      map[string]string{types.KeelPolicyLabel: "all"},
					},
					v1beta1.DeploymentSpec{
						Template: v1.PodTemplateSpec{
							Spec: v1.PodSpec{
								Containers: []v1.Container{
									v1.Container{
										Image: "gcr.io/v2-namespace/hello-world:1.1.1",
									},
									v1.Container{
										Image: "yo-world:1.1.1",
									},
								},
							},
						},
					},
					v1beta1.DeploymentStatus{},
				},
			},
			wantUpdated: v1beta1.Deployment{
				meta_v1.TypeMeta{},
				meta_v1.ObjectMeta{
					Name:        "dep-1",
					Namespace:   "xxxx",
					Annotations: map[string]string{},
					Labels:      map[string]string{types.KeelPolicyLabel: "all"},
				},
				v1beta1.DeploymentSpec{
					Template: v1.PodTemplateSpec{
						Spec: v1.PodSpec{
							Containers: []v1.Container{
								v1.Container{
									Image: "gcr.io/v2-namespace/hello-world:1.1.2",
								},
								v1.Container{
									Image: "yo-world:1.1.1",
								},
							},
						},
					},
				},
				v1beta1.DeploymentStatus{},
			},
			wantShouldUpdateDeployment: true,
			wantErr:                    false,
		},
		{
			name: "force update untagged container",
			args: args{
				newVersion: unsafeGetVersion("1.1.2"),
				policy:     types.PolicyTypeForce,
				repo:       &types.Repository{Name: "gcr.io/v2-namespace/hello-world", Tag: "1.1.2"},
				deployment: v1beta1.Deployment{
					meta_v1.TypeMeta{},
					meta_v1.ObjectMeta{
						Name:        "dep-1",
						Namespace:   "xxxx",
						Annotations: map[string]string{},
						Labels:      map[string]string{types.KeelPolicyLabel: "force"},
					},
					v1beta1.DeploymentSpec{
						Template: v1.PodTemplateSpec{
							Spec: v1.PodSpec{
								Containers: []v1.Container{
									v1.Container{
										Image: "gcr.io/v2-namespace/hello-world:latest",
									},
									v1.Container{
										Image: "yo-world:1.1.1",
									},
								},
							},
						},
					},
					v1beta1.DeploymentStatus{},
				},
			},
			wantUpdated: v1beta1.Deployment{
				meta_v1.TypeMeta{},
				meta_v1.ObjectMeta{
					Name:        "dep-1",
					Namespace:   "xxxx",
					Annotations: map[string]string{forceUpdateImageAnnotation: "gcr.io/v2-namespace/hello-world:1.1.2"},
					Labels:      map[string]string{types.KeelPolicyLabel: "force"},
				},
				v1beta1.DeploymentSpec{
					Template: v1.PodTemplateSpec{
						Spec: v1.PodSpec{
							Containers: []v1.Container{
								v1.Container{
									Image: "gcr.io/v2-namespace/hello-world:1.1.2",
								},
								v1.Container{
									Image: "yo-world:1.1.1",
								},
							},
						},
					},
				},
				v1beta1.DeploymentStatus{},
			},
			wantShouldUpdateDeployment: true,
			wantErr:                    false,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			p := &Provider{
				implementer: tt.fields.implementer,
				events:      tt.fields.events,
				stop:        tt.fields.stop,
			}
			gotUpdated, gotShouldUpdateDeployment, err := p.checkVersionedDeployment(tt.args.newVersion, tt.args.policy, tt.args.repo, tt.args.deployment)
			if (err != nil) != tt.wantErr {
				t.Errorf("Provider.checkVersionedDeployment() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if !reflect.DeepEqual(gotUpdated, tt.wantUpdated) {
				t.Errorf("Provider.checkVersionedDeployment() gotUpdated = %v, want %v", gotUpdated, tt.wantUpdated)
			}
			if gotShouldUpdateDeployment != tt.wantShouldUpdateDeployment {
				t.Errorf("Provider.checkVersionedDeployment() gotShouldUpdateDeployment = %v, want %v", gotShouldUpdateDeployment, tt.wantShouldUpdateDeployment)
			}
		})
	}
}

func TestProvider_checkVersionedDeployment(t *testing.T) {
	type fields struct {
		implementer     Implementer
		sender          notification.Sender
		approvalManager approvals.Manager
		events          chan *types.Event
		stop            chan struct{}
	}
	type args struct {
		newVersion *types.Version
		policy     types.PolicyType
		repo       *types.Repository
		deployment v1beta1.Deployment
	}
	tests := []struct {
		name                       string
		fields                     fields
		args                       args
		wantUpdatePlan             *UpdatePlan
		wantShouldUpdateDeployment bool
		wantErr                    bool
	}{
		{
			name: "standard version bump",
			args: args{
				newVersion: unsafeGetVersion("1.1.2"),
				policy:     types.PolicyTypeAll,
				repo:       &types.Repository{Name: "gcr.io/v2-namespace/hello-world", Tag: "1.1.2"},
				deployment: v1beta1.Deployment{
					meta_v1.TypeMeta{},
					meta_v1.ObjectMeta{
						Name:        "dep-1",
						Namespace:   "xxxx",
						Annotations: map[string]string{},
						Labels:      map[string]string{types.KeelPolicyLabel: "all"},
					},
					v1beta1.DeploymentSpec{
						Template: v1.PodTemplateSpec{
							Spec: v1.PodSpec{
								Containers: []v1.Container{
									v1.Container{
										Image: "gcr.io/v2-namespace/hello-world:1.1.1",
									},
								},
							},
						},
					},
					v1beta1.DeploymentStatus{},
				},
			},
			wantUpdatePlan: &UpdatePlan{
				Deployment: v1beta1.Deployment{
					meta_v1.TypeMeta{},
					meta_v1.ObjectMeta{
						Name:        "dep-1",
						Namespace:   "xxxx",
						Annotations: map[string]string{},
						Labels:      map[string]string{types.KeelPolicyLabel: "all"},
					},
					v1beta1.DeploymentSpec{
						Template: v1.PodTemplateSpec{
							Spec: v1.PodSpec{
								Containers: []v1.Container{
									v1.Container{
										Image: "gcr.io/v2-namespace/hello-world:1.1.2",
									},
								},
							},
						},
					},
					v1beta1.DeploymentStatus{},
				},
				NewVersion:     "1.1.2",
				CurrentVersion: "1.1.1",
			},
			wantShouldUpdateDeployment: true,
			wantErr:                    false,
		},
		{
			name: "standard ignore version bump",
			args: args{
				newVersion: unsafeGetVersion("1.1.1"),
				policy:     types.PolicyTypeAll,
				repo:       &types.Repository{Name: "gcr.io/v2-namespace/hello-world", Tag: "1.1.1"},
				deployment: v1beta1.Deployment{
					meta_v1.TypeMeta{},
					meta_v1.ObjectMeta{
						Name:        "dep-1",
						Namespace:   "xxxx",
						Annotations: map[string]string{},
						Labels:      map[string]string{types.KeelPolicyLabel: "all"},
					},
					v1beta1.DeploymentSpec{
						Template: v1.PodTemplateSpec{
							Spec: v1.PodSpec{
								Containers: []v1.Container{
									v1.Container{
										Image: "gcr.io/v2-namespace/hello-world:1.1.1",
									},
								},
							},
						},
					},
					v1beta1.DeploymentStatus{},
				},
			},
			wantUpdatePlan: &UpdatePlan{
				Deployment:     v1beta1.Deployment{},
				NewVersion:     "",
				CurrentVersion: "",
			},
			wantShouldUpdateDeployment: false,
			wantErr:                    false,
		},
		{
			name: "multiple containers, version bump one",
			args: args{
				newVersion: unsafeGetVersion("1.1.2"),
				policy:     types.PolicyTypeAll,
				repo:       &types.Repository{Name: "gcr.io/v2-namespace/hello-world", Tag: "1.1.2"},
				deployment: v1beta1.Deployment{
					meta_v1.TypeMeta{},
					meta_v1.ObjectMeta{
						Name:        "dep-1",
						Namespace:   "xxxx",
						Annotations: map[string]string{},
						Labels:      map[string]string{types.KeelPolicyLabel: "all"},
					},
					v1beta1.DeploymentSpec{
						Template: v1.PodTemplateSpec{
							Spec: v1.PodSpec{
								Containers: []v1.Container{
									v1.Container{
										Image: "gcr.io/v2-namespace/hello-world:1.1.1",
									},
									v1.Container{
										Image: "yo-world:1.1.1",
									},
								},
							},
						},
					},
					v1beta1.DeploymentStatus{},
				},
			},
			wantUpdatePlan: &UpdatePlan{
				Deployment: v1beta1.Deployment{
					meta_v1.TypeMeta{},
					meta_v1.ObjectMeta{
						Name:        "dep-1",
						Namespace:   "xxxx",
						Annotations: map[string]string{},
						Labels:      map[string]string{types.KeelPolicyLabel: "all"},
					},
					v1beta1.DeploymentSpec{
						Template: v1.PodTemplateSpec{
							Spec: v1.PodSpec{
								Containers: []v1.Container{
									v1.Container{
										Image: "gcr.io/v2-namespace/hello-world:1.1.2",
									},
									v1.Container{
										Image: "yo-world:1.1.1",
									},
								},
							},
						},
					},
					v1beta1.DeploymentStatus{},
				},
				NewVersion:     "1.1.2",
				CurrentVersion: "1.1.1",
			},
			wantShouldUpdateDeployment: true,
			wantErr:                    false,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			p := &Provider{
				implementer:     tt.fields.implementer,
				sender:          tt.fields.sender,
				approvalManager: tt.fields.approvalManager,
				events:          tt.fields.events,
				stop:            tt.fields.stop,
			}
			gotUpdatePlan, gotShouldUpdateDeployment, err := p.checkVersionedDeployment(tt.args.newVersion, tt.args.policy, tt.args.repo, tt.args.deployment)
			if (err != nil) != tt.wantErr {
				t.Errorf("Provider.checkVersionedDeployment() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if !reflect.DeepEqual(gotUpdatePlan, tt.wantUpdatePlan) {
				t.Errorf("Provider.checkVersionedDeployment() gotUpdatePlan = %v, want %v", gotUpdatePlan, tt.wantUpdatePlan)
			}
			if gotShouldUpdateDeployment != tt.wantShouldUpdateDeployment {
				t.Errorf("Provider.checkVersionedDeployment() gotShouldUpdateDeployment = %v, want %v", gotShouldUpdateDeployment, tt.wantShouldUpdateDeployment)
			}
		})
	}
}
<commit_msg>updating tests to expect for plan<commit_after>package kubernetes

import (
	"reflect"
	"testing"

	"github.com/rusenask/keel/approvals"
	"github.com/rusenask/keel/extension/notification"
	"github.com/rusenask/keel/types"
	"github.com/rusenask/keel/util/version"

	meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"

	"k8s.io/client-go/pkg/api/v1"
	"k8s.io/client-go/pkg/apis/extensions/v1beta1"
)

func unsafeGetVersion(ver string) *types.Version {
	v, err := version.GetVersion(ver)
	if err != nil {
		panic(err)
	}
	return v
}

func TestProvider_checkVersionedDeployment(t *testing.T) {
	type fields struct {
		implementer     Implementer
		sender          notification.Sender
		approvalManager approvals.Manager
		events          chan *types.Event
		stop            chan struct{}
	}
	type args struct {
		newVersion *types.Version
		policy     types.PolicyType
		repo       *types.Repository
		deployment v1beta1.Deployment
	}
	tests := []struct {
		name                       string
		fields                     fields
		args                       args
		wantUpdatePlan             *UpdatePlan
		wantShouldUpdateDeployment bool
		wantErr                    bool
	}{
		{
			name: "standard version bump",
			args: args{
				newVersion: unsafeGetVersion("1.1.2"),
				policy:     types.PolicyTypeAll,
				repo:       &types.Repository{Name: "gcr.io/v2-namespace/hello-world", Tag: "1.1.2"},
				deployment: v1beta1.Deployment{
					meta_v1.TypeMeta{},
					meta_v1.ObjectMeta{
						Name:        "dep-1",
						Namespace:   "xxxx",
						Annotations: map[string]string{},
						Labels:      map[string]string{types.KeelPolicyLabel: "all"},
					},
					v1beta1.DeploymentSpec{
						Template: v1.PodTemplateSpec{
							Spec: v1.PodSpec{
								Containers: []v1.Container{
									v1.Container{
										Image: "gcr.io/v2-namespace/hello-world:1.1.1",
									},
								},
							},
						},
					},
					v1beta1.DeploymentStatus{},
				},
			},
			wantUpdatePlan: &UpdatePlan{
				Deployment: v1beta1.Deployment{
					meta_v1.TypeMeta{},
					meta_v1.ObjectMeta{
						Name:        "dep-1",
						Namespace:   "xxxx",
						Annotations: map[string]string{},
						Labels:      map[string]string{types.KeelPolicyLabel: "all"},
					},
					v1beta1.DeploymentSpec{
						Template: v1.PodTemplateSpec{
							Spec: v1.PodSpec{
								Containers: []v1.Container{
									v1.Container{
										Image: "gcr.io/v2-namespace/hello-world:1.1.2",
									},
								},
							},
						},
					},
					v1beta1.DeploymentStatus{},
				},
				NewVersion:     "1.1.2",
				CurrentVersion: "1.1.1",
			},
			wantShouldUpdateDeployment: true,
			wantErr:                    false,
		},
		{
			name: "standard ignore version bump",
			args: args{
				newVersion: unsafeGetVersion("1.1.1"),
				policy:     types.PolicyTypeAll,
				repo:       &types.Repository{Name: "gcr.io/v2-namespace/hello-world", Tag: "1.1.1"},
				deployment: v1beta1.Deployment{
					meta_v1.TypeMeta{},
					meta_v1.ObjectMeta{
						Name:        "dep-1",
						Namespace:   "xxxx",
						Annotations: map[string]string{},
						Labels:      map[string]string{types.KeelPolicyLabel: "all"},
					},
					v1beta1.DeploymentSpec{
						Template: v1.PodTemplateSpec{
							Spec: v1.PodSpec{
								Containers: []v1.Container{
									v1.Container{
										Image: "gcr.io/v2-namespace/hello-world:1.1.1",
									},
								},
							},
						},
					},
					v1beta1.DeploymentStatus{},
				},
			},
			wantUpdatePlan: &UpdatePlan{
				Deployment:     v1beta1.Deployment{},
				NewVersion:     "",
				CurrentVersion: "",
			},
			wantShouldUpdateDeployment: false,
			wantErr:                    false,
		},
		{
			name: "multiple containers, version bump one",
			args: args{
				newVersion: unsafeGetVersion("1.1.2"),
				policy:     types.PolicyTypeAll,
				repo:       &types.Repository{Name: "gcr.io/v2-namespace/hello-world", Tag: "1.1.2"},
				deployment: v1beta1.Deployment{
					meta_v1.TypeMeta{},
					meta_v1.ObjectMeta{
						Name:        "dep-1",
						Namespace:   "xxxx",
						Annotations: map[string]string{},
						Labels:      map[string]string{types.KeelPolicyLabel: "all"},
					},
					v1beta1.DeploymentSpec{
						Template: v1.PodTemplateSpec{
							Spec: v1.PodSpec{
								Containers: []v1.Container{
									v1.Container{
										Image: "gcr.io/v2-namespace/hello-world:1.1.1",
									},
									v1.Container{
										Image: "yo-world:1.1.1",
									},
								},
							},
						},
					},
					v1beta1.DeploymentStatus{},
				},
			},
			wantUpdatePlan: &UpdatePlan{
				Deployment: v1beta1.Deployment{
					meta_v1.TypeMeta{},
					meta_v1.ObjectMeta{
						Name:        "dep-1",
						Namespace:   "xxxx",
						Annotations: map[string]string{},
						Labels:      map[string]string{types.KeelPolicyLabel: "all"},
					},
					v1beta1.DeploymentSpec{
						Template: v1.PodTemplateSpec{
							Spec: v1.PodSpec{
								Containers: []v1.Container{
									v1.Container{
										Image: "gcr.io/v2-namespace/hello-world:1.1.2",
									},
									v1.Container{
										Image: "yo-world:1.1.1",
									},
								},
							},
						},
					},
					v1beta1.DeploymentStatus{},
				},
				NewVersion:     "1.1.2",
				CurrentVersion: "1.1.1",
			},
			wantShouldUpdateDeployment: true,
			wantErr:                    false,
		},
		{
			name: "force update untagged container",
			args: args{
				newVersion: unsafeGetVersion("1.1.2"),
				policy:     types.PolicyTypeForce,
				repo:       &types.Repository{Name: "gcr.io/v2-namespace/hello-world", Tag: "1.1.2"},
				deployment: v1beta1.Deployment{
					meta_v1.TypeMeta{},
					meta_v1.ObjectMeta{
						Name:        "dep-1",
						Namespace:   "xxxx",
						Annotations: map[string]string{},
						Labels:      map[string]string{types.KeelPolicyLabel: "force"},
					},
					v1beta1.DeploymentSpec{
						Template: v1.PodTemplateSpec{
							Spec: v1.PodSpec{
								Containers: []v1.Container{
									v1.Container{
										Image: "gcr.io/v2-namespace/hello-world:latest",
									},
									v1.Container{
										Image: "yo-world:1.1.1",
									},
								},
							},
						},
					},
					v1beta1.DeploymentStatus{},
				},
			},
			wantUpdatePlan: &UpdatePlan{
				Deployment: v1beta1.Deployment{
					meta_v1.TypeMeta{},
					meta_v1.ObjectMeta{
						Name:        "dep-1",
						Namespace:   "xxxx",
						Annotations: map[string]string{forceUpdateImageAnnotation: "gcr.io/v2-namespace/hello-world:1.1.2"},
						Labels:      map[string]string{types.KeelPolicyLabel: "force"},
					},
					v1beta1.DeploymentSpec{
						Template: v1.PodTemplateSpec{
							Spec: v1.PodSpec{
								Containers: []v1.Container{
									v1.Container{
										Image: "gcr.io/v2-namespace/hello-world:1.1.2",
									},
									v1.Container{
										Image: "yo-world:1.1.1",
									},
								},
							},
						},
					},
					v1beta1.DeploymentStatus{},
				},
				NewVersion:     "1.1.2",
				CurrentVersion: "latest",
			},
			wantShouldUpdateDeployment: true,
			wantErr:                    false,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			p := &Provider{
				implementer:     tt.fields.implementer,
				sender:          tt.fields.sender,
				approvalManager: tt.fields.approvalManager,
				events:          tt.fields.events,
				stop:            tt.fields.stop,
			}
			gotUpdatePlan, gotShouldUpdateDeployment, err := p.checkVersionedDeployment(tt.args.newVersion, tt.args.policy, tt.args.repo, tt.args.deployment)
			if (err != nil) != tt.wantErr {
				t.Errorf("Provider.checkVersionedDeployment() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if !reflect.DeepEqual(gotUpdatePlan, tt.wantUpdatePlan) {
				t.Errorf("Provider.checkVersionedDeployment() gotUpdatePlan = %v, want %v", gotUpdatePlan, tt.wantUpdatePlan)
			}
			if gotShouldUpdateDeployment != tt.wantShouldUpdateDeployment {
				t.Errorf("Provider.checkVersionedDeployment() gotShouldUpdateDeployment = %v, want %v", gotShouldUpdateDeployment, tt.wantShouldUpdateDeployment)
			}
		})
	}
}
<|endoftext|>


<commit_before>package kernels;

import (
    "math"
)
func l2Norm(v []float64) float64{
    var res float64
    for _,val := range(v) {
        res = res + val*val
    }
    return math.Sqrt(res)
}

func Epanechnikov(v []float64) float64 {
        return math.Max(1-l2Norm(v), 0)
}

func Gaussian(v []float64) float64 {
    return math.Exp(-l2Norm(v))
}

func Naive(v []float64) float64 {
    return math.Min(l2Norm(v), 1)
}
<commit_msg>corrections diverses<commit_after><|endoftext|>


<commit_before>// Copyright 2016 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package stringforwarder

import "sync"

// StringForwarder is a goroutine-safe type that pipes messages from the
// its Forward() method, sending them to callback.  The send will not be
// blocked by the callback, but will instead discard messages if there
// is an incomplete callback in progress. The number of discarded messages
// is tracked and returned when the forwarder is stopped.
type StringForwarder struct {
	mu           sync.Mutex
	cond         *sync.Cond
	current      *string
	stopped      bool
	discardCount uint64
}

// New returns a new StringForwarder that sends messages to the callback,
// function, dropping messages if the receiver has not yet consumed the
// last message.
func New(callback func(string)) *StringForwarder {
	if callback == nil {
		// Nothing to forward to, so no need to start the loop().
		// We'll just count the discardCount.
		return &StringForwarder{stopped: true}
	}
	forwarder := &StringForwarder{}
	forwarder.cond = sync.NewCond(&forwarder.mu)
	go forwarder.loop(callback)
	return forwarder
}

// Forward sends the message to be processed by the callback function,
// discarding the message if another message is currently being processed.
// The number of discarded messages is recorded for reporting by the Stop
// method.
//
// Forward is safe to call from multiple goroutines at once.
// Note that if this StringForwarder was created with a nil callback, all
// messages will be discarded.
func (f *StringForwarder) Forward(msg string) {
	f.mu.Lock()
	if f.stopped || f.current != nil {
		f.discardCount++
	} else {
		f.current = &msg
		f.cond.Signal()
	}
	f.mu.Unlock()
}

// Stop cleans up the goroutine running behind StringForwarder and returns the
// count of discarded messages. Stop is thread-safe and may be called multiple
// times - after the first time, it simply returns the current discard count.
func (f *StringForwarder) Stop() uint64 {
	var count uint64
	f.mu.Lock()
	if !f.stopped {
		f.stopped = true
		f.cond.Signal()
	}
	count = f.discardCount
	f.mu.Unlock()
	return count
}

// loop invokes forwarded messages with the given callback until stopped.
func (f *StringForwarder) loop(callback func(string)) {
	f.mu.Lock()
	defer f.mu.Unlock()
	for {
		for !f.stopped && f.current == nil {
			f.cond.Wait()
		}
		if f.stopped {
			return
		}
		f.invokeCallback(callback, *f.current)
		f.current = nil
	}
}

// invokeCallback invokes the given callback with a message,
// unlocking the forwarder's mutex for the duration of the
// callback.
func (f *StringForwarder) invokeCallback(callback func(string), msg string) {
	f.mu.Unlock()
	defer f.mu.Lock()
	callback(msg)
}
<commit_msg>util/stringforwarder: tweak exit criteria<commit_after>// Copyright 2016 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package stringforwarder

import "sync"

// StringForwarder is a goroutine-safe type that pipes messages from the
// its Forward() method, sending them to callback.  The send will not be
// blocked by the callback, but will instead discard messages if there
// is an incomplete callback in progress. The number of discarded messages
// is tracked and returned when the forwarder is stopped.
type StringForwarder struct {
	mu           sync.Mutex
	cond         *sync.Cond
	current      *string
	stopped      bool
	discardCount uint64
}

// New returns a new StringForwarder that sends messages to the callback,
// function, dropping messages if the receiver has not yet consumed the
// last message.
func New(callback func(string)) *StringForwarder {
	if callback == nil {
		// Nothing to forward to, so no need to start the loop().
		// We'll just count the discardCount.
		return &StringForwarder{stopped: true}
	}
	forwarder := &StringForwarder{}
	forwarder.cond = sync.NewCond(&forwarder.mu)
	go forwarder.loop(callback)
	return forwarder
}

// Forward sends the message to be processed by the callback function,
// discarding the message if another message is currently being processed.
// The number of discarded messages is recorded for reporting by the Stop
// method.
//
// Forward is safe to call from multiple goroutines at once.
// Note that if this StringForwarder was created with a nil callback, all
// messages will be discarded.
func (f *StringForwarder) Forward(msg string) {
	f.mu.Lock()
	if f.stopped || f.current != nil {
		f.discardCount++
	} else {
		f.current = &msg
		f.cond.Signal()
	}
	f.mu.Unlock()
}

// Stop cleans up the goroutine running behind StringForwarder and returns the
// count of discarded messages. Stop is thread-safe and may be called multiple
// times - after the first time, it simply returns the current discard count.
func (f *StringForwarder) Stop() uint64 {
	var count uint64
	f.mu.Lock()
	if !f.stopped {
		f.stopped = true
		f.cond.Signal()
	}
	count = f.discardCount
	f.mu.Unlock()
	return count
}

// loop invokes forwarded messages with the given callback until stopped.
func (f *StringForwarder) loop(callback func(string)) {
	f.mu.Lock()
	defer f.mu.Unlock()
	for {
		for !f.stopped && f.current == nil {
			f.cond.Wait()
		}
		if f.current == nil {
			return
		}
		f.invokeCallback(callback, *f.current)
		f.current = nil
	}
}

// invokeCallback invokes the given callback with a message,
// unlocking the forwarder's mutex for the duration of the
// callback.
func (f *StringForwarder) invokeCallback(callback func(string), msg string) {
	f.mu.Unlock()
	defer f.mu.Lock()
	callback(msg)
}
<|endoftext|>


<commit_before>package xen

import (
	"atman/mm"
	"atman/xen/hypercall"
	"unsafe"
)

const (
	DOMID_SELF = 0x7FF0

	grantTableMaxFrames = 4
	grantTableNrEntries = 0x1000 / unsafe.Sizeof(GrantTableEntry{})

	grantTableNrReserved = 8
)

var grantTable *GrantTable

type GrantTable struct {
	entries []GrantTableEntry

	grefs grefFreeList
}

// MapGrantTable maps Xen's shared grant table into memory
// and returns a pointer to it.
func MapGrantTable() *GrantTable {
	if grantTable == nil {
		grantTable = setupGrantTable(grantTableMaxFrames)
	}

	return grantTable
}

func setupGrantTable(nrFrames int) *GrantTable {
	grantFrames := make([]uintptr, nrFrames)

	loadGrantFrames(grantFrames)

	tablePtr := mm.MapFrames(grantFrames)
	table := (*[grantTableNrEntries]GrantTableEntry)(tablePtr)

	grefs := make(grefFreeList, 0, grantTableNrEntries)

	for i := grantTableNrReserved; i < grantTableMaxFrames; i++ {
		grefs.put(gref(i))
	}

	return &GrantTable{
		entries: table[:],
		grefs:   grefs,
	}
}

func (t *GrantTable) GrantAccess(domid uint16, frame uintptr, readOnly bool) (gref, bool) {
	gref, ok := t.grefs.get()
	if !ok {
		return gref, ok
	}

	flags := hypercall.GTF_permit_access
	if readOnly {
		flags |= hypercall.GTF_readonly
	}

	t.entries[gref].Frame = frame
	t.entries[gref].DomID = domid
	// TODO: wmb()
	t.entries[gref].Flags = uint16(flags)

	return gref, true
}

func (t *GrantTable) EndAccess(gref gref) bool {
	for {
		flags := t.entries[gref].Flags

		if flags&(hypercall.GTF_reading|hypercall.GTF_writing) != 0 {
			return false
		}

		// TODO: compareAndSwapUint16(&t.entries[gref].Flags, flags, 0)
		t.entries[gref].Flags = 0
		break
	}

	t.grefs.put(gref)
	return true
}

func loadGrantFrames(frames []uintptr) uintptr {
	setup := struct {
		DomID    uint16
		_        uint16
		NrFrames uint32
		Status   uint16
		_        [6]byte
		Frames   *uintptr
	}{
		DomID:    DOMID_SELF,
		NrFrames: uint32(len(frames)),
		Frames:   &frames[0],
	}

	return hypercall.GrantTableOp(
		hypercall.GNTTABOP_setup_table,
		unsafe.Pointer(&setup),
	)
}

// GrantTableEntry is the V2 grant table entry structure for full pages.
type GrantTableEntry struct {
	Flags uint16
	DomID uint16
	_     uint32
	Frame uintptr
}

type gref int

// grefFreeList is a free-list of grefs, where each gref
// is an index to an unused entry in the grant table.
type grefFreeList []gref

func (l *grefFreeList) get() (gref, bool) {
	s := *l
	if len(s) == 0 {
		return 0, false
	}
	gref := s[len(s)-1]
	*l = s[:len(s)-1]
	return gref, true
}

func (l *grefFreeList) put(gref gref) {
	old := *l
	*l = append(old, gref)
}
<commit_msg>atman/xen: fix grant table<commit_after>package xen

import (
	"atman/mm"
	"atman/xen/hypercall"
	"unsafe"
)

const (
	DOMID_SELF = 0x7FF0

	grantTableMaxFrames = 4
	grantTableNrEntries = grantTableMaxFrames * int(0x1000/unsafe.Sizeof(GrantTableEntry{}))

	grantTableNrReserved = 8
)

var grantTable *GrantTable

type GrantTable struct {
	entries []GrantTableEntry

	grefs grefFreeList
}

// MapGrantTable maps Xen's shared grant table into memory
// and returns a pointer to it.
func MapGrantTable() *GrantTable {
	if grantTable == nil {
		grantTable = setupGrantTable(grantTableMaxFrames)
	}

	return grantTable
}

func setupGrantTable(nrFrames int) *GrantTable {
	grantFrames := make([]uintptr, nrFrames)

	loadGrantFrames(grantFrames)

	tablePtr := mm.MapFrames(grantFrames)
	table := (*[grantTableNrEntries]GrantTableEntry)(tablePtr)

	grefs := make(grefFreeList, 0, grantTableNrEntries)

	for i := grantTableNrReserved; i < grantTableNrEntries; i++ {
		grefs.put(Gref(i))
	}

	return &GrantTable{
		entries: table[:],
		grefs:   grefs,
	}
}

func (t *GrantTable) GrantAccess(domid uint16, frame uintptr, readOnly bool) (Gref, bool) {
	gref, ok := t.grefs.get()
	if !ok {
		return gref, ok
	}

	flags := hypercall.GTF_permit_access
	if readOnly {
		flags |= hypercall.GTF_readonly
	}

	t.entries[gref].Frame = frame
	t.entries[gref].DomID = domid
	// TODO: wmb()
	t.entries[gref].Flags = uint16(flags)

	return gref, true
}

func (t *GrantTable) EndAccess(gref Gref) bool {
	for {
		flags := t.entries[gref].Flags

		if flags&(hypercall.GTF_reading|hypercall.GTF_writing) != 0 {
			return false
		}

		// TODO: compareAndSwapUint16(&t.entries[gref].Flags, flags, 0)
		t.entries[gref].Flags = 0
		break
	}

	t.grefs.put(gref)
	return true
}

func loadGrantFrames(frames []uintptr) uintptr {
	setup := struct {
		DomID    uint16
		_        uint16
		NrFrames uint32
		Status   uint16
		_        [6]byte
		Frames   *uintptr
	}{
		DomID:    DOMID_SELF,
		NrFrames: uint32(len(frames)),
		Frames:   &frames[0],
	}

	return hypercall.GrantTableOp(
		hypercall.GNTTABOP_setup_table,
		unsafe.Pointer(&setup),
	)
}

// GrantTableEntry is the V2 grant table entry structure for full pages.
type GrantTableEntry struct {
	Flags uint16
	DomID uint16
	_     uint32
	Frame uintptr
}

type Gref uint32

// grefFreeList is a free-list of grefs, where each gref
// is an index to an unused entry in the grant table.
type grefFreeList []Gref

func (l *grefFreeList) get() (Gref, bool) {
	s := *l
	if len(s) == 0 {
		return 0, false
	}
	gref := s[len(s)-1]
	*l = s[:len(s)-1]
	return gref, true
}

func (l *grefFreeList) put(gref Gref) {
	old := *l
	*l = append(old, gref)
}
<|endoftext|>


<commit_before>package l10n

var phrasesAR = map[string]string{
	"Anonymous post":                 "منشور مجهول المصدر",
	"Blogs":                          "المدونات",
	"Enter":                          "أدخل",
	"Newer":                          "الأحدث",
	"Older":                          "الأقدم",
	"Posts":                          "المنشورات",
	"Publish to...":                  "النشر إلى…",
	"Publish":                        "نشر",
	"Read more...":                   "اقرأ المزيد…",
	"This blog requires a password.": "هذه المدونة تتطلب کلمة سرية.",
	"Toggle theme":                   "تغيير القالب",
	"View posts":                     "مشاهدة المنشورات",
	"delete":                         "حذف",
	"edit":                           "تعديل",
	"move to...":                     "أنقله إلى…",
	"pin":                            "تدبيس",
	"published with write.as":  "مدعوم من write.as",
	"share modal ending":       "ارسلهه إلى صديق، شاركه عبر الويب، أو غرّده. تعلّم المزيد.",
	"share modal introduction": "كل الفيديوهات المنشورة لديها رابط سري مميز، يمكنك مشاركته. هذا هو الرابط:",
	"share modal title":        "شارك هذا المنشور",
	"share":                    "شارك",
	"unpin":                    "إلغاء التدبيس",
}
<commit_msg>Update Arabic translation<commit_after>package l10n

var phrasesAR = map[string]string{
	"Anonymous post":                 "منشور مجهول المصدر",
	"Blogs":                          "المدونات",
	"Enter":                          "أدخل",
	"Newer":                          "الأحدث",
	"Older":                          "الأقدم",
	"Posts":                          "المنشورات",
	"Publish to...":                  "النشر إلى…",
	"Publish":                        "نشر",
	"Read more...":                   "اقرأ المزيد…",
	"Subscribe":                      "اشترك",
	"This blog requires a password.": "هذه المدونة تتطلب کلمة سرية.",
	"Toggle theme":                   "تغيير القالب",
	"View posts":                     "مشاهدة المنشورات",
	"delete":                         "حذف",
	"edit":                           "تعديل",
	"email subscription prompt":      "ادخل عنوان بريدك الإلكتروني للإشتراك في التحديثات",
	"move to...":                     "أنقله إلى…",
	"pin":                            "تدبيس",
	"published with write.as":        "مدعوم من write.as",
	"share modal ending":             "ارسلهه إلى صديق، شاركه عبر الويب، أو غرّده. تعلّم المزيد.",
	"share modal introduction":       "كل الفيديوهات المنشورة لديها رابط سري مميز، يمكنك مشاركته. هذا هو الرابط:",
	"share modal title":              "شارك هذا المنشور",
	"share":                          "شارك",
	"unpin":                          "إلغاء التدبيس",
}
<|endoftext|>