<commit_before>package guid

import (
	"fmt"
	"math/rand"
	"os"
)

// GUID is a unique identifier designed to virtually guarantee non-conflict between values generated
// across a distributed system. This allows for values that are
type GUID struct {
	timeHighAndVersion      uint16
	timeMid                 uint16
	timeLow                 uint32
	clockSeqHighAndReserved uint8
	clockSeqLow             uint8
	node                    [6]byte
}

var (
	emptyGUID GUID
)

// NewGUID generates and returns a new globally unique identifier
func NewGUID() GUID {
	result, err := version4()
	if err != nil {
		panic(err) //Version 4 (psuedo-random GUID) doesn't use anything that could fail.
	}
	return result
}

// Empty returns a copy of the default and empty GUID.
func Empty() GUID {
	return emptyGUID
}

var defaultFormat = "D"
var knownFormats = map[string]string{
	"N": "%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x",
	"D": "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
	"B": "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
	"P": "(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
	"X": "{0x%08x,0x%04x,0x%04x,{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x}}",
}

// Parse instantiates a GUID from a text represention of the same GUID.
// This is the inverse function of String()
func Parse(value string) (GUID, error) {
	var guid GUID
	for _, fullFormat := range knownFormats {
		parity, err := fmt.Sscanf(
			value,
			fullFormat,
			&guid.timeLow,
			&guid.timeMid,
			&guid.timeHighAndVersion,
			&guid.clockSeqHighAndReserved,
			&guid.clockSeqLow,
			&guid.node[0],
			&guid.node[1],
			&guid.node[2],
			&guid.node[3],
			&guid.node[4],
			&guid.node[5])
		if parity == 11 && err == nil {
			return guid, err
		}
	}
	return emptyGUID, fmt.Errorf("\"%s\" is not in a recognized format", value)
}

func (guid *GUID) String() string {
	result, _ := guid.Format(defaultFormat)
	return result
}

// Format returns a text representation of a GUID that conforms to the specified format.
func (guid *GUID) Format(format string) (string, error) {
	if format == "" {
		format = defaultFormat
	}
	fullFormat, present := knownFormats[format]
	if !present {
		return "", fmt.Errorf("%s is not a recognized format string. Please choose from", format)
	}
	return fmt.Sprintf(
		fullFormat,
		guid.timeLow,
		guid.timeMid,
		guid.timeHighAndVersion,
		guid.clockSeqHighAndReserved,
		guid.clockSeqLow,
		guid.node[0],
		guid.node[1],
		guid.node[2],
		guid.node[3],
		guid.node[4],
		guid.node[5]), nil
}

// Version reads a GUID to parse which mechanism of generating GUIDS was employed.
// Values returned here are documented in rfc4122.txt.
func (guid *GUID) Version() uint {
	return uint(guid.timeHighAndVersion >> 12)
}

const (
	creationFileMode      os.FileMode = os.ModeExclusive
	creationStateFilePath string      = "foo.lock"
)

func version1() (GUID, error) {
	var retval GUID
	return retval, nil
}

func version4() (GUID, error) {
	var retval GUID
	var bits uint32

	// Randomly set all time components and version
	bits = rand.Uint32()
	retval.timeHighAndVersion |= uint16(bits >> 16)
	retval.timeMid |= uint16(bits)
	bits = rand.Uint32()
	retval.timeLow = bits
	bits = rand.Uint32()
	retval.clockSeqHighAndReserved = uint8(bits)
	retval.clockSeqLow = uint8(bits >> 8)

	//Randomly set clock-sequence, reserved, and node
	if written, err := rand.Read(retval.node[:]); !(nil == err && written == len(retval.node)) {
		retval = emptyGUID
		return retval, err
	}

	if err := retval.setVersion(4); nil != err {
		return emptyGUID, err
	}
	retval.clockSeqHighAndReserved = (retval.clockSeqHighAndReserved & 0x3f) | 0x80

	return retval, nil
}

func (guid *GUID) setVersion(version uint16) error {
	if version > 5 {
		return fmt.Errorf("While setting GUID version, unsupported version: %d", version)
	}
	guid.timeHighAndVersion = (guid.timeHighAndVersion & 0x0fff) | version<<12
	return nil
}
<commit_msg>Adding format consts for easier access.<commit_after>package guid

import (
	"fmt"
	"math/rand"
	"os"
)

// GUID is a unique identifier designed to virtually guarantee non-conflict between values generated
// across a distributed system.
type GUID struct {
	timeHighAndVersion      uint16
	timeMid                 uint16
	timeLow                 uint32
	clockSeqHighAndReserved uint8
	clockSeqLow             uint8
	node                    [6]byte
}

var (
	emptyGUID GUID
)

// NewGUID generates and returns a new globally unique identifier
func NewGUID() GUID {
	result, err := version4()
	if err != nil {
		panic(err) //Version 4 (psuedo-random GUID) doesn't use anything that could fail.
	}
	return result
}

// Empty returns a copy of the default and empty GUID.
func Empty() GUID {
	return emptyGUID
}

// These constants define the possible string formats available via this implementation of Guid.
const (
	FormatB       string = "B"
	FormatD       string = "D"
	FormatN       string = "N"
	FormatP       string = "P"
	FormatX       string = "X"
	FormatDefault string = FormatD
)

var knownFormats = map[string]string{
	FormatN: "%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x",
	FormatD: "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
	FormatB: "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
	FormatP: "(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
	FormatX: "{0x%08x,0x%04x,0x%04x,{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x}}",
}

// Parse instantiates a GUID from a text represention of the same GUID.
// This is the inverse function of String()
func Parse(value string) (GUID, error) {
	var guid GUID
	for _, fullFormat := range knownFormats {
		parity, err := fmt.Sscanf(
			value,
			fullFormat,
			&guid.timeLow,
			&guid.timeMid,
			&guid.timeHighAndVersion,
			&guid.clockSeqHighAndReserved,
			&guid.clockSeqLow,
			&guid.node[0],
			&guid.node[1],
			&guid.node[2],
			&guid.node[3],
			&guid.node[4],
			&guid.node[5])
		if parity == 11 && err == nil {
			return guid, err
		}
	}
	return emptyGUID, fmt.Errorf("\"%s\" is not in a recognized format", value)
}

func (guid *GUID) String() string {
	result, _ := guid.Format(FormatDefault)
	return result
}

// Format returns a text representation of a GUID that conforms to the specified format.
func (guid *GUID) Format(format string) (string, error) {
	if format == "" {
		format = FormatDefault
	}
	fullFormat, present := knownFormats[format]
	if !present {
		return "", fmt.Errorf("%s is not a recognized format string. Please choose from", format)
	}
	return fmt.Sprintf(
		fullFormat,
		guid.timeLow,
		guid.timeMid,
		guid.timeHighAndVersion,
		guid.clockSeqHighAndReserved,
		guid.clockSeqLow,
		guid.node[0],
		guid.node[1],
		guid.node[2],
		guid.node[3],
		guid.node[4],
		guid.node[5]), nil
}

// Version reads a GUID to parse which mechanism of generating GUIDS was employed.
// Values returned here are documented in rfc4122.txt.
func (guid *GUID) Version() uint {
	return uint(guid.timeHighAndVersion >> 12)
}

const (
	creationFileMode      os.FileMode = os.ModeExclusive
	creationStateFilePath string      = "foo.lock"
)

func version1() (GUID, error) {
	var retval GUID
	return retval, nil
}

func version4() (GUID, error) {
	var retval GUID
	var bits uint32

	// Randomly set all time components and version
	bits = rand.Uint32()
	retval.timeHighAndVersion |= uint16(bits >> 16)
	retval.timeMid |= uint16(bits)
	bits = rand.Uint32()
	retval.timeLow = bits
	bits = rand.Uint32()
	retval.clockSeqHighAndReserved = uint8(bits)
	retval.clockSeqLow = uint8(bits >> 8)

	//Randomly set clock-sequence, reserved, and node
	if written, err := rand.Read(retval.node[:]); !(nil == err && written == len(retval.node)) {
		retval = emptyGUID
		return retval, err
	}

	if err := retval.setVersion(4); nil != err {
		return emptyGUID, err
	}
	retval.clockSeqHighAndReserved = (retval.clockSeqHighAndReserved & 0x3f) | 0x80

	return retval, nil
}

func (guid *GUID) setVersion(version uint16) error {
	if version > 5 {
		return fmt.Errorf("While setting GUID version, unsupported version: %d", version)
	}
	guid.timeHighAndVersion = (guid.timeHighAndVersion & 0x0fff) | version<<12
	return nil
}
<|endoftext|>


<commit_before>package tarpan

import (
	"errors"
	"log"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/soniah/gosnmp"
)

// Tarpan constants
const (
	ConcurrentProcesses = 5
)

// Exit code
const (
	ExitCodeOK = iota
	ExitCodeConfError
	ExitCodeParseFlagError
)

// SNMP constants
const (
	community = "public"
	port      = 161
	timeout   = 2
	retry     = 3
	//MaximumPDUBytes = 512
)

// JSON structure definition
type DataSet struct {
	Default Defaults `json:"defaults"`
	Targets []Target `json:"targets"`
}

type Defaults struct {
	Port      uint16 `json:"port"`
	Version   string `json:"version"`
	Community string `json:"community"`
}

type Target struct {
	Name      string `json:"name"`
	Address   string `json:"address"`
	Port      uint16 `json:"port"`
	Version   string `json:"version"`
	Community string `json:"community"`
	OIDs      []OID  `json:"oids"`
}

type OID struct {
	OID         string `json:"oid"`
	Description string `json:"description"`
}

// Tarpan result structures
type TarpanResult struct {
	Name      string    `json:"name"`
	Address   string    `json:"address"`
	Port      uint16    `json:"port"`
	Version   string    `json:"version"`
	Community string    `json:"community"`
	VarBinds  []VarBind `json:"varbinds"`
}

type VarBind struct {
	Description string         `json:"description"`
	OID         string         `json:"oid"`
	Type        gosnmp.Asn1BER `json:"type"`
	Value       interface{}    `json:"value"`
	Time        int64          `json:"time"`
}

type Tarpan interface {
	makeRequestBody()
	SetManager()
	SetParams()
	Get(params map[string]string, oids []string) ([]gosnmp.SnmpPDU, error)
	Run()
}

type TarpanManager struct {
	snmp *gosnmp.GoSNMP
}

type SnmpResult struct {
	target  Target
	results []gosnmp.SnmpPDU
	time    int64
}

type Channels struct {
	semaphoe chan int
	results  chan SnmpResult
}

func (t *TarpanManager) Get(params map[string]string,
	oids []string) ([]gosnmp.SnmpPDU, error) {
	t.SetParams(params)
	connection_err := t.snmp.Connect()
	if connection_err != nil {
		log.Fatalf("Connection error: %")
		return nil, errors.New(connection_err.Error())
	}
	result, request_err := t.snmp.Get(oids)
	if request_err != nil {
		return nil, errors.New(request_err.Error())
	}
	t.snmp.Conn.Close()

	return result.Variables, nil
}

func (t *TarpanManager) SetManager(manager *gosnmp.GoSNMP) {
	t.snmp = manager

	return
}

func (t *TarpanManager) SetParams(p map[string]string) {
	if value, ok := p["target"]; ok {
		t.snmp.Target = value
	}
	if value, ok := p["port"]; ok {
		port, _ := strconv.ParseUint(value, 10, 16)
		t.snmp.Port = uint16(port)
	} else {
		t.snmp.Port = uint16(port)
	}
	if value, ok := p["community"]; ok {
		t.snmp.Community = value
	}
	if value, ok := p["version"]; ok {
		if value == "2c" {
			t.snmp.Version = gosnmp.Version2c
		}
	}
	if value, ok := p["timeout"]; ok {
		sec, _ := strconv.Atoi(value)
		t.snmp.Timeout = time.Duration(sec) * time.Second
	} else {
		t.snmp.Timeout = time.Duration(timeout) * time.Second
	}
	if value, ok := p["retries"]; ok {
		retries, _ := strconv.Atoi(value)
		t.snmp.Retries = retries
	} else {
		t.snmp.Retries = retry

	}

	return
}

func makeRequestBody(ds *DataSet, idx int) (map[string]string, error) {
	address := ""
	err := validateIP(ds.Targets[idx].Address)
	if err == nil {
		address = ds.Targets[idx].Address
	} else {
		return map[string]string{}, err
	}
	community := ds.Targets[idx].Community
	if community == "" {
		community = ds.Default.Community
	}
	version := ds.Targets[idx].Version
	if version == "" {
		version = ds.Default.Version
	}
	port := ds.Targets[idx].Port
	if port == 0 {
		port = ds.Default.Port
	}

	request_body := map[string]string{
		"target":    address,
		"community": community,
		"version":   version,
		"port":      strconv.Itoa(int(port)),
	}

	return request_body, err
}

func makeChannel(result_buffer_length int) *Channels {
	channel := &Channels{
		semaphoe: make(chan int, ConcurrentProcesses),
		results:  make(chan SnmpResult, result_buffer_length),
	}

	return channel
}

func makeTarpanResult(c *Channels) []*TarpanResult {
	var tarpanResults []*TarpanResult
	var varbinds []VarBind
	var result SnmpResult
	length := len(c.results)
	for i := 0; i < length; i++ {
		varbinds = []VarBind{}
		result = <-c.results
		for _, val := range result.results {
			for _, o := range result.target.OIDs {
				n := strings.TrimLeft(val.Name, ".")
				if o.OID == n {
					v := VarBind{
						Description: o.Description,
						OID:         val.Name,
						Type:        val.Type,
						Value:       val.Value,
						Time:        result.time,
					}
					varbinds = append(varbinds, v)
					break
				}
			}
		}
		tr := &TarpanResult{
			Name:      result.target.Name,
			Address:   result.target.Address,
			Port:      result.target.Port,
			Version:   result.target.Version,
			Community: result.target.Community,
			VarBinds:  varbinds,
		}
		tarpanResults = append(tarpanResults, tr)
	}

	return tarpanResults
}

func Collect(dataset *DataSet) []*TarpanResult {
	var waitGroup sync.WaitGroup
	var managers []*TarpanManager
	//var tm TarpanManager
	var channels *Channels
	var oids []string

	for i := 0; i < len(dataset.Targets); i++ {
		managers = append(managers, &TarpanManager{
			snmp: &gosnmp.GoSNMP{},
		})
	}

	channels = makeChannel(len(dataset.Targets))
	for index := range dataset.Targets {

		// TODO: split oid slice according to PDU size
		oids = []string{}
		for oid_idx := range dataset.Targets[index].OIDs {
			oids = append(oids, dataset.Targets[index].OIDs[oid_idx].OID)
		}

		waitGroup.Add(1)
		go func(ds *DataSet, idx int, o []string, c *Channels) {
			defer waitGroup.Done()
			c.semaphoe <- 0
			req_body, req_body_err := makeRequestBody(ds, idx)
			if req_body_err != nil {
				log.Print(req_body_err)
				<-c.semaphoe
				return
			}
			t := time.Now()
			results, err := managers[idx].Get(req_body, o)
			if err != nil {
				log.Print(err)
				<-c.semaphoe
				waitGroup.Done()
				return
			}
			ret := SnmpResult{
				target:  ds.Targets[idx],
				results: results,
				time:    t.Unix(),
			}
			c.results <- ret
			<-c.semaphoe
		}(dataset, index, oids, channels)
	}
	waitGroup.Wait()
	tr := makeTarpanResult(channels)

	return tr
}

func Run(target string) (int, error) {
	var err error

	// Load targets
	dataset, loadErr := loadConfig(target)
	if loadErr != nil {
		return ExitCodeConfError, loadErr
	}

	// collect data
	tr := Collect(dataset)

	// output
	Write("aa", tr)

	return ExitCodeOK, err
}
<commit_msg>fixed nested for loop<commit_after>package tarpan

import (
	"errors"
	"log"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/soniah/gosnmp"
)

// Tarpan constants
const (
	ConcurrentProcesses = 5
)

// Exit code
const (
	ExitCodeOK = iota
	ExitCodeConfError
	ExitCodeParseFlagError
)

// SNMP constants
const (
	community = "public"
	port      = 161
	timeout   = 2
	retry     = 3
	//MaximumPDUBytes = 512
)

// JSON structure definition
type DataSet struct {
	Default Defaults `json:"defaults"`
	Targets []Target `json:"targets"`
}

type Defaults struct {
	Port      uint16 `json:"port"`
	Version   string `json:"version"`
	Community string `json:"community"`
}

type Target struct {
	Name      string `json:"name"`
	Address   string `json:"address"`
	Port      uint16 `json:"port"`
	Version   string `json:"version"`
	Community string `json:"community"`
	OIDs      []OID  `json:"oids"`
}

type OID struct {
	OID         string `json:"oid"`
	Description string `json:"description"`
}

// Tarpan result structures
type TarpanResult struct {
	Name      string    `json:"name"`
	Address   string    `json:"address"`
	Port      uint16    `json:"port"`
	Version   string    `json:"version"`
	Community string    `json:"community"`
	VarBinds  []VarBind `json:"varbinds"`
}

type VarBind struct {
	Description string         `json:"description"`
	OID         string         `json:"oid"`
	Type        gosnmp.Asn1BER `json:"type"`
	Value       interface{}    `json:"value"`
	Time        int64          `json:"time"`
}

type Tarpan interface {
	makeRequestBody()
	SetManager()
	SetParams()
	Get(params map[string]string, oids []string) ([]gosnmp.SnmpPDU, error)
	Run()
}

type TarpanManager struct {
	snmp *gosnmp.GoSNMP
}

type SnmpResult struct {
	target  Target
	results []gosnmp.SnmpPDU
	time    int64
}

type Channels struct {
	semaphoe chan int
	results  chan SnmpResult
}

func (t *TarpanManager) Get(params map[string]string,
	oids []string) ([]gosnmp.SnmpPDU, error) {
	t.SetParams(params)
	connection_err := t.snmp.Connect()
	if connection_err != nil {
		log.Fatalf("Connection error: %")
		return nil, errors.New(connection_err.Error())
	}
	result, request_err := t.snmp.Get(oids)
	if request_err != nil {
		return nil, errors.New(request_err.Error())
	}
	t.snmp.Conn.Close()

	return result.Variables, nil
}

func (t *TarpanManager) SetManager(manager *gosnmp.GoSNMP) {
	t.snmp = manager

	return
}

func (t *TarpanManager) SetParams(p map[string]string) {
	if value, ok := p["target"]; ok {
		t.snmp.Target = value
	}
	if value, ok := p["port"]; ok {
		port, _ := strconv.ParseUint(value, 10, 16)
		t.snmp.Port = uint16(port)
	} else {
		t.snmp.Port = uint16(port)
	}
	if value, ok := p["community"]; ok {
		t.snmp.Community = value
	}
	if value, ok := p["version"]; ok {
		if value == "2c" {
			t.snmp.Version = gosnmp.Version2c
		}
	}
	if value, ok := p["timeout"]; ok {
		sec, _ := strconv.Atoi(value)
		t.snmp.Timeout = time.Duration(sec) * time.Second
	} else {
		t.snmp.Timeout = time.Duration(timeout) * time.Second
	}
	if value, ok := p["retries"]; ok {
		retries, _ := strconv.Atoi(value)
		t.snmp.Retries = retries
	} else {
		t.snmp.Retries = retry

	}

	return
}

func makeRequestBody(ds *DataSet, idx int) (map[string]string, error) {
	address := ""
	err := validateIP(ds.Targets[idx].Address)
	if err == nil {
		address = ds.Targets[idx].Address
	} else {
		return map[string]string{}, err
	}
	community := ds.Targets[idx].Community
	if community == "" {
		community = ds.Default.Community
	}
	version := ds.Targets[idx].Version
	if version == "" {
		version = ds.Default.Version
	}
	port := ds.Targets[idx].Port
	if port == 0 {
		port = ds.Default.Port
	}

	request_body := map[string]string{
		"target":    address,
		"community": community,
		"version":   version,
		"port":      strconv.Itoa(int(port)),
	}

	return request_body, err
}

func makeChannel(result_buffer_length int) *Channels {
	channel := &Channels{
		semaphoe: make(chan int, ConcurrentProcesses),
		results:  make(chan SnmpResult, result_buffer_length),
	}

	return channel
}

func makeTarpanResult(c *Channels) []*TarpanResult {
	var tarpanResults []*TarpanResult
	var varbinds []VarBind
	var result SnmpResult
	length := len(c.results)
	for i := 0; i < length; i++ {
		varbinds = []VarBind{}
		result = <-c.results
		varbinds = makeResultVarBinds(result)
		tr := &TarpanResult{
			Name:      result.target.Name,
			Address:   result.target.Address,
			Port:      result.target.Port,
			Version:   result.target.Version,
			Community: result.target.Community,
			VarBinds:  varbinds,
		}
		tarpanResults = append(tarpanResults, tr)
	}

	return tarpanResults
}

func makeResultVarBinds(ret SnmpResult) []VarBind {
	var varbinds []VarBind
	for _, val := range ret.results {
		n := strings.TrimLeft(val.Name, ".")
		desc, _ := getTargetOIDDescription(n, ret.target.OIDs)
		v := VarBind{
			Description: desc,
			OID:         val.Name,
			Type:        val.Type,
			Value:       val.Value,
			Time:        ret.time,
		}
		varbinds = append(varbinds, v)
	}

	return varbinds
}

func getTargetOIDDescription(oid string, oids []OID) (string, error) {
	for _, o := range oids {
		if o.OID == oid {
			return o.Description, nil
		}
	}

	return "", errors.New("oid not found")
}

func Collect(dataset *DataSet) []*TarpanResult {
	var waitGroup sync.WaitGroup
	var managers []*TarpanManager
	//var tm TarpanManager
	var channels *Channels
	var oids []string

	for i := 0; i < len(dataset.Targets); i++ {
		managers = append(managers, &TarpanManager{
			snmp: &gosnmp.GoSNMP{},
		})
	}

	channels = makeChannel(len(dataset.Targets))
	for index := range dataset.Targets {

		// TODO: split oid slice according to PDU size
		oids = []string{}
		for oid_idx := range dataset.Targets[index].OIDs {
			oids = append(oids, dataset.Targets[index].OIDs[oid_idx].OID)
		}

		waitGroup.Add(1)
		go func(ds *DataSet, idx int, o []string, c *Channels) {
			defer waitGroup.Done()
			c.semaphoe <- 0
			req_body, req_body_err := makeRequestBody(ds, idx)
			if req_body_err != nil {
				log.Print(req_body_err)
				<-c.semaphoe
				return
			}
			t := time.Now()
			results, err := managers[idx].Get(req_body, o)
			if err != nil {
				log.Print(err)
				<-c.semaphoe
				waitGroup.Done()
				return
			}
			c.results <- SnmpResult{
				target:  ds.Targets[idx],
				results: results,
				time:    t.Unix(),
			}
			<-c.semaphoe
		}(dataset, index, oids, channels)
	}
	waitGroup.Wait()
	tr := makeTarpanResult(channels)

	return tr
}

func Run(target string) (int, error) {
	var err error

	// Load targets
	dataset, loadErr := loadConfig(target)
	if loadErr != nil {
		return ExitCodeConfError, loadErr
	}

	// collect data
	tr := Collect(dataset)

	// output
	Write("aa", tr)

	return ExitCodeOK, err
}
<|endoftext|>


<commit_before>// Package hkjnweb is the personal websites http://www.hkjn.me /
// http://blog.hkjn.me.
//
// See https://github.com/hkjn/autosite for the framework that enables
// this site.
package hkjnweb

import (
	"fmt"
	"net/http"

	"appengine"

	"html/template"

	"hkjn.me/autosite"
)

var (
	baseTemplates = []string{
		"tmpl/base.tmpl",
		"tmpl/base_header.tmpl",
		"tmpl/head.tmpl",
		"tmpl/style.tmpl",
		"tmpl/fonts.tmpl",
		"tmpl/js.tmpl",
	}
	live = !appengine.IsDevAppServer()
)

// aeLogger returns a pages.Logger from a request.
func aeLogger(r *http.Request) autosite.Logger {
	return appengine.NewContext(r)
}

var (
	webDomain  = "www.hkjn.me"
	blogDomain = "blog.hkjn.me"
	web        = autosite.New(
		"Henrik Jonsson",
		"pages/*.tmpl", // glob for pages
		webDomain,      // live domain
		append(baseTemplates, "tmpl/page.tmpl"),
		aeLogger,
		live,
		tmplFuncs(webDomain),
	)

	blog = autosite.NewBlog(
		"Henrik Jonsson's blog",
		"blog/*/*/*.tmpl", // glob for blog entries
		blogDomain,        // live domain
		append(baseTemplates, "tmpl/blog.tmpl"),
		append(baseTemplates, "tmpl/blog_listing.tmpl"),
		aeLogger,
		live,
		tmplFuncs(blogDomain),
	)

	redirects = map[string]string{
		"/where": "http://computare0.appspot.com/where/me@hkjn.me",
	}
)

// tmplFuncs returns extra template functions.
func tmplFuncs(domain string) template.FuncMap {
	return template.FuncMap{
		"live": func() bool { return live },
		"domain": func() string {
			if live {
				return domain
			}
			return ""
		},
	}
}

// init initializes the app.
func init() {
	if live {
		web.ChangeURI("/webindex", "/")
		http.HandleFunc("hkjn.me/", nakedIndexHandler)
	} else {
		blog.ChangeURI("/", "/blogindex")
		http.HandleFunc("/nakedindex", nakedIndexHandler)
	}
	for uri, newUri := range redirects {
		web.AddRedirect(uri, newUri)
	}

	web.Register()
	blog.Register()
}

// nakedIndexHandler serves hkjn.me/[package], supplying the <meta>
// tag for the `go get` tool to allow `import hkjn.me/[package]`, and
// redirecting to godoc.org if the `go-get` param is missing.
func nakedIndexHandler(w http.ResponseWriter, r *http.Request) {
	c := appengine.NewContext(r)
	c.Infof("nakedIndexHandler for URI %s\n", r.RequestURI)
	q := r.URL.Query()
	if q.Get("go-get") != "" {
		repoRoot := fmt.Sprintf("https://github.com/hkjn%s", r.URL.Path)
		importPrefix := fmt.Sprintf("hkjn.me%s", r.URL.Path)
		c.Debugf("got go-get param, assuming it's `go get` and pointing it to %s\n", repoRoot)
		fmt.Fprintf(w, `<meta name="go-import" content="%s git %s">\n`, importPrefix, repoRoot)
	} else {
		nextURL := ""
		if r.URL.Path == "/" {
			nextURL = fmt.Sprintf("http://%s", webDomain)
			c.Debugf("regular visitor to naked domain, assuming they're here for www and redirecting to %s..\n", nextURL)
		} else {
			nextURL = fmt.Sprintf("https://godoc.org/hkjn.me/%s", r.URL.Path)
			c.Debugf("regular visitor to naked domain, assuming they're here for go packages and redirecting to %s..\n", nextURL)
		}
		http.Redirect(w, r, nextURL, http.StatusSeeOther)
	}
}
<commit_msg>makes naked domain serve the same result regardless of go-get, and use http-equiv='refresh' to send actual users to godoc.org. makes the repo root be correct in case of subpackages - hkjn.me/probes/dnsprobe->github.com/hkjn/probes, etc<commit_after>// Package hkjnweb is the personal websites http://www.hkjn.me /
// http://blog.hkjn.me.
//
// See https://github.com/hkjn/autosite for the framework that enables
// this site.
package hkjnweb

import (
	"fmt"
	"net/http"
	"strings"

	"appengine"

	"html/template"

	"hkjn.me/autosite"
)

var (
	baseTemplates = []string{
		"tmpl/base.tmpl",
		"tmpl/base_header.tmpl",
		"tmpl/head.tmpl",
		"tmpl/style.tmpl",
		"tmpl/fonts.tmpl",
		"tmpl/js.tmpl",
	}
	live = !appengine.IsDevAppServer()
)

// aeLogger returns a pages.Logger from a request.
func aeLogger(r *http.Request) autosite.Logger {
	return appengine.NewContext(r)
}

var (
	webDomain  = "www.hkjn.me"
	blogDomain = "blog.hkjn.me"
	web        = autosite.New(
		"Henrik Jonsson",
		"pages/*.tmpl", // glob for pages
		webDomain,      // live domain
		append(baseTemplates, "tmpl/page.tmpl"),
		aeLogger,
		live,
		tmplFuncs(webDomain),
	)

	blog = autosite.NewBlog(
		"Henrik Jonsson's blog",
		"blog/*/*/*.tmpl", // glob for blog entries
		blogDomain,        // live domain
		append(baseTemplates, "tmpl/blog.tmpl"),
		append(baseTemplates, "tmpl/blog_listing.tmpl"),
		aeLogger,
		live,
		tmplFuncs(blogDomain),
	)
	goImportTmpl = `<head>
    <meta http-equiv="refresh" content="0; URL='%s'">
    <meta name="go-import" content="%s git %s">
  </head>`

	redirects = map[string]string{
		"/where": "http://computare0.appspot.com/where/me@hkjn.me",
	}
)

// tmplFuncs returns extra template functions.
func tmplFuncs(domain string) template.FuncMap {
	return template.FuncMap{
		"live": func() bool { return live },
		"domain": func() string {
			if live {
				return domain
			}
			return ""
		},
	}
}

// init initializes the app.
func init() {
	if live {
		web.ChangeURI("/webindex", "/")
		http.HandleFunc("hkjn.me/", nakedIndexHandler)
	} else {
		blog.ChangeURI("/", "/blogindex")
		http.HandleFunc("/nakedindex", nakedIndexHandler)
	}
	for uri, newUri := range redirects {
		web.AddRedirect(uri, newUri)
	}

	web.Register()
	blog.Register()
}

// nakedIndexHandler serves hkjn.me/[package], supplying the <meta>
// tag for the `go get` tool to allow `import hkjn.me/[package]`, and
// redirecting to godoc.org if the `go-get` param is missing.
func nakedIndexHandler(w http.ResponseWriter, r *http.Request) {
	c := appengine.NewContext(r)
	c.Infof("nakedIndexHandler for URI %s\n", r.RequestURI)
	if r.URL.Path == "/" {
		c.Debugf("regular visitor to naked domain, assuming they're here for www and redirecting to /..\n")
		http.Redirect(w, r, fmt.Sprintf("http://%s", webDomain), http.StatusSeeOther)
	} else {
		parts := strings.Split(r.URL.Path, "/")
		godocUrl := fmt.Sprintf("https://godoc.org/hkjn.me%s", r.URL.Path)
		repoRoot := fmt.Sprintf("https://github.com/hkjn/%s", parts[1])
		importPrefix := fmt.Sprintf("hkjn.me%s", r.URL.Path)
		fmt.Fprintf(w, goImportTmpl, godocUrl, importPrefix, repoRoot)
	}
}
<|endoftext|>


<commit_before>package jenkins

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"regexp"
	"strconv"
	"strings"
	"time"

	"github.com/Sirupsen/logrus"
)

// Client contains the information for connecting to a jenkins instance
type Client struct {
	Baseurl  string `json:"base_url"`
	Username string `json:"username"`
	Token    string `json:"token"`
}

// Response describes the response returned by jenkins
type Response struct {
	Name  string `json:"name"`
	Build Build  `json:"build"`
}

// Build describes a jenkins build
type Build struct {
	Number     int             `json:"number"`
	URL        string          `json:"full_url"`
	Phase      string          `json:"phase"`
	Status     string          `json:"status"`
	Parameters BuildParameters `json:"parameters"`
}

// BuildParameters decribes the jenkins build parameters
type BuildParameters struct {
	GitBaseRepo string `json:"GIT_BASE_REPO"`
	GitSha      string `json:"GIT_SHA1"`
	PR          string `json:"PR"`
}

// Request describes a request to jenkins
type Request struct {
	Parameters []map[string]string `json:"parameter"`
}

// JobBuildsResponse describes a response for a job's builds.
type JobBuildsResponse struct {
	Builds []RecentBuild `json:"builds"`
}

// RecentBuild describes a build from the Jenkins API.
type RecentBuild struct {
	ID        string        `json:"id"`
	Actions   []interface{} `json:"actions"`
	Building  bool          `json:"building"`
	Timestamp time.Time     `json:"timstamp"`
	NodeName  string        `json:"builtOn"`
}

// Action defines the action for a build.
type Action struct {
	Parameters []Parameter `json:"parameters"`
}

// Parameter defines the parameters for a build.
type Parameter struct {
	Name  string `json:"Name"`
	Value string `json:"Value"`
}

// QueuedBuildsResponse describes a response for a job's builds.
type QueuedBuildsResponse struct {
	Builds []QueuedBuild `json:"items"`
}

// QueuedBuild represents a build in the queue.
type QueuedBuild struct {
	ID      int           `json:"id"`
	Actions []interface{} `json:"actions"`
	Task    QueueTask     `json:"task"`
}

// QueueTask is a task associated with a build in the queue.
type QueueTask struct {
	Name string `json:"name"`
}

// New sets the authentication for the Jenkins client
// Password can be an API token as described in:
// https://wiki.jenkins-ci.org/display/JENKINS/Authenticating+scripted+clients
func New(uri, username, token string) *Client {
	return &Client{
		Baseurl:  uri,
		Username: username,
		Token:    token,
	}
}

// Build sends a build request to jenkins
func (c *Client) Build(job string, data Request) error {
	// encode the request data
	d, err := json.Marshal(data)
	if err != nil {
		return err
	}

	// set up the request
	url := fmt.Sprintf("%s/job/%s/build", c.Baseurl, job)
	req, err := http.NewRequest("POST", url, bytes.NewBuffer(d))
	if err != nil {
		return err
	}

	// add the auth
	req.SetBasicAuth(c.Username, c.Token)

	// do the request
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return err
	}

	// check the status code
	// it should be 201
	if resp.StatusCode != 201 {
		return fmt.Errorf("jenkins post to %s responded with status %d, data: %s", url, resp.StatusCode, string(d))
	}

	return nil
}

// BuildWithParameters sends a build request with parameters to jenkins
func (c *Client) BuildWithParameters(job string, parameters string) error {
	// set up the request
	url := fmt.Sprintf("%s/job/%s/buildWithParameters?%s", c.Baseurl, job, parameters)
	req, err := http.NewRequest("POST", url, bytes.NewBuffer([]byte{}))
	if err != nil {
		return err
	}

	// add the auth
	req.SetBasicAuth(c.Username, c.Token)

	// do the request
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return err
	}

	// check the status code
	// it should be 201
	if resp.StatusCode != 201 {
		return fmt.Errorf("jenkins post to %s responded with status %d", url, resp.StatusCode)
	}

	return nil
}

// CancelBuildsForPR cancels any queued or running builds for a PR.
func (c *Client) CancelBuildsForPR(job, pr string) error {
	var e string

	// first check the queue
	q, err := c.GetQueuedBuildForPR(job, pr)
	if err != nil {
		e = fmt.Sprintf("Getting queued build for job %s, pr %s failed: %v; ", job, pr, err)
	} else if q != nil {
		// if it is not nil then we found a matching build, cancel it
		if err := c.CancelBuild(job, strconv.Itoa(q.ID), true); err != nil {
			e = fmt.Sprintf("cancelling queued build for job %s, pr %s failed: %v; ", job, pr, err)
		}
		logrus.Infof("Cancelled queued build (%d) for job %s, pr %s", q.ID, job, pr)
	}

	// check running builds
	b, err := c.GetRunningBuildForPR(job, pr)
	if err != nil {
		e += fmt.Sprintf("Getting running build for job %s, pr %s failed: %v;", job, pr, err)
	} else if b != nil {
		// if it is not nil then we found a matching build, cancel it
		if err := c.CancelBuild(job, b.ID, false); err != nil {
			e += fmt.Sprintf("cancelling running build for job %s, pr %s failed: %v;", job, pr, err)
		}
		logrus.Infof("Cancelled running build (%s) for job %s, pr %s", b.ID, job, pr)
	}

	if e != "" {
		return errors.New(e)
	}

	return nil
}

// CancelBuild cancels/stops a running or queued build.
func (c *Client) CancelBuild(job, id string, isQueued bool) error {
	// set up the request
	url := fmt.Sprintf("%s/job/%s/%s/stop", c.Baseurl, job, id)
	if isQueued {
		url = fmt.Sprintf("%s/queue/cancelItem?id=%s", c.Baseurl, id)
	}
	req, err := http.NewRequest("POST", url, bytes.NewBuffer([]byte{}))
	if err != nil {
		return err
	}

	// add the auth
	req.SetBasicAuth(c.Username, c.Token)

	// do the request
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return err
	}

	// check the status code
	// it should be 201
	if resp.StatusCode != 201 {
		return fmt.Errorf("jenkins post to %s responded with status %d", url, resp.StatusCode)
	}

	return nil
}

// GetRunningBuildForPR returns the running build for a Jenkins job and PR if there is one.
func (c *Client) GetRunningBuildForPR(job, pr string) (*RecentBuild, error) {
	builds, err := c.GetBuilds(job)
	if err != nil {
		return nil, err
	}

	for _, build := range builds {
		if build.Building && len(build.Actions) > 0 {
			if a, ok := build.Actions[0].(Action); ok {
				for _, p := range a.Parameters {
					if p.Name == "PR" && p.Value == pr {
						return &build, nil
					}
				}
			}
		}
	}

	return nil, nil
}

// GetBuilds gets the builds for a Jenkins job.
func (c *Client) GetBuilds(job string) (b []RecentBuild, err error) {
	// set up the request
	url := fmt.Sprintf("%s/job/%s/api/json?tree=%s", c.Baseurl, job, url.QueryEscape("builds[builtOn,actions[parameters[name,value]],timestamp,id,building]"))
	req, err := http.NewRequest("GET", url, bytes.NewBuffer([]byte{}))
	if err != nil {
		return b, err
	}

	// add the auth
	req.SetBasicAuth(c.Username, c.Token)

	// do the request
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return b, err
	}
	defer resp.Body.Close()

	// check the status code
	// it should be 200
	if resp.StatusCode != 200 {
		return b, fmt.Errorf("jenkins get builds for %s request to %s responded with status %d", job, url, resp.StatusCode)
	}

	var r JobBuildsResponse
	if err := json.NewDecoder(resp.Body).Decode(&r); err != nil {
		return b, fmt.Errorf("decoding json response from builds from %s failed: %v", url, err)
	}

	return r.Builds, nil
}

// GetQueuedBuildForPR returns the queued build for a Jenkins job and PR if there is one.
func (c *Client) GetQueuedBuildForPR(job, pr string) (*QueuedBuild, error) {
	// set up the request
	url := fmt.Sprintf("%s/queue/api/json?tree=%s", c.Baseurl, url.QueryEscape("items[id,task[name]]"))
	req, err := http.NewRequest("GET", url, bytes.NewBuffer([]byte{}))
	if err != nil {
		return nil, err
	}

	// add the auth
	req.SetBasicAuth(c.Username, c.Token)

	// do the request
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	// check the status code
	// it should be 200
	if resp.StatusCode != 200 {
		return nil, fmt.Errorf("jenkins get queued builds request to %s responded with status %d", url, resp.StatusCode)
	}

	var r QueuedBuildsResponse
	if err := json.NewDecoder(resp.Body).Decode(&r); err != nil {
		return nil, fmt.Errorf("decoding json response from queued builds from %s failed: %v", url, err)
	}

	// loop through and collect only the ones that task name matches the job.
	for _, build := range r.Builds {
		if build.Task.Name == job && len(build.Actions) > 0 {
			if a, ok := build.Actions[0].(Action); ok {
				for _, p := range a.Parameters {
					if p.Name == "PR" && p.Value == pr {
						return &build, nil
					}
				}
			}
		}
	}

	return nil, nil
}

// GetBuildLog returns the consoleText for a Jenkins build.
func (c *Client) GetBuildLog(job string, id int) (string, error) {
	// set up the request
	url := fmt.Sprintf("%s/job/%s/%d/consoleText", c.Baseurl, job, id)
	resp, err := http.Get(url)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	// check the status code
	// it should be 200
	if resp.StatusCode != 200 {
		return "", fmt.Errorf("jenkins get logs request to %s responded with status %d", url, resp.StatusCode)
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", fmt.Errorf("reading body from logs response to %s failed: %v", url, err)
	}

	return parseFailedBuildLog(job, url, string(body)), nil
}

func parseFailedBuildLog(job, url, log string) string {
	testComment := fmt.Sprintf(`Job: %s [FAILED](%s):

~~~console

`, job, strings.Replace(url, "consoleText", "console", 1))
	// set the chars to resturn around the index where the line was matched
	sl := 500

	// first try to find FAIL in the log
	re := regexp.MustCompile(`FAIL((.)*?)(\n|\r)`)
	m := re.FindAllStringIndex(log, 1)

	if len(m) == 0 {
		// try another way, by looking for the end before the PostBuildScript
		re = regexp.MustCompile(`PostBuildScript((.)*?)(\n|\r)`)
		m = re.FindAllStringIndex(log, 1)
	}

	if len(m) == 0 {
		// if still empty just return empty comment
		return ""
	}

	// get the post build script index
	pbIndex := strings.Index(log, "Now starting POST-BUILD steps")

	for _, index := range m {
		// get a few lines around the index
		start := 0
		if (index[0] - sl) > start {
			start = index[0] - sl
		}
		end := len(log) - 1
		if pbIndex > 5 {
			// set the end to be that instead, since we don't need to include
			// the post build script logs in the comment
			end = pbIndex - 5
		}
		if index[1]+sl < end {
			end = index[1] + sl
		}
		testComment += fmt.Sprintf("---\n%s\n---\n\n", log[start:end])
	}

	return testComment + "~~~"
}
<commit_msg>Fixes for jenkins API<commit_after>package jenkins

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"regexp"
	"strconv"
	"strings"
	"time"

	"github.com/Sirupsen/logrus"
)

// Client contains the information for connecting to a jenkins instance
type Client struct {
	Baseurl  string `json:"base_url"`
	Username string `json:"username"`
	Token    string `json:"token"`
}

// Response describes the response returned by jenkins
type Response struct {
	Name  string `json:"name"`
	Build Build  `json:"build"`
}

// Build describes a jenkins build
type Build struct {
	Number     int             `json:"number"`
	URL        string          `json:"full_url"`
	Phase      string          `json:"phase"`
	Status     string          `json:"status"`
	Parameters BuildParameters `json:"parameters"`
}

// BuildParameters decribes the jenkins build parameters
type BuildParameters struct {
	GitBaseRepo string `json:"GIT_BASE_REPO"`
	GitSha      string `json:"GIT_SHA1"`
	PR          string `json:"PR"`
}

// Request describes a request to jenkins
type Request struct {
	Parameters []map[string]string `json:"parameter,omitempty"`
}

// JobBuildsResponse describes a response for a job's builds.
type JobBuildsResponse struct {
	Builds []RecentBuild `json:"builds,omitempty"`
}

// RecentBuild describes a build from the Jenkins API.
type RecentBuild struct {
	ID        string    `json:"id,omitempty"`
	Actions   []Action  `json:"actions,omitempty"`
	Building  bool      `json:"building,omitempty"`
	Timestamp time.Time `json:"timstamp,omitempty"`
	NodeName  string    `json:"builtOn,omitempty"`
}

// Action defines the action for a build.
type Action struct {
	Parameters []Parameter `json:"parameters,omitempty"`
}

// Parameter defines the parameters for a build.
type Parameter struct {
	Name  string `json:"name,omitempty"`
	Value string `json:"value,omitempty"`
}

// QueuedBuildsResponse describes a response for a job's builds.
type QueuedBuildsResponse struct {
	Builds []QueuedBuild `json:"items,omitempty"`
}

// QueuedBuild represents a build in the queue.
type QueuedBuild struct {
	ID      int       `json:"id,omitempty"`
	Actions []Action  `json:"actions,omitempty"`
	Task    QueueTask `json:"task,omitempty"`
}

// QueueTask is a task associated with a build in the queue.
type QueueTask struct {
	Name string `json:"name,omitempty"`
}

// New sets the authentication for the Jenkins client
// Password can be an API token as described in:
// https://wiki.jenkins-ci.org/display/JENKINS/Authenticating+scripted+clients
func New(uri, username, token string) *Client {
	return &Client{
		Baseurl:  uri,
		Username: username,
		Token:    token,
	}
}

// Build sends a build request to jenkins
func (c *Client) Build(job string, data Request) error {
	// encode the request data
	d, err := json.Marshal(data)
	if err != nil {
		return err
	}

	// set up the request
	url := fmt.Sprintf("%s/job/%s/build", c.Baseurl, job)
	req, err := http.NewRequest("POST", url, bytes.NewBuffer(d))
	if err != nil {
		return err
	}

	// add the auth
	req.SetBasicAuth(c.Username, c.Token)

	// do the request
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return err
	}

	// check the status code
	// it should be 201
	if resp.StatusCode != 201 {
		return fmt.Errorf("jenkins post to %s responded with status %d, data: %s", url, resp.StatusCode, string(d))
	}

	return nil
}

// BuildWithParameters sends a build request with parameters to jenkins
func (c *Client) BuildWithParameters(job string, parameters string) error {
	// set up the request
	url := fmt.Sprintf("%s/job/%s/buildWithParameters?%s", c.Baseurl, job, parameters)
	req, err := http.NewRequest("POST", url, bytes.NewBuffer([]byte{}))
	if err != nil {
		return err
	}

	// add the auth
	req.SetBasicAuth(c.Username, c.Token)

	// do the request
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return err
	}

	// check the status code
	// it should be 201
	if resp.StatusCode != 201 {
		return fmt.Errorf("jenkins post to %s responded with status %d", url, resp.StatusCode)
	}

	return nil
}

// CancelBuildsForPR cancels any queued or running builds for a PR.
func (c *Client) CancelBuildsForPR(job, pr string) error {
	var e string

	// first check the queue
	q, err := c.GetQueuedBuildForPR(job, pr)
	if err != nil {
		e = fmt.Sprintf("Getting queued build for job %s, pr %s failed: %v; ", job, pr, err)
	} else if q != nil {
		// if it is not nil then we found a matching build, cancel it
		if err := c.CancelBuild(job, strconv.Itoa(q.ID), true); err != nil {
			e = fmt.Sprintf("cancelling queued build for job %s, pr %s failed: %v; ", job, pr, err)
		}
		logrus.Infof("Cancelled queued build (%d) for job %s, pr %s", q.ID, job, pr)
	}

	// check running builds
	b, err := c.GetRunningBuildForPR(job, pr)
	if err != nil {
		e += fmt.Sprintf("Getting running build for job %s, pr %s failed: %v;", job, pr, err)
	} else if b != nil {
		// if it is not nil then we found a matching build, cancel it
		if err := c.CancelBuild(job, b.ID, false); err != nil {
			e += fmt.Sprintf("cancelling running build for job %s, pr %s failed: %v;", job, pr, err)
		}
		logrus.Infof("Cancelled running build (%s) for job %s, pr %s", b.ID, job, pr)
	}

	if e != "" {
		return errors.New(e)
	}

	return nil
}

// CancelBuild cancels/stops a running or queued build.
func (c *Client) CancelBuild(job, id string, isQueued bool) error {
	// set up the request
	url := fmt.Sprintf("%s/job/%s/%s/stop", c.Baseurl, job, id)
	if isQueued {
		url = fmt.Sprintf("%s/queue/cancelItem?id=%s", c.Baseurl, id)
	}
	req, err := http.NewRequest("POST", url, bytes.NewBuffer([]byte{}))
	if err != nil {
		return err
	}

	// add the auth
	req.SetBasicAuth(c.Username, c.Token)

	// do the request
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return err
	}

	// check the status code
	// it should be 201
	if resp.StatusCode != 201 && resp.StatusCode != 200 {
		return fmt.Errorf("jenkins post to %s responded with status %d", url, resp.StatusCode)
	}

	return nil
}

// GetRunningBuildForPR returns the running build for a Jenkins job and PR if there is one.
func (c *Client) GetRunningBuildForPR(job, pr string) (*RecentBuild, error) {
	builds, err := c.GetBuilds(job)
	if err != nil {
		return nil, err
	}

	for _, build := range builds {
		if build.Building {
			for _, a := range build.Actions {
				for _, p := range a.Parameters {
					if p.Name == "PR" && p.Value == pr {
						return &build, nil
					}
				}
			}
		}
	}

	return nil, nil
}

// GetBuilds gets the builds for a Jenkins job.
func (c *Client) GetBuilds(job string) (b []RecentBuild, err error) {
	// set up the request
	url := fmt.Sprintf("%s/job/%s/api/json?tree=%s", c.Baseurl, job, url.QueryEscape("builds[builtOn,actions[parameters[name,value]],timestamp,id,building]"))
	req, err := http.NewRequest("GET", url, bytes.NewBuffer([]byte{}))
	if err != nil {
		return b, err
	}

	// add the auth
	req.SetBasicAuth(c.Username, c.Token)

	// do the request
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return b, err
	}
	defer resp.Body.Close()

	// check the status code
	// it should be 200
	if resp.StatusCode != 200 {
		return b, fmt.Errorf("jenkins get builds for %s request to %s responded with status %d", job, url, resp.StatusCode)
	}

	var r JobBuildsResponse
	if err := json.NewDecoder(resp.Body).Decode(&r); err != nil {
		return b, fmt.Errorf("decoding json response from builds from %s failed: %v", url, err)
	}

	return r.Builds, nil
}

// GetQueuedBuildForPR returns the queued build for a Jenkins job and PR if there is one.
func (c *Client) GetQueuedBuildForPR(job, pr string) (*QueuedBuild, error) {
	// set up the request
	url := fmt.Sprintf("%s/queue/api/json?tree=%s", c.Baseurl, url.QueryEscape("items[id,task[name]]"))
	req, err := http.NewRequest("GET", url, bytes.NewBuffer([]byte{}))
	if err != nil {
		return nil, err
	}

	// add the auth
	req.SetBasicAuth(c.Username, c.Token)

	// do the request
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	// check the status code
	// it should be 200
	if resp.StatusCode != 200 {
		return nil, fmt.Errorf("jenkins get queued builds request to %s responded with status %d", url, resp.StatusCode)
	}

	var r QueuedBuildsResponse
	if err := json.NewDecoder(resp.Body).Decode(&r); err != nil {
		return nil, fmt.Errorf("decoding json response from queued builds from %s failed: %v", url, err)
	}

	// loop through and collect only the ones that task name matches the job.
	for _, build := range r.Builds {
		if build.Task.Name == job {
			for _, a := range build.Actions {
				for _, p := range a.Parameters {
					if p.Name == "PR" && p.Value == pr {
						return &build, nil
					}
				}
			}
		}
	}

	return nil, nil
}

// GetBuildLog returns the consoleText for a Jenkins build.
func (c *Client) GetBuildLog(job string, id int) (string, error) {
	// set up the request
	url := fmt.Sprintf("%s/job/%s/%d/consoleText", c.Baseurl, job, id)
	resp, err := http.Get(url)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	// check the status code
	// it should be 200
	if resp.StatusCode != 200 {
		return "", fmt.Errorf("jenkins get logs request to %s responded with status %d", url, resp.StatusCode)
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", fmt.Errorf("reading body from logs response to %s failed: %v", url, err)
	}

	return parseFailedBuildLog(job, url, string(body)), nil
}

func parseFailedBuildLog(job, url, log string) string {
	testComment := fmt.Sprintf(`Job: %s [FAILED](%s):

~~~console

`, job, strings.Replace(url, "consoleText", "console", 1))
	// set the chars to resturn around the index where the line was matched
	sl := 500

	// first try to find FAIL in the log
	re := regexp.MustCompile(`FAIL((.)*?)(\n|\r)`)
	m := re.FindAllStringIndex(log, 1)

	if len(m) == 0 {
		// try another way, by looking for the end before the PostBuildScript
		re = regexp.MustCompile(`PostBuildScript((.)*?)(\n|\r)`)
		m = re.FindAllStringIndex(log, 1)
	}

	if len(m) == 0 {
		// if still empty just return empty comment
		return ""
	}

	// get the post build script index
	pbIndex := strings.Index(log, "Now starting POST-BUILD steps")

	for _, index := range m {
		// get a few lines around the index
		start := 0
		if (index[0] - sl) > start {
			start = index[0] - sl
		}
		end := len(log) - 1
		if pbIndex > 5 {
			// set the end to be that instead, since we don't need to include
			// the post build script logs in the comment
			end = pbIndex - 5
		}
		if index[1]+sl < end {
			end = index[1] + sl
		}
		testComment += fmt.Sprintf("---\n%s\n---\n\n", log[start:end])
	}

	return testComment + "~~~"
}
<|endoftext|>


<commit_before>package cli

import (
	"bytes"
	"net/http"
	"strings"

	"github.com/labstack/gommon/color"
)

func (cmd *Command) RegisterHTTP(ctxs ...*Context) error {
	clr := color.Color{}
	clr.Disable()
	if len(ctxs) > 0 {
		clr = ctxs[0].color
	}
	if cmd.routersMap == nil {
		cmd.routersMap = make(map[string]string)
	}
	commands := []*Command{cmd}
	for len(commands) > 0 {
		c := commands[0]
		commands = commands[1:]
		if c.HTTPRouters != nil {
			for _, r := range c.HTTPRouters {
				if _, exists := c.routersMap[r]; exists {
					return throwRouterRepeat(clr.Yellow(r))
				}
				cmd.routersMap[r] = c.Path()
			}
		}
		if c.nochild() {
			continue
		}
		commands = append(commands, c.children...)
	}
	return nil
}

func (cmd *Command) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if err := r.ParseForm(); err != nil {
		return
	}

	var (
		path  = r.URL.Path
		found = false
	)
	if cmd.routersMap != nil {
		path, found = cmd.routersMap[path]
	}
	if !found {
		path = strings.TrimPrefix(r.URL.Path, "/")
		path = strings.TrimSuffix(path, "/")
	}

	router := strings.Split(path, "/")
	args := make([]string, 0, len(r.Form)*2+len(router))
	for _, r := range router {
		args = append(args, r)
	}
	for key, values := range r.Form {
		if len(key) == 0 || len(values) == 0 {
			continue
		}
		if !strings.HasPrefix(key, dashOne) {
			if len(key) == 1 {
				key = dashOne + key
			} else {
				key = dashTwo + key
			}
		}
		args = append(args, key, values[len(values)-1])
	}
	Debugf("path: %s", path)
	Debugf("args: %q", args)

	buf := new(bytes.Buffer)
	statusCode := http.StatusOK
	if err := cmd.RunWithWriter(args, buf, r.Method); err != nil {
		buf.Write([]byte(err.Error()))
		nativeError := err
		if werr, ok := err.(wrapError); ok {
			nativeError = werr.err
		}
		Debugf("error type: %s", TypeName(nativeError))
		switch nativeError.(type) {
		case commandNotFoundError:
			statusCode = http.StatusNotFound

		case methodNotAllowedError:
			statusCode = http.StatusMethodNotAllowed

		default:
			statusCode = http.StatusInternalServerError
		}
	}
	Debugf("reap: %s", buf.String())
	w.WriteHeader(statusCode)
	w.Write(buf.Bytes())
}
<commit_msg>fix typo<commit_after>package cli

import (
	"bytes"
	"net/http"
	"strings"

	"github.com/labstack/gommon/color"
)

func (cmd *Command) RegisterHTTP(ctxs ...*Context) error {
	clr := color.Color{}
	clr.Disable()
	if len(ctxs) > 0 {
		clr = ctxs[0].color
	}
	if cmd.routersMap == nil {
		cmd.routersMap = make(map[string]string)
	}
	commands := []*Command{cmd}
	for len(commands) > 0 {
		c := commands[0]
		commands = commands[1:]
		if c.HTTPRouters != nil {
			for _, r := range c.HTTPRouters {
				if _, exists := c.routersMap[r]; exists {
					return throwRouterRepeat(clr.Yellow(r))
				}
				cmd.routersMap[r] = c.Path()
			}
		}
		if c.nochild() {
			continue
		}
		commands = append(commands, c.children...)
	}
	return nil
}

func (cmd *Command) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if err := r.ParseForm(); err != nil {
		return
	}

	var (
		path  = r.URL.Path
		found = false
	)
	if cmd.routersMap != nil {
		path, found = cmd.routersMap[path]
	}
	if !found {
		path = strings.TrimPrefix(r.URL.Path, "/")
		path = strings.TrimSuffix(path, "/")
	}

	router := strings.Split(path, "/")
	args := make([]string, 0, len(r.Form)*2+len(router))
	for _, r := range router {
		args = append(args, r)
	}
	for key, values := range r.Form {
		if len(key) == 0 || len(values) == 0 {
			continue
		}
		if !strings.HasPrefix(key, dashOne) {
			if len(key) == 1 {
				key = dashOne + key
			} else {
				key = dashTwo + key
			}
		}
		args = append(args, key, values[len(values)-1])
	}
	Debugf("path: %s", path)
	Debugf("args: %q", args)

	buf := new(bytes.Buffer)
	statusCode := http.StatusOK
	if err := cmd.RunWithWriter(args, buf, r.Method); err != nil {
		buf.Write([]byte(err.Error()))
		nativeError := err
		if werr, ok := err.(wrapError); ok {
			nativeError = werr.err
		}
		Debugf("error type: %s", TypeName(nativeError))
		switch nativeError.(type) {
		case commandNotFoundError:
			statusCode = http.StatusNotFound

		case methodNotAllowedError:
			statusCode = http.StatusMethodNotAllowed

		default:
			statusCode = http.StatusInternalServerError
		}
	}
	Debugf("resp: %s", buf.String())
	w.WriteHeader(statusCode)
	w.Write(buf.Bytes())
}
<|endoftext|>


<commit_before>package dalga

import (
	"net"
	"net/http"
	"strconv"
)

func (d *Dalga) makeServer() (func(), error) {
	var err error
	addr := d.C.HTTP.Host + ":" + d.C.HTTP.Port
	d.listener, err = net.Listen("tcp", addr)
	if err != nil {
		return nil, err
	}

	handler := http.NewServeMux()
	handler.HandleFunc("/schedule", d.makeHandler(handleSchedule))
	handler.HandleFunc("/cancel", d.makeHandler(handleCancel))

	return func() {
		http.Serve(d.listener, handler)
		debug("HTTP server is done")
		d.quitPublisher <- true
		debug("Sent quit message")
	}, nil
}

func (dalga *Dalga) makeHandler(fn func(http.ResponseWriter, *http.Request, *Dalga)) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		fn(w, r, dalga)
	}
}

// hadleSchedule is the web server endpoint for path: /schedule
func handleSchedule(w http.ResponseWriter, r *http.Request, d *Dalga) {
	routingKey, body, intervalString := r.FormValue("routing_key"), r.FormValue("body"), r.FormValue("interval")
	debug("/schedule", routingKey, body)

	intervalUint64, err := strconv.ParseUint(intervalString, 10, 64)
	if err != nil {
		http.Error(w, "Cannot parse interval", http.StatusBadRequest)
		return
	}

	if intervalUint64 < 1 {
		http.Error(w, "interval must be >= 1", http.StatusBadRequest)
		return
	}

	err = d.Schedule(routingKey, []byte(body), uint32(intervalUint64))
	if err != nil {
		panic(err)
	}
}

// handleCancel is the web server endpoint for path: /cancel
func handleCancel(w http.ResponseWriter, r *http.Request, d *Dalga) {
	routingKey, body := r.FormValue("routing_key"), r.FormValue("body")
	debug("/cancel", routingKey, body)

	err := d.Cancel(routingKey, []byte(body))
	if err != nil {
		panic(err)
	}
}
<commit_msg>Revert "64"<commit_after>package dalga

import (
	"net"
	"net/http"
	"strconv"
)

func (d *Dalga) makeServer() (func(), error) {
	var err error
	addr := d.C.HTTP.Host + ":" + d.C.HTTP.Port
	d.listener, err = net.Listen("tcp", addr)
	if err != nil {
		return nil, err
	}

	handler := http.NewServeMux()
	handler.HandleFunc("/schedule", d.makeHandler(handleSchedule))
	handler.HandleFunc("/cancel", d.makeHandler(handleCancel))

	return func() {
		http.Serve(d.listener, handler)
		debug("HTTP server is done")
		d.quitPublisher <- true
		debug("Sent quit message")
	}, nil
}

func (dalga *Dalga) makeHandler(fn func(http.ResponseWriter, *http.Request, *Dalga)) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		fn(w, r, dalga)
	}
}

// hadleSchedule is the web server endpoint for path: /schedule
func handleSchedule(w http.ResponseWriter, r *http.Request, d *Dalga) {
	routingKey, body, intervalString := r.FormValue("routing_key"), r.FormValue("body"), r.FormValue("interval")
	debug("/schedule", routingKey, body)

	intervalUint64, err := strconv.ParseUint(intervalString, 10, 32)
	if err != nil {
		http.Error(w, "Cannot parse interval", http.StatusBadRequest)
		return
	}

	if intervalUint64 < 1 {
		http.Error(w, "interval must be >= 1", http.StatusBadRequest)
		return
	}

	err = d.Schedule(routingKey, []byte(body), uint32(intervalUint64))
	if err != nil {
		panic(err)
	}
}

// handleCancel is the web server endpoint for path: /cancel
func handleCancel(w http.ResponseWriter, r *http.Request, d *Dalga) {
	routingKey, body := r.FormValue("routing_key"), r.FormValue("body")
	debug("/cancel", routingKey, body)

	err := d.Cancel(routingKey, []byte(body))
	if err != nil {
		panic(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/base64"
	"net/http"
	"strings"
)

func BasicAuth(handler http.HandlerFunc, username, password string) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		authError := func() {
			w.Header().Set("WWW-Authenticate", "Basic realm=\"Zork\"")
			http.Error(w, "authorization failed", http.StatusUnauthorized)
		}

		auth := strings.SplitN(r.Header.Get("Authorization"), " ", 2)
		if len(auth) != 2 || auth[0] != "Basic" {
			authError()
			return
		}

		payload, err := base64.StdEncoding.DecodeString(auth[1])
		if err != nil {
			authError()
			return
		}

		pair := strings.SplitN(string(payload), ":", 2)
		if len(pair) != 2 || !(pair[0] == username && pair[1] == password) {
			authError()
			return
		}

		handler(w, r)
	}
}
<commit_msg>Simplify basic auth code signifigantly<commit_after>package main

import (
	"net/http"
)

func BasicAuth(handler http.Handler, username, password string) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		if u, p, ok := r.BasicAuth(); !ok || !(u == username && p == password) {
			w.Header().Set("WWW-Authenticate", "Basic realm=\"Zork\"")
			http.Error(w, "authorization failed", http.StatusUnauthorized)
			return
		}

		handler.ServeHTTP(w, r)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
)

type JobState struct {
	Name  string `json:"name"`
	URL   string `json:"url"`
	Color string `json:"color"`
}

type Jenkins struct {
	NodeDescription string     `json:"nodeDescription"`
	Jobs            []JobState `json:"jobs"`
}

func responseBody(url string) ([]byte, error) {
	response, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()
	contents, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}
	return contents, nil
}

func JenkinsJobs(jenkins *string) ([]JobState, error) {
	contents, err := responseBody("http://" + *jenkins + "/api/json?pretty=true")
	if err != nil {
		return nil, err
	}
	fmt.Printf("%s\n", string(contents))

	var data Jenkins
	err = json.Unmarshal(contents, &data)
	if err != nil {
		return nil, err
	}
	return data.Jobs, nil
}
func JenkinsJob(jenkins, jobName *string) (JobState, error) {
	noJob := JobState{}

	url := "http://" + *jenkins + "/job/" + *jobName + "/api/json?pretty=true"
	fmt.Printf("%s\n", url)
	contents, err := responseBody(url)
	if err != nil {
		return noJob, err
	}
	fmt.Printf("%s\n", string(contents))

	// var data Jenkins
	// err = json.Unmarshal(contents, &data)
	// if err != nil {
	// 	return nil, err
	// }
	// return data.Jobs, nil
	return noJob, errors.New("Job not found.")
}
func main() {
	jenkins := flag.String("jenkins", "127.0.0.1:8080", "Jenkins hostname")
	jobName := flag.String("jobName", "test", "Jenkins job name")
	flag.Parse()

	job, err := JenkinsJob(jenkins, jobName)
	if err != nil {
		fmt.Printf("%s", err)
		os.Exit(1)
	}
	fmt.Printf("Name: %s, URL: %s, Color: %s\n", job.Name, job.URL, job.Color)
}
<commit_msg>parse job and buid<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
)

type JobState struct {
	Name  string `json:"name"`
	URL   string `json:"url"`
	Color string `json:"color"`
}

type Jenkins struct {
	NodeDescription string     `json:"nodeDescription"`
	Jobs            []JobState `json:"jobs"`
}

func responseBody(url string) ([]byte, error) {
	response, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()
	contents, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}
	return contents, nil
}

func JenkinsJobs(jenkins *string) ([]JobState, error) {
	contents, err := responseBody("http://" + *jenkins + "/api/json?pretty=true")
	if err != nil {
		return nil, err
	}
	fmt.Printf("%s\n", string(contents))

	var data Jenkins
	err = json.Unmarshal(contents, &data)
	if err != nil {
		return nil, err
	}
	return data.Jobs, nil
}
func JenkinsJob(jenkins, jobName *string) (Job, error) {
	noJob := Job{}

	url := "http://" + *jenkins + "/job/" + *jobName + "/api/json?pretty=true"
	fmt.Printf("%s\n", url)
	contents, err := responseBody(url)
	if err != nil {
		return noJob, err
	}
	fmt.Printf("%s\n", string(contents))

	var data Job
	err = json.Unmarshal(contents, &data)
	if err != nil {
		return noJob, err
	}
	return data, nil
}

type Build struct {
	Number int    `json:"number"`
	URL    string `json:"url"`
}

type Job struct {
	Name      string `json:"name"`
	URL       string `json:"url"`
	Color     string `json:"color"`
	InQueue   bool   `json:"inQueue"`
	LastBuild Build  `json:"lastBuild"`
}

func main() {
	jenkins := flag.String("jenkins", "127.0.0.1:8080", "Jenkins hostname")
	jobName := flag.String("jobName", "test", "Jenkins job name")
	flag.Parse()

	job, err := JenkinsJob(jenkins, jobName)
	if err != nil {
		fmt.Printf("%s", err)
		os.Exit(1)
	}
	fmt.Println("Name:", job.Name)
	fmt.Println("URL:", job.URL)
	fmt.Println("Color:", job.Color)
	fmt.Println("InQueue:", job.InQueue)
	fmt.Println("LastBuild number:", job.LastBuild.Number)
	fmt.Println("LastBuild URL:", job.LastBuild.URL)
}
<|endoftext|>


<commit_before>package main

import "net/http"

// CustomClient is the state for our custom http wrapper, which houses
// the needed data to be able to rewrite the outgoing request during
// redirects.
type CustomClient struct {
	URL  string
	IP   string
	Host string
}

func (c *CustomClient) redirectHandler(req *http.Request, via []*http.Request) error {
	req = c.requestWrap(req)

	// rewrite Referer (Referrer) if it exists, to have the proper hostname
	uri := via[len(via)-1].URL
	uri.Host = via[len(via)-1].Host
	req.Header.Set("Referer", uri.String())

	return nil
}

func (c *CustomClient) requestWrap(req *http.Request) *http.Request {
	// spoof useragent, as there are going to be sites/servers that are
	// setup to deny by a specific useragent string (or lack there of)
	req.Header.Set("User-Agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36")

	// if an IP address is provided, rewrite the Host headers
	// of note: if we plan to support custom ports, these should be rewritten
	// within the header. E.g. "hostname.com:8080" -- though, common ports like
	// 80 and 443 are left out.

	// assign the origin host to the host header value
	req.Host = c.Host

	// and overwrite the host used to make the connection
	if len(c.IP) > 0 {
		req.URL.Host = c.IP
	}

	return req
}

// getHandler wraps the standard net/http library, allowing us to spoof hostnames and IP addresses
func (c *CustomClient) getHandler() (*http.Response, error) {
	client := &http.Client{
		CheckRedirect: c.redirectHandler,
	}

	req, err := http.NewRequest("GET", c.URL, nil)

	if err != nil {
		return nil, err
	}

	c.Host = req.URL.Host

	req = c.requestWrap(req)

	// actually make the request here
	resp, err := client.Do(req)

	return resp, err
}

// Get wraps GetHandler -- easy interface for making get requests
func Get(url string, ip string) (*http.Response, error) {
	c := &CustomClient{URL: url, IP: ip}

	return c.getHandler()
}
<commit_msg>set http timeout to 10s<commit_after>package main

import (
	"net/http"
	"time"
)

// CustomClient is the state for our custom http wrapper, which houses
// the needed data to be able to rewrite the outgoing request during
// redirects.
type CustomClient struct {
	URL  string
	IP   string
	Host string
}

func (c *CustomClient) redirectHandler(req *http.Request, via []*http.Request) error {
	req = c.requestWrap(req)

	// rewrite Referer (Referrer) if it exists, to have the proper hostname
	uri := via[len(via)-1].URL
	uri.Host = via[len(via)-1].Host
	req.Header.Set("Referer", uri.String())

	return nil
}

func (c *CustomClient) requestWrap(req *http.Request) *http.Request {
	// spoof useragent, as there are going to be sites/servers that are
	// setup to deny by a specific useragent string (or lack there of)
	req.Header.Set("User-Agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36")

	// if an IP address is provided, rewrite the Host headers
	// of note: if we plan to support custom ports, these should be rewritten
	// within the header. E.g. "hostname.com:8080" -- though, common ports like
	// 80 and 443 are left out.

	// assign the origin host to the host header value
	req.Host = c.Host

	// and overwrite the host used to make the connection
	if len(c.IP) > 0 {
		req.URL.Host = c.IP
	}

	return req
}

// getHandler wraps the standard net/http library, allowing us to spoof hostnames and IP addresses
func (c *CustomClient) getHandler() (*http.Response, error) {
	client := &http.Client{
		CheckRedirect: c.redirectHandler,
		Timeout:       time.Duration(10) * time.Second,
	}

	req, err := http.NewRequest("GET", c.URL, nil)

	if err != nil {
		return nil, err
	}

	c.Host = req.URL.Host

	req = c.requestWrap(req)

	// actually make the request here
	resp, err := client.Do(req)

	return resp, err
}

// Get wraps GetHandler -- easy interface for making get requests
func Get(url string, ip string) (*http.Response, error) {
	c := &CustomClient{URL: url, IP: ip}

	return c.getHandler()
}
<|endoftext|>


<commit_before>/*
Copyright 2014 Rohith All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package marathon

// Info is the detailed stats returned from marathon info
type Info struct {
	EventSubscriber struct {
		HTTPEndpoints []string `json:"http_endpoints"`
		Type          string   `json:"type"`
	} `json:"event_subscriber"`
	FrameworkID string `json:"frameworkId"`
	HTTPConfig  struct {
		AssetsPath interface{} `json:"assets_path"`
		HTTPPort   float64     `json:"http_port"`
		HTTPSPort  float64     `json:"https_port"`
	} `json:"http_config"`
	Leader         string `json:"leader"`
	MarathonConfig struct {
		Checkpoint                 bool    `json:"checkpoint"`
		Executor                   string  `json:"executor"`
		FailoverTimeout            float64 `json:"failover_timeout"`
		Ha                         bool    `json:"ha"`
		Hostname                   string  `json:"hostname"`
		LocalPortMax               float64 `json:"local_port_max"`
		LocalPortMin               float64 `json:"local_port_min"`
		Master                     string  `json:"master"`
		MesosRole                  string  `json:"mesos_role"`
		MesosUser                  string  `json:"mesos_user"`
		ReconciliationInitialDelay float64 `json:"reconciliation_initial_delay"`
		ReconciliationInterval     float64 `json:"reconciliation_interval"`
		TaskLaunchTimeout          float64 `json:"task_launch_timeout"`
	} `json:"marathon_config"`
	Name            string `json:"name"`
	Version         string `json:"version"`
	ZookeeperConfig struct {
		Zk              string `json:"zk"`
		ZkFutureTimeout struct {
			Duration float64 `json:"duration"`
		} `json:"zk_future_timeout"`
		ZkHosts   string  `json:"zk_hosts"`
		ZkPath    string  `json:"zk_path"`
		ZkState   string  `json:"zk_state"`
		ZkTimeout float64 `json:"zk_timeout"`
	} `json:"zookeeper_config"`
}

// Info retrieves the info stats from marathon
func (r *marathonClient) Info() (*Info, error) {
	info := new(Info)
	if err := r.apiGet(marathonAPIInfo, nil, info); err != nil {
		return nil, err
	}

	return info, nil
}

// Leader retrieves the current marathon leader node
func (r *marathonClient) Leader() (string, error) {
	var leader struct {
		Leader string `json:"leader"`
	}
	if err := r.apiGet(marathonAPILeader, nil, &leader); err != nil {
		return "", err
	}

	return leader.Leader, nil
}

// AbdicateLeader abdicates the marathon leadership
func (r *marathonClient) AbdicateLeader() (string, error) {
	var message struct {
		Message string `json:"message"`
	}

	if err := r.apiDelete(marathonAPILeader, nil, &message); err != nil {
		return "", err
	}

	return message.Message, nil
}
<commit_msg>Add more fields to the info.go config field (#250)<commit_after>/*
Copyright 2014 Rohith All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package marathon

// Info is the detailed stats returned from marathon info
type Info struct {
	EventSubscriber struct {
		HTTPEndpoints []string `json:"http_endpoints"`
		Type          string   `json:"type"`
	} `json:"event_subscriber"`
	FrameworkID string `json:"frameworkId"`
	HTTPConfig  struct {
		AssetsPath interface{} `json:"assets_path"`
		HTTPPort   float64     `json:"http_port"`
		HTTPSPort  float64     `json:"https_port"`
	} `json:"http_config"`
	Leader         string `json:"leader"`
	MarathonConfig struct {
		Checkpoint                     bool    `json:"checkpoint"`
		Executor                       string  `json:"executor"`
		FailoverTimeout                float64 `json:"failover_timeout"`
		FrameworkName                  string  `json:"framework_name"`
		Ha                             bool    `json:"ha"`
		Hostname                       string  `json:"hostname"`
		LeaderProxyConnectionTimeoutMs float64 `json:"leader_proxy_connection_timeout_ms"`
		LeaderProxyReadTimeoutMs       float64 `json:"leader_proxy_read_timeout_ms"`
		LocalPortMax                   float64 `json:"local_port_max"`
		LocalPortMin                   float64 `json:"local_port_min"`
		Master                         string  `json:"master"`
		MesosLeaderUIURL               string  `json:"mesos_leader_ui_url"`
		WebUIURL                       string  `json:"webui_url"`
		MesosRole                      string  `json:"mesos_role"`
		MesosUser                      string  `json:"mesos_user"`
		ReconciliationInitialDelay     float64 `json:"reconciliation_initial_delay"`
		ReconciliationInterval         float64 `json:"reconciliation_interval"`
		TaskLaunchTimeout              float64 `json:"task_launch_timeout"`
		TaskReservationTimeout         float64 `json:"task_reservation_timeout"`
	} `json:"marathon_config"`
	Name            string `json:"name"`
	Version         string `json:"version"`
	ZookeeperConfig struct {
		Zk              string `json:"zk"`
		ZkFutureTimeout struct {
			Duration float64 `json:"duration"`
		} `json:"zk_future_timeout"`
		ZkHosts   string  `json:"zk_hosts"`
		ZkPath    string  `json:"zk_path"`
		ZkState   string  `json:"zk_state"`
		ZkTimeout float64 `json:"zk_timeout"`
	} `json:"zookeeper_config"`
}

// Info retrieves the info stats from marathon
func (r *marathonClient) Info() (*Info, error) {
	info := new(Info)
	if err := r.apiGet(marathonAPIInfo, nil, info); err != nil {
		return nil, err
	}

	return info, nil
}

// Leader retrieves the current marathon leader node
func (r *marathonClient) Leader() (string, error) {
	var leader struct {
		Leader string `json:"leader"`
	}
	if err := r.apiGet(marathonAPILeader, nil, &leader); err != nil {
		return "", err
	}

	return leader.Leader, nil
}

// AbdicateLeader abdicates the marathon leadership
func (r *marathonClient) AbdicateLeader() (string, error) {
	var message struct {
		Message string `json:"message"`
	}

	if err := r.apiDelete(marathonAPILeader, nil, &message); err != nil {
		return "", err
	}

	return message.Message, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"
)

type info struct {
	os.FileInfo
	path  string
	depth int
	err   error
	infos []*info
}

//Think/Write pusodue code
//what is the right way to write this function...
func (inf *info) visit(opts *options) (dirs, files int) {
	fi, err := os.Stat(inf.path)
	if err != nil {
		inf.err = err
		return
	}
	inf.FileInfo = fi
	if !fi.IsDir() {
		return 0, 1
	}
	dir, err := os.Open(inf.path)
	if err != nil {
		inf.err = err
		return
	}
	names, err := dir.Readdirnames(-1)
	dir.Close()
	if err != nil {
		inf.err = err
		return
	}
	inf.infos = make([]*info, 0)
	for _, name := range names {
		// "all" option
		if !opts.all && strings.HasPrefix(name, ".") {
			continue
		}
		_inf := &info{
			path:  filepath.Join(inf.path, name),
			depth: inf.depth + 1,
		}
		d, f := _inf.visit(opts)
		// "dirs only" option
		if opts.dirsOnly && !_inf.IsDir() {
			continue
		}
		inf.infos = append(inf.infos, _inf)
		dirs, files = dirs+d, files+f
	}
	return dirs + 1, files
}

func (inf *info) print(indent string) {
	if inf.err != nil {
		err := strings.Split(inf.err.Error(), ": ")[1]
		fmt.Printf("%s [%s]\n", inf.path, err)
		return
	}
	if inf.depth == 0 {
		fmt.Println(inf.path)
	} else {
		fmt.Println(inf.Name())
	}
	add := "│   "
	for i, _inf := range inf.infos {
		if i == len(inf.infos)-1 {
			fmt.Printf(indent + "└── ")
			add = "    "
		} else {
			fmt.Printf(indent + "├── ")
		}
		_inf.print(indent + add)
	}
}
<commit_msg>add full path<commit_after>package main

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"
)

type info struct {
	os.FileInfo
	path  string
	depth int
	err   error
	infos []*info
}

//Think/Write pusodue code
//what is the right way to write this function...
func (inf *info) visit(opts *options) (dirs, files int) {
	fi, err := os.Stat(inf.path)
	if err != nil {
		inf.err = err
		return
	}
	inf.FileInfo = fi
	if !fi.IsDir() {
		return 0, 1
	}
	dir, err := os.Open(inf.path)
	if err != nil {
		inf.err = err
		return
	}
	names, err := dir.Readdirnames(-1)
	dir.Close()
	if err != nil {
		inf.err = err
		return
	}
	inf.infos = make([]*info, 0)
	for _, name := range names {
		// "all" option
		if !opts.all && strings.HasPrefix(name, ".") {
			continue
		}
		_inf := &info{
			path:  filepath.Join(inf.path, name),
			depth: inf.depth + 1,
		}
		d, f := _inf.visit(opts)
		// "dirs only" option
		if opts.dirsOnly && !_inf.IsDir() {
			continue
		}
		inf.infos = append(inf.infos, _inf)
		dirs, files = dirs+d, files+f
	}
	return dirs + 1, files
}

func (inf *info) print(indent string, opts *options) {
	if inf.err != nil {
		err := strings.Split(inf.err.Error(), ": ")[1]
		fmt.Printf("%s [%s]\n", inf.path, err)
		return
	}
	// Print name/path
	if inf.depth == 0 || opts.fullPath {
		fmt.Println(inf.path)
	} else {
		fmt.Println(inf.Name())
	}
	add := "│   "
	for i, _inf := range inf.infos {
		if i == len(inf.infos)-1 {
			fmt.Printf(indent + "└── ")
			add = "    "
		} else {
			fmt.Printf(indent + "├── ")
		}
		_inf.print(indent+add, opts)
	}
}
<|endoftext|>


<commit_before>package cli

import (
	"github.com/centurylinkcloud/clc-go-cli/base"
	"github.com/centurylinkcloud/clc-go-cli/commands"
	"github.com/centurylinkcloud/clc-go-cli/models"
	"github.com/centurylinkcloud/clc-go-cli/models/datacenter"
	"github.com/centurylinkcloud/clc-go-cli/models/group"
	"github.com/centurylinkcloud/clc-go-cli/models/server"
)

var AllCommands []base.Command = make([]base.Command, 0)

func init() {
	registerCommandBase(&server.CreateReq{}, &server.ServerRes{}, commands.CommandExcInfo{
		Verb:     "POST",
		Url:      "https://api.ctl.io/v2/servers/{accountAlias}",
		Resource: "server",
		Command:  "create",
	})
	registerCommandBase(&server.DeleteReq{}, &server.ServerRes{}, commands.CommandExcInfo{
		Verb:     "DELETE",
		Url:      "https://api.ctl.io/v2/servers/{accountAlias}/{ServerId}",
		Resource: "server",
		Command:  "delete",
	})
	registerCommandBase(&server.UpdateReq{}, &models.LinkEntity{}, commands.CommandExcInfo{
		Verb:     "PATCH",
		Url:      "https://api.ctl.io/v2/servers/{accountAlias}/{ServerId}",
		Resource: "server",
		Command:  "update",
	})
	registerCommandBase(&server.GetReq{}, &server.GetRes{}, commands.CommandExcInfo{
		Verb:     "GET",
		Url:      "https://api.ctl.io/v2/servers/{accountAlias}/{ServerId}",
		Resource: "server",
		Command:  "get",
	})
	registerCommandBase(&server.GetCredentialsReq{}, &server.GetCredentialsRes{}, commands.CommandExcInfo{
		Verb:     "GET",
		Url:      "https://api.ctl.io/v2/servers/{accountAlias}/{ServerId}/credentials",
		Resource: "server",
		Command:  "get-credentials",
	})
	registerCommandBase(&server.GetImportsReq{}, &server.GetImportsRes{}, commands.CommandExcInfo{
		Verb:     "GET",
		Url:      "https://api.ctl.io/v2/vmImport/{accountAlias}/{LocationId}/available",
		Resource: "server",
		Command:  "get-imports",
	})
	registerCommandBase(&server.GetIPAddressReq{}, &server.GetIPAddressRes{}, commands.CommandExcInfo{
		Verb:     "GET",
		Url:      "https://api.ctl.io/v2/servers/{accountAlias}/{ServerId}/publicIPAddresses/{PublicIp}",
		Resource: "server",
		Command:  "get-public-ip-address",
	})
	registerCommandBase(&server.AddIPAddressReq{}, &models.LinkEntity{}, commands.CommandExcInfo{
		Verb:     "POST",
		Url:      "https://api.ctl.io/v2/servers/{accountAlias}/{ServerId}/publicIPAddresses",
		Resource: "server",
		Command:  "add-public-ip-address",
	})
	registerCommandBase(&server.RemoveIPAddressReq{}, &models.LinkEntity{}, commands.CommandExcInfo{
		Verb:     "DELETE",
		Url:      "https://api.ctl.io/v2/servers/{accountAlias}/{ServerId}/publicIPAddresses/{PublicIp}",
		Resource: "server",
		Command:  "remove-public-ip-address",
	})
	registerCommandBase(&server.UpdateIPAddressReq{}, &models.LinkEntity{}, commands.CommandExcInfo{
		Verb:     "PUT",
		Url:      "https://api.ctl.io/v2/servers/{accountAlias}/{ServerId}/publicIPAddresses/{PublicIp}",
		Resource: "server",
		Command:  "update-public-ip-address",
	})
	registerCommandBase(&server.PowerReq{}, &[]server.ServerRes{}, commands.CommandExcInfo{
		Verb:     "POST",
		Url:      "https://api.ctl.io/v2/operations/{accountAlias}/servers/powerOn",
		Resource: "server",
		Command:  "power-on",
	})
	registerCommandBase(&server.PowerReq{}, &[]server.ServerRes{}, commands.CommandExcInfo{
		Verb:     "POST",
		Url:      "https://api.ctl.io/v2/operations/{accountAlias}/servers/powerOff",
		Resource: "server",
		Command:  "power-off",
	})
	registerCommandBase(&server.PowerReq{}, &[]server.ServerRes{}, commands.CommandExcInfo{
		Verb:     "POST",
		Url:      "https://api.ctl.io/v2/operations/{accountAlias}/servers/pause",
		Resource: "server",
		Command:  "pause",
	})
	registerCommandBase(&server.PowerReq{}, &[]server.ServerRes{}, commands.CommandExcInfo{
		Verb:     "POST",
		Url:      "https://api.ctl.io/v2/operations/{accountAlias}/servers/reset",
		Resource: "server",
		Command:  "reset",
	})
	registerCommandBase(&server.PowerReq{}, &[]server.ServerRes{}, commands.CommandExcInfo{
		Verb:     "POST",
		Url:      "https://api.ctl.io/v2/operations/{accountAlias}/servers/shutDown",
		Resource: "server",
		Command:  "shut-down",
	})
	registerCommandBase(&server.PowerReq{}, &[]server.ServerRes{}, commands.CommandExcInfo{
		Verb:     "POST",
		Url:      "https://api.ctl.io/v2/operations/{accountAlias}/servers/archive",
		Resource: "server",
		Command:  "archive",
	})
	registerCommandBase(&server.RestoreReq{}, &models.LinkEntity{}, commands.CommandExcInfo{
		Verb:     "POST",
		Url:      "https://api.ctl.io/v2/servers/{accountAlias}/{ServerId}/restore",
		Resource: "server",
		Command:  "restore",
	})
	registerCommandBase(&server.CreateSnapshotReq{}, &[]server.ServerRes{}, commands.CommandExcInfo{
		Verb:     "POST",
		Url:      "https://api.ctl.io/v2/operations/{accountAlias}/servers/createSnapshot",
		Resource: "server",
		Command:  "create-snapshot",
	})
	registerCommandBase(&server.RevertToSnapshotReq{}, &models.LinkEntity{}, commands.CommandExcInfo{
		Verb:     "POST",
		Url:      "https://api.ctl.io/v2/servers/{accountAlias}/{ServerId}/snapshots/{SnapshotId}/restore",
		Resource: "server",
		Command:  "revert-to-snapshot",
	})
	registerCommandBase(&server.DeleteSnapshotReq{}, &models.LinkEntity{}, commands.CommandExcInfo{
		Verb:     "DELETE",
		Url:      "https://api.ctl.io/v2/servers/{accountAlias}/{ServerId}/snapshots/{SnapshotId}",
		Resource: "server",
		Command:  "delete-snapshot",
	})

	registerCommandBase(&group.GetReq{}, &group.Entity{}, commands.CommandExcInfo{
		Verb:     "GET",
		Url:      "https://api.ctl.io/v2/groups/{accountAlias}/{GroupId}",
		Resource: "group",
		Command:  "get",
	})

	registerCommandBase(&datacenter.ListReq{}, &[]datacenter.ListRes{}, commands.CommandExcInfo{
		Verb:     "GET",
		Url:      "https://api.ctl.io/v2/datacenters/{accountAlias}",
		Resource: "data-center",
		Command:  "list",
	})
	registerCommandBase(&datacenter.GetReq{}, &datacenter.GetRes{}, commands.CommandExcInfo{
		Verb:     "GET",
		Url:      "https://api.ctl.io/v2/datacenters/{accountAlias}/{DataCenter}?groupLinks={GroupLinks}",
		Resource: "data-center",
		Command:  "get",
	})
}

func registerCommandBase(inputModel interface{}, outputModel interface{}, info commands.CommandExcInfo) {
	cmd := &commands.CommandBase{
		Input:   inputModel,
		Output:  outputModel,
		ExcInfo: info,
	}
	AllCommands = append(AllCommands, cmd)
}
<commit_msg>Add a function for registering commands that are not of the CommandBase type.<commit_after>package cli

import (
	"github.com/centurylinkcloud/clc-go-cli/base"
	"github.com/centurylinkcloud/clc-go-cli/commands"
	"github.com/centurylinkcloud/clc-go-cli/models"
	"github.com/centurylinkcloud/clc-go-cli/models/datacenter"
	"github.com/centurylinkcloud/clc-go-cli/models/group"
	"github.com/centurylinkcloud/clc-go-cli/models/server"
)

var AllCommands []base.Command = make([]base.Command, 0)

func init() {
	registerCommandBase(&server.CreateReq{}, &server.ServerRes{}, commands.CommandExcInfo{
		Verb:     "POST",
		Url:      "https://api.ctl.io/v2/servers/{accountAlias}",
		Resource: "server",
		Command:  "create",
	})
	registerCommandBase(&server.DeleteReq{}, &server.ServerRes{}, commands.CommandExcInfo{
		Verb:     "DELETE",
		Url:      "https://api.ctl.io/v2/servers/{accountAlias}/{ServerId}",
		Resource: "server",
		Command:  "delete",
	})
	registerCommandBase(&server.UpdateReq{}, &models.LinkEntity{}, commands.CommandExcInfo{
		Verb:     "PATCH",
		Url:      "https://api.ctl.io/v2/servers/{accountAlias}/{ServerId}",
		Resource: "server",
		Command:  "update",
	})
	registerCommandBase(&server.GetReq{}, &server.GetRes{}, commands.CommandExcInfo{
		Verb:     "GET",
		Url:      "https://api.ctl.io/v2/servers/{accountAlias}/{ServerId}",
		Resource: "server",
		Command:  "get",
	})
	registerCommandBase(&server.GetCredentialsReq{}, &server.GetCredentialsRes{}, commands.CommandExcInfo{
		Verb:     "GET",
		Url:      "https://api.ctl.io/v2/servers/{accountAlias}/{ServerId}/credentials",
		Resource: "server",
		Command:  "get-credentials",
	})
	registerCommandBase(&server.GetImportsReq{}, &server.GetImportsRes{}, commands.CommandExcInfo{
		Verb:     "GET",
		Url:      "https://api.ctl.io/v2/vmImport/{accountAlias}/{LocationId}/available",
		Resource: "server",
		Command:  "get-imports",
	})
	registerCommandBase(&server.GetIPAddressReq{}, &server.GetIPAddressRes{}, commands.CommandExcInfo{
		Verb:     "GET",
		Url:      "https://api.ctl.io/v2/servers/{accountAlias}/{ServerId}/publicIPAddresses/{PublicIp}",
		Resource: "server",
		Command:  "get-public-ip-address",
	})
	registerCommandBase(&server.AddIPAddressReq{}, &models.LinkEntity{}, commands.CommandExcInfo{
		Verb:     "POST",
		Url:      "https://api.ctl.io/v2/servers/{accountAlias}/{ServerId}/publicIPAddresses",
		Resource: "server",
		Command:  "add-public-ip-address",
	})
	registerCommandBase(&server.RemoveIPAddressReq{}, &models.LinkEntity{}, commands.CommandExcInfo{
		Verb:     "DELETE",
		Url:      "https://api.ctl.io/v2/servers/{accountAlias}/{ServerId}/publicIPAddresses/{PublicIp}",
		Resource: "server",
		Command:  "remove-public-ip-address",
	})
	registerCommandBase(&server.UpdateIPAddressReq{}, &models.LinkEntity{}, commands.CommandExcInfo{
		Verb:     "PUT",
		Url:      "https://api.ctl.io/v2/servers/{accountAlias}/{ServerId}/publicIPAddresses/{PublicIp}",
		Resource: "server",
		Command:  "update-public-ip-address",
	})
	registerCommandBase(&server.PowerReq{}, &[]server.ServerRes{}, commands.CommandExcInfo{
		Verb:     "POST",
		Url:      "https://api.ctl.io/v2/operations/{accountAlias}/servers/powerOn",
		Resource: "server",
		Command:  "power-on",
	})
	registerCommandBase(&server.PowerReq{}, &[]server.ServerRes{}, commands.CommandExcInfo{
		Verb:     "POST",
		Url:      "https://api.ctl.io/v2/operations/{accountAlias}/servers/powerOff",
		Resource: "server",
		Command:  "power-off",
	})
	registerCommandBase(&server.PowerReq{}, &[]server.ServerRes{}, commands.CommandExcInfo{
		Verb:     "POST",
		Url:      "https://api.ctl.io/v2/operations/{accountAlias}/servers/pause",
		Resource: "server",
		Command:  "pause",
	})
	registerCommandBase(&server.PowerReq{}, &[]server.ServerRes{}, commands.CommandExcInfo{
		Verb:     "POST",
		Url:      "https://api.ctl.io/v2/operations/{accountAlias}/servers/reset",
		Resource: "server",
		Command:  "reset",
	})
	registerCommandBase(&server.PowerReq{}, &[]server.ServerRes{}, commands.CommandExcInfo{
		Verb:     "POST",
		Url:      "https://api.ctl.io/v2/operations/{accountAlias}/servers/shutDown",
		Resource: "server",
		Command:  "shut-down",
	})
	registerCommandBase(&server.PowerReq{}, &[]server.ServerRes{}, commands.CommandExcInfo{
		Verb:     "POST",
		Url:      "https://api.ctl.io/v2/operations/{accountAlias}/servers/archive",
		Resource: "server",
		Command:  "archive",
	})
	registerCommandBase(&server.RestoreReq{}, &models.LinkEntity{}, commands.CommandExcInfo{
		Verb:     "POST",
		Url:      "https://api.ctl.io/v2/servers/{accountAlias}/{ServerId}/restore",
		Resource: "server",
		Command:  "restore",
	})
	registerCommandBase(&server.CreateSnapshotReq{}, &[]server.ServerRes{}, commands.CommandExcInfo{
		Verb:     "POST",
		Url:      "https://api.ctl.io/v2/operations/{accountAlias}/servers/createSnapshot",
		Resource: "server",
		Command:  "create-snapshot",
	})
	registerCommandBase(&server.RevertToSnapshotReq{}, &models.LinkEntity{}, commands.CommandExcInfo{
		Verb:     "POST",
		Url:      "https://api.ctl.io/v2/servers/{accountAlias}/{ServerId}/snapshots/{SnapshotId}/restore",
		Resource: "server",
		Command:  "revert-to-snapshot",
	})
	registerCommandBase(&server.DeleteSnapshotReq{}, &models.LinkEntity{}, commands.CommandExcInfo{
		Verb:     "DELETE",
		Url:      "https://api.ctl.io/v2/servers/{accountAlias}/{ServerId}/snapshots/{SnapshotId}",
		Resource: "server",
		Command:  "delete-snapshot",
	})

	registerCommandBase(&group.GetReq{}, &group.Entity{}, commands.CommandExcInfo{
		Verb:     "GET",
		Url:      "https://api.ctl.io/v2/groups/{accountAlias}/{GroupId}",
		Resource: "group",
		Command:  "get",
	})

	registerCommandBase(&datacenter.ListReq{}, &[]datacenter.ListRes{}, commands.CommandExcInfo{
		Verb:     "GET",
		Url:      "https://api.ctl.io/v2/datacenters/{accountAlias}",
		Resource: "data-center",
		Command:  "list",
	})
	registerCommandBase(&datacenter.GetReq{}, &datacenter.GetRes{}, commands.CommandExcInfo{
		Verb:     "GET",
		Url:      "https://api.ctl.io/v2/datacenters/{accountAlias}/{DataCenter}?groupLinks={GroupLinks}",
		Resource: "data-center",
		Command:  "get",
	})
}

func registerCommandBase(inputModel interface{}, outputModel interface{}, info commands.CommandExcInfo) {
	cmd := &commands.CommandBase{
		Input:   inputModel,
		Output:  outputModel,
		ExcInfo: info,
	}
	AllCommands = append(AllCommands, cmd)
}

func registerCustomCommand(cmd base.Command) {
	AllCommands = append(AllCommands, cmd)
}
<|endoftext|>


<commit_before>package main

import "github.com/hopkinsth/lambda-phage/Godeps/_workspace/src/gopkg.in/yaml.v2"
import "github.com/hopkinsth/lambda-phage/Godeps/_workspace/src/github.com/spf13/cobra"
import "github.com/hopkinsth/lambda-phage/Godeps/_workspace/src/github.com/peterh/liner"
import "strconv"
import "strings"
import "fmt"
import "io/ioutil"
import "os"

func init() {
	initCmd := &cobra.Command{
		Use:   "init",
		Short: "initializes a config for your function",
		Run:   initPhage,
	}

	cmds = append(cmds, initCmd)
}

type prompt struct {
	text           string
	def            string
	stringStore    **string
	stringSetStore *[]*string
	intStore       **int64
}

// helps you build a config file
func initPhage(c *cobra.Command, _ []string) {
	l := liner.NewLiner()

	fmt.Println(`
		HELLO AND WELCOME

		This command will help you set up your code for deployment to lambda!
		Please answer the prompts as they appear below:
	`)

	//reqMsg := "Sorry, that field is required. Try again."

	cfg := new(Config)
	cfg.IamRole = new(IamRole)
	cfg.Location = new(Location)
	wd, _ := os.Getwd()
	st, _ := os.Stat(wd)

	prompts := []prompt{
		prompt{
			"Enter a project name",
			st.Name(),
			&cfg.Name,
			nil,
			nil,
		},
		prompt{
			"Enter a project description if you'd like",
			"",
			&cfg.Description,
			nil,
			nil,
		},
		prompt{
			"Enter an archive name if you'd like",
			st.Name() + ".zip",
			&cfg.Archive,
			nil,
			nil,
		},
		prompt{
			"What runtime are you using: nodejs, java8, or python 2.7?",
			"nodejs",
			&cfg.Runtime,
			nil,
			nil,
		},

		prompt{
			"Enter an entry point or handler name",
			"index.handler",
			&cfg.EntryPoint,
			nil,
			nil,
		},

		prompt{
			"Enter memory size",
			"128",
			nil,
			nil,
			&cfg.MemorySize,
		},
		prompt{
			"Enter timeout",
			"5",
			nil,
			nil,
			&cfg.Timeout,
		},
		prompt{
			"Enter AWS regions where this function will run",
			"us-east-1",
			nil,
			&cfg.Regions,
			nil,
		},
		prompt{
			"Enter IAM role name",
			"us-east-1",
			&cfg.IamRole.Name,
			nil,
			nil,
		},
	}

	for _, cPrompt := range prompts {
		p := cPrompt
		text := p.text
		if p.def != "" {
			text += " [" + p.def + "]"
		}

		text += ": "
		if s, err := l.Prompt(text); err == nil {
			input := s
			hasInput := input != ""
			if p.stringStore != nil {
				if hasInput {
					*p.stringStore = &input
				} else {
					*p.stringStore = &p.def
				}

			} else if p.stringSetStore != nil {
				var splitMe string
				if hasInput {
					splitMe = input
				} else {
					splitMe = p.def
				}

				spl := strings.Split(splitMe, ",")
				pspl := make([]*string, len(spl))
				for i, v := range spl {
					// we need to set the value
					// in a variable local to this block
					// because the pointed-to value in
					// `v` will change on the next
					// loop iteration
					realVal := v
					pspl[i] = &realVal
				}

				*p.stringSetStore = pspl

			} else if p.intStore != nil {
				var tParse string
				if hasInput {
					tParse = input
				} else {
					tParse = p.def
				}

				i, _ := strconv.ParseInt(tParse, 10, 64)
				*p.intStore = &i
			}
		} else if err == liner.ErrPromptAborted {
			fmt.Println("Aborted")
			return
		} else {
			fmt.Println("Error reading line: ", err)
			return
		}
	}

	l.Close()

	d, err := yaml.Marshal(cfg)
	if err != nil {
		panic(err)
	}
	ioutil.WriteFile("l-p.yml", d, os.FileMode(0644))
}
<commit_msg>use slightly cleaner method for declaring prompts<commit_after>package main

import "github.com/hopkinsth/lambda-phage/Godeps/_workspace/src/gopkg.in/yaml.v2"
import "github.com/hopkinsth/lambda-phage/Godeps/_workspace/src/github.com/spf13/cobra"
import "github.com/hopkinsth/lambda-phage/Godeps/_workspace/src/github.com/peterh/liner"
import "strconv"
import "strings"
import "fmt"
import "io/ioutil"
import "os"

func init() {
	initCmd := &cobra.Command{
		Use:   "init",
		Short: "initializes a config for your function",
		Run:   initPhage,
	}

	cmds = append(cmds, initCmd)
}

type prompt struct {
	text           string
	def            string
	required       bool
	stringStore    **string
	stringSetStore *[]*string
	intStore       **int64
	funcStore      func(interface{})
}

func newPrompt() *prompt {
	return new(prompt)
}

func (p *prompt) isRequired() *prompt {
	p.required = true
	return p
}

func (p *prompt) setDef(d string) *prompt {
	p.def = d
	return p
}

func (p *prompt) setText(t string) *prompt {
	p.text = t
	return p
}

func (p *prompt) withString(s **string) *prompt {
	p.stringStore = s
	return p
}

func (p *prompt) withStringSet(s *[]*string) *prompt {
	p.stringSetStore = s
	return p
}

func (p *prompt) withInt(s **int64) *prompt {
	p.intStore = s
	return p
}

func (p *prompt) withFunc(s func(interface{})) *prompt {
	p.funcStore = s
	return p
}

// helps you build a config file
func initPhage(c *cobra.Command, _ []string) {
	l := liner.NewLiner()

	fmt.Println(`
		HELLO AND WELCOME

		This command will help you set up your code for deployment to lambda!
		Please answer the prompts as they appear below:
	`)

	//reqMsg := "Sorry, that field is required. Try again."

	cfg := new(Config)
	cfg.IamRole = new(IamRole)
	cfg.Location = new(Location)
	wd, _ := os.Getwd()
	st, _ := os.Stat(wd)

	prompts := []*prompt{
		newPrompt().
			withString(&cfg.Name).
			setText("Enter a project name").
			setDef(st.Name()),
		newPrompt().
			withString(&cfg.Description).
			setText("Enter a project description if you'd like").
			setDef(""),
		newPrompt().
			withString(&cfg.Archive).
			setText("Enter a archive name if you'd like").
			setDef(st.Name() + ".zip"),
		newPrompt().
			withString(&cfg.Runtime).
			setText("What runtime are you using: nodejs, java8, or python 2.7?").
			setDef("nodejs"),
		newPrompt().
			withString(&cfg.EntryPoint).
			setText("Enter an entry point or handler name").
			setDef("index.handler"),
		newPrompt().
			withInt(&cfg.MemorySize).
			setText("Enter memory size").
			setDef("128"),
		newPrompt().
			withInt(&cfg.Timeout).
			setText("Enter timeout").
			setDef("5"),
		newPrompt().
			withStringSet(&cfg.Regions).
			setText("Enter AWS regions where this function will run").
			setDef("us-east-1"),
		newPrompt().
			withString(&cfg.IamRole.Name).
			isRequired().
			setText("Enter IAM role name").
			setDef(""),
	}

	for _, cPrompt := range prompts {
		p := cPrompt
		text := p.text
		if p.def != "" {
			text += " [" + p.def + "]"
		}

		text += ": "
		if s, err := l.Prompt(text); err == nil {
			input := s
			hasInput := input != ""
			if p.stringStore != nil {
				if hasInput {
					*p.stringStore = &input
				} else {
					*p.stringStore = &p.def
				}

			} else if p.stringSetStore != nil {
				var splitMe string
				if hasInput {
					splitMe = input
				} else {
					splitMe = p.def
				}

				spl := strings.Split(splitMe, ",")
				pspl := make([]*string, len(spl))
				for i, v := range spl {
					// we need to set the value
					// in a variable local to this block
					// because the pointed-to value in
					// `v` will change on the next
					// loop iteration
					realVal := v
					pspl[i] = &realVal
				}

				*p.stringSetStore = pspl

			} else if p.intStore != nil {
				var tParse string
				if hasInput {
					tParse = input
				} else {
					tParse = p.def
				}

				i, _ := strconv.ParseInt(tParse, 10, 64)
				*p.intStore = &i
			}
		} else if err == liner.ErrPromptAborted {
			fmt.Println("Aborted")
			return
		} else {
			fmt.Println("Error reading line: ", err)
			return
		}
	}

	l.Close()

	d, err := yaml.Marshal(cfg)
	if err != nil {
		panic(err)
	}
	ioutil.WriteFile("l-p.yml", d, os.FileMode(0644))
}
<|endoftext|>


<commit_before>// Copyright 2013 Jongmin Kim. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.

package helloworld

import (
	"fmt"
	"net/http"
)

func init() {
	http.HandleFunc("/", handle)
}

func handle(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "Hello, World! 세상아 안녕!")
}
<commit_msg>test pre git commit<commit_after>// Copyright 2013 Jongmin Kim. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package geoip

import (
	"fmt"
	"net/http"
)

func init() {
	http.HandleFunc("/", handle)
}

func handle(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "Hello, World! 세상아 안녕!")
}
<|endoftext|>