<commit_before>// Copyright 2016 Factom Foundation
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package main

import (
	"flag"
	"fmt"
	"os"
	"strconv"

	"github.com/FactomProject/factom"
)

// newtx creates a new transaction in the wallet.
var newtx = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli newtx TXNAME"
	cmd.description = "Create a new transaction in the wallet"
	cmd.execFunc = func(args []string) {
		os.Args = args
		flag.Parse()
		args = flag.Args()

		if len(args) != 1 {
			fmt.Println(cmd.helpMsg)
			return
		}
		if err := factom.NewTransaction(args[0]); err != nil {
			errorln(err)
			return
		}
	}
	help.Add("newtx", cmd)
	return cmd
}()

// rmtx removes a transaction in the wallet.
var rmtx = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli rmtx TXNAME"
	cmd.description = "Remove a transaction in the wallet"
	cmd.execFunc = func(args []string) {
		os.Args = args
		flag.Parse()
		args = flag.Args()

		if len(args) != 1 {
			fmt.Println(cmd.helpMsg)
			return
		}
		if err := factom.DeleteTransaction(args[0]); err != nil {
			errorln(err)
			return
		}
	}
	help.Add("rmtx", cmd)
	return cmd
}()

// listtxs lists the working transactions in the wallet.
var listtxs = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli listtxs"
	cmd.description = "List current working transactions in the wallet"
	cmd.execFunc = func(args []string) {
		os.Args = args
		flag.Parse()
		args = flag.Args()

		txs, err := factom.ListTransactions()
		if err != nil {
			errorln(err)
			return
		}
		for _, tx := range txs {
			fmt.Println("{")
			fmt.Println("	Name:", tx.Name)
			fmt.Println("	TxID:", tx.TxID)
			fmt.Println("	TotalInputs:", tx.TotalInputs)
			fmt.Println("	TotalOutputs:", tx.TotalOutputs)
			fmt.Println("	TotalECOutputs:", tx.TotalECOutputs)
			fmt.Println("}")
		}
	}
	help.Add("listtxs", cmd)
	return cmd
}()

// addtxinput adds a factoid input to a transaction in the wallet.
var addtxinput = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli addtxinput TXNAME ADDRESS AMOUNT"
	cmd.description = "Add a Factoid input to a transaction in the wallet"
	cmd.execFunc = func(args []string) {
		os.Args = args
		flag.Parse()
		args = flag.Args()

		if len(args) != 3 {
			fmt.Println(cmd.helpMsg)
			return
		}
		var amt uint64
		if i, err := strconv.ParseFloat(args[2], 64); err != nil {
			errorln(err)
		} else if i < 0 {
			errorln("AMMOUNT may not be less than 0")
		} else {
			amt = uint64(i * 1e8)
		}
		if err := factom.AddTransactionInput(args[0], args[1], amt); err != nil {
			errorln(err)
			return
		}
	}
	help.Add("addtxinput", cmd)
	return cmd
}()

// addtxoutput adds a factoid output to a transaction in the wallet.
var addtxoutput = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli addtxoutput TXNAME ADDRESS AMOUNT"
	cmd.description = "Add a Factoid output to a transaction in the wallet"
	cmd.execFunc = func(args []string) {
		os.Args = args
		flag.Parse()
		args = flag.Args()

		if len(args) != 3 {
			fmt.Println(cmd.helpMsg)
			return
		}
		var amt uint64
		if i, err := strconv.ParseFloat(args[2], 64); err != nil {
			errorln(err)
		} else if i < 0 {
			errorln("AMMOUNT may not be less than 0")
		} else {
			amt = uint64(i * 1e8)
		}
		if err := factom.AddTransactionOutput(args[0], args[1], amt); err != nil {
			errorln(err)
			return
		}
	}
	help.Add("addtxoutput", cmd)
	return cmd
}()

// addtxecoutput adds an entry credit output to a transaction in the wallet.
var addtxecoutput = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli addtxecoutput TXNAME ADDRESS AMOUNT"
	cmd.description = "Add an Entry Credit output to a transaction in the wallet"
	cmd.execFunc = func(args []string) {
		os.Args = args
		flag.Parse()
		args = flag.Args()

		if len(args) != 3 {
			fmt.Println(cmd.helpMsg)
			return
		}
		var amt uint64
		if i, err := strconv.ParseFloat(args[2], 64); err != nil {
			errorln(err)
		} else if i < 0 {
			errorln("AMMOUNT may not be less than 0")
		} else {
			amt = uint64(i * 1e8)
		}
		if err := factom.AddTransactionECOutput(args[0], args[1], amt); err != nil {
			errorln(err)
			return
		}
	}
	help.Add("addtxecoutput", cmd)
	return cmd
}()

// addtxfee adds an entry credit output to a transaction in the wallet.
var addtxfee = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli addtxfee TXNAME ADDRESS"
	cmd.description = "Add the transaction fee to an input of a transaction in the wallet"
	cmd.execFunc = func(args []string) {
		os.Args = args
		flag.Parse()
		args = flag.Args()

		if len(args) != 2 {
			fmt.Println(cmd.helpMsg)
			return
		}
		if err := factom.AddTransactionFee(args[0], args[1]); err != nil {
			errorln(err)
			return
		}
	}
	help.Add("addtxfee", cmd)
	return cmd
}()

// subtxfee adds an entry credit output to a transaction in the wallet.
var subtxfee = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli subtxfee TXNAME ADDRESS"
	cmd.description = "Subtract the transaction fee from an output of a transaction in the wallet"
	cmd.execFunc = func(args []string) {
		os.Args = args
		flag.Parse()
		args = flag.Args()

		if len(args) != 2 {
			fmt.Println(cmd.helpMsg)
			return
		}
		if err := factom.SubTransactionFee(args[0], args[1]); err != nil {
			errorln(err)
			return
		}
	}
	help.Add("subtxfee", cmd)
	return cmd
}()

// signtx signs a transaction in the wallet.
var signtx = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli signtx TXNAME"
	cmd.description = "Sign a transaction in the wallet"
	cmd.execFunc = func(args []string) {
		os.Args = args
		flag.Parse()
		args = flag.Args()

		if len(args) != 1 {
			fmt.Println(cmd.helpMsg)
			return
		}
		if err := factom.SignTransaction(args[0]); err != nil {
			errorln(err)
			return
		}
	}
	help.Add("signtx", cmd)
	return cmd
}()

// composetx composes the signed json rpc object to make a transaction against factomd
var composetx = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli composetx TXNAME"
	cmd.description = "Compose a wallet transaction into a json rpc object"
	cmd.execFunc = func(args []string) {
		os.Args = args
		flag.Parse()
		args = flag.Args()

		if len(args) != 1 {
			fmt.Println(cmd.helpMsg)
			return
		}
		p, err := factom.ComposeTransaction(args[0])
		if err != nil {
			errorln(err)
			return
		}
		fmt.Println(string(p))
	}
	help.Add("composetx", cmd)
	return cmd
}()

// sendtx composes and sends the signed transaction to factomd
var sendtx = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli sendtx TXNAME"
	cmd.description = "Send a Transaction to Factom"
	cmd.execFunc = func(args []string) {
		os.Args = args
		flag.Parse()
		args = flag.Args()

		if len(args) != 1 {
			fmt.Println(cmd.helpMsg)
			return
		}
		t, err := factom.SendTransaction(args[0])
		if err != nil {
			errorln(err)
			return
		}
		fmt.Println("TxID:", t)
	}
	help.Add("sendtx", cmd)
	return cmd
}()

// sendfct sends factoids between 2 addresses
var sendfct = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli sendfct FROMADDRESS TOADDRESS AMMOUNT"
	cmd.description = "Send Factoids between 2 addresses"
	cmd.execFunc = func(args []string) {
		os.Args = args
		flag.Parse()
		args = flag.Args()

		if len(args) != 3 {
			fmt.Println(cmd.helpMsg)
			return
		}
		var amt uint64
		if i, err := strconv.ParseFloat(args[2], 64); err != nil {
			errorln(err)
		} else if i < 0 {
			errorln("AMMOUNT may not be less than 0")
		} else {
			amt = uint64(i * 1e8)
		}
		t, err := factom.SendFactoid(args[0], args[1], amt)
		if err != nil {
			errorln(err)
			return
		}
		fmt.Println("TxID:", t)
	}
	help.Add("sendfct", cmd)
	return cmd
}()

// buyec sends factoids between 2 addresses
var buyec = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli buyec FCTADDRESS ECADDRESS ECAMMOUNT"
	cmd.description = "Buy entry credits"
	cmd.execFunc = func(args []string) {
		os.Args = args
		flag.Parse()
		args = flag.Args()

		if len(args) != 3 {
			fmt.Println(cmd.helpMsg)
			return
		}
		var amt uint64
		if i, err := strconv.Atoi(args[2]); err != nil {
			errorln(err)
			return
		} else if i < 0 {
			errorln("AMMOUNT may not be less than 0")
			return
		} else {
			rate, err := factom.GetRate()
			if err != nil {
				errorln(err)
			}
			amt = uint64(i) * rate
		}
		t, err := factom.BuyEC(args[0], args[1], amt)
		if err != nil {
			errorln(err)
			return
		}
		fmt.Println("TxID:", t)
	}
	help.Add("buyec", cmd)
	return cmd
}()
<commit_msg>print raw tx, show fees, display human readable amounts<commit_after>// Copyright 2016 Factom Foundation
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package main

import (
	"flag"
	"fmt"
	"os"
	"strconv"

	"github.com/FactomProject/factom"
)

// newtx creates a new transaction in the wallet.
var newtx = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli newtx TXNAME"
	cmd.description = "Create a new transaction in the wallet"
	cmd.execFunc = func(args []string) {
		os.Args = args
		flag.Parse()
		args = flag.Args()

		if len(args) != 1 {
			fmt.Println(cmd.helpMsg)
			return
		}
		if err := factom.NewTransaction(args[0]); err != nil {
			errorln(err)
			return
		}
	}
	help.Add("newtx", cmd)
	return cmd
}()

// rmtx removes a transaction in the wallet.
var rmtx = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli rmtx TXNAME"
	cmd.description = "Remove a transaction in the wallet"
	cmd.execFunc = func(args []string) {
		os.Args = args
		flag.Parse()
		args = flag.Args()

		if len(args) != 1 {
			fmt.Println(cmd.helpMsg)
			return
		}
		if err := factom.DeleteTransaction(args[0]); err != nil {
			errorln(err)
			return
		}
	}
	help.Add("rmtx", cmd)
	return cmd
}()

// listtxs lists the working transactions in the wallet.
var listtxs = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli listtxs"
	cmd.description = "List current working transactions in the wallet"
	cmd.execFunc = func(args []string) {
		os.Args = args
		flag.Parse()
		args = flag.Args()

		txs, err := factom.ListTransactions()
		if err != nil {
			errorln(err)
			return
		}
		for _, tx := range txs {
			fmt.Println("{")
			fmt.Println("	Name:", tx.Name)
			fmt.Println("	TxID:", tx.TxID)
			fmt.Println("	TotalInputs:", float64(tx.TotalInputs)/100000000)
			fmt.Println("	TotalOutputs:", float64(tx.TotalOutputs)/100000000)
			fmt.Println("	TotalECOutputs:", float64(tx.TotalECOutputs)/100000000)
			feesPaid := tx.TotalInputs - (tx.TotalOutputs + tx.TotalECOutputs)
			fmt.Println("	FeesPaid:", float64(feesPaid)/100000000)
			fmt.Println("	RawTransaction:", tx.RawTransaction)
			fmt.Println("}")
		}
	}
	help.Add("listtxs", cmd)
	return cmd
}()

// addtxinput adds a factoid input to a transaction in the wallet.
var addtxinput = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli addtxinput TXNAME ADDRESS AMOUNT"
	cmd.description = "Add a Factoid input to a transaction in the wallet"
	cmd.execFunc = func(args []string) {
		os.Args = args
		flag.Parse()
		args = flag.Args()

		if len(args) != 3 {
			fmt.Println(cmd.helpMsg)
			return
		}
		var amt uint64
		if i, err := strconv.ParseFloat(args[2], 64); err != nil {
			errorln(err)
		} else if i < 0 {
			errorln("AMMOUNT may not be less than 0")
		} else {
			amt = uint64(i * 1e8)
		}
		if err := factom.AddTransactionInput(args[0], args[1], amt); err != nil {
			errorln(err)
			return
		}
	}
	help.Add("addtxinput", cmd)
	return cmd
}()

// addtxoutput adds a factoid output to a transaction in the wallet.
var addtxoutput = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli addtxoutput TXNAME ADDRESS AMOUNT"
	cmd.description = "Add a Factoid output to a transaction in the wallet"
	cmd.execFunc = func(args []string) {
		os.Args = args
		flag.Parse()
		args = flag.Args()

		if len(args) != 3 {
			fmt.Println(cmd.helpMsg)
			return
		}
		var amt uint64
		if i, err := strconv.ParseFloat(args[2], 64); err != nil {
			errorln(err)
		} else if i < 0 {
			errorln("AMMOUNT may not be less than 0")
		} else {
			amt = uint64(i * 1e8)
		}
		if err := factom.AddTransactionOutput(args[0], args[1], amt); err != nil {
			errorln(err)
			return
		}
	}
	help.Add("addtxoutput", cmd)
	return cmd
}()

// addtxecoutput adds an entry credit output to a transaction in the wallet.
var addtxecoutput = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli addtxecoutput TXNAME ADDRESS AMOUNT"
	cmd.description = "Add an Entry Credit output to a transaction in the wallet"
	cmd.execFunc = func(args []string) {
		os.Args = args
		flag.Parse()
		args = flag.Args()

		if len(args) != 3 {
			fmt.Println(cmd.helpMsg)
			return
		}
		var amt uint64
		if i, err := strconv.ParseFloat(args[2], 64); err != nil {
			errorln(err)
		} else if i < 0 {
			errorln("AMMOUNT may not be less than 0")
		} else {
			amt = uint64(i * 1e8)
		}
		if err := factom.AddTransactionECOutput(args[0], args[1], amt); err != nil {
			errorln(err)
			return
		}
	}
	help.Add("addtxecoutput", cmd)
	return cmd
}()

// addtxfee adds an entry credit output to a transaction in the wallet.
var addtxfee = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli addtxfee TXNAME ADDRESS"
	cmd.description = "Add the transaction fee to an input of a transaction in the wallet"
	cmd.execFunc = func(args []string) {
		os.Args = args
		flag.Parse()
		args = flag.Args()

		if len(args) != 2 {
			fmt.Println(cmd.helpMsg)
			return
		}
		if err := factom.AddTransactionFee(args[0], args[1]); err != nil {
			errorln(err)
			return
		}
	}
	help.Add("addtxfee", cmd)
	return cmd
}()

// subtxfee adds an entry credit output to a transaction in the wallet.
var subtxfee = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli subtxfee TXNAME ADDRESS"
	cmd.description = "Subtract the transaction fee from an output of a transaction in the wallet"
	cmd.execFunc = func(args []string) {
		os.Args = args
		flag.Parse()
		args = flag.Args()

		if len(args) != 2 {
			fmt.Println(cmd.helpMsg)
			return
		}
		if err := factom.SubTransactionFee(args[0], args[1]); err != nil {
			errorln(err)
			return
		}
	}
	help.Add("subtxfee", cmd)
	return cmd
}()

// signtx signs a transaction in the wallet.
var signtx = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli signtx TXNAME"
	cmd.description = "Sign a transaction in the wallet"
	cmd.execFunc = func(args []string) {
		os.Args = args
		flag.Parse()
		args = flag.Args()

		if len(args) != 1 {
			fmt.Println(cmd.helpMsg)
			return
		}
		if err := factom.SignTransaction(args[0]); err != nil {
			errorln(err)
			return
		}
	}
	help.Add("signtx", cmd)
	return cmd
}()

// composetx composes the signed json rpc object to make a transaction against factomd
var composetx = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli composetx TXNAME"
	cmd.description = "Compose a wallet transaction into a json rpc object"
	cmd.execFunc = func(args []string) {
		os.Args = args
		flag.Parse()
		args = flag.Args()

		if len(args) != 1 {
			fmt.Println(cmd.helpMsg)
			return
		}
		p, err := factom.ComposeTransaction(args[0])
		if err != nil {
			errorln(err)
			return
		}
		fmt.Println(string(p))
	}
	help.Add("composetx", cmd)
	return cmd
}()

// sendtx composes and sends the signed transaction to factomd
var sendtx = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli sendtx TXNAME"
	cmd.description = "Send a Transaction to Factom"
	cmd.execFunc = func(args []string) {
		os.Args = args
		flag.Parse()
		args = flag.Args()

		if len(args) != 1 {
			fmt.Println(cmd.helpMsg)
			return
		}
		t, err := factom.SendTransaction(args[0])
		if err != nil {
			errorln(err)
			return
		}
		fmt.Println("TxID:", t)
	}
	help.Add("sendtx", cmd)
	return cmd
}()

// sendfct sends factoids between 2 addresses
var sendfct = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli sendfct FROMADDRESS TOADDRESS AMMOUNT"
	cmd.description = "Send Factoids between 2 addresses"
	cmd.execFunc = func(args []string) {
		os.Args = args
		flag.Parse()
		args = flag.Args()

		if len(args) != 3 {
			fmt.Println(cmd.helpMsg)
			return
		}
		var amt uint64
		if i, err := strconv.ParseFloat(args[2], 64); err != nil {
			errorln(err)
		} else if i < 0 {
			errorln("AMMOUNT may not be less than 0")
		} else {
			amt = uint64(i * 1e8)
		}
		t, err := factom.SendFactoid(args[0], args[1], amt)
		if err != nil {
			errorln(err)
			return
		}
		fmt.Println("TxID:", t)
	}
	help.Add("sendfct", cmd)
	return cmd
}()

// buyec sends factoids between 2 addresses
var buyec = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli buyec FCTADDRESS ECADDRESS ECAMMOUNT"
	cmd.description = "Buy entry credits"
	cmd.execFunc = func(args []string) {
		os.Args = args
		flag.Parse()
		args = flag.Args()

		if len(args) != 3 {
			fmt.Println(cmd.helpMsg)
			return
		}
		var amt uint64
		if i, err := strconv.Atoi(args[2]); err != nil {
			errorln(err)
			return
		} else if i < 0 {
			errorln("AMMOUNT may not be less than 0")
			return
		} else {
			rate, err := factom.GetRate()
			if err != nil {
				errorln(err)
			}
			amt = uint64(i) * rate
		}
		t, err := factom.BuyEC(args[0], args[1], amt)
		if err != nil {
			errorln(err)
			return
		}
		fmt.Println("TxID:", t)
	}
	help.Add("buyec", cmd)
	return cmd
}()
<|endoftext|>


<commit_before>package resource

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

type ComputeResource struct {
	CPUCount int   `json:"cpuCount,omitempty"`
	CPULevel int   `json:"cpuLevel,omitempty"` // higher number means higher compute power
	MemoryMB int64 `json:"memoryMB,omitempty"`
}

func (a ComputeResource) String() string {
	return fmt.Sprintf("CPUCount %d Level %d Memory %d MB", a.CPUCount, a.CPULevel, a.MemoryMB)
}

func (a ComputeResource) Minus(b ComputeResource) ComputeResource {
	return ComputeResource{
		CPUCount: a.CPUCount - b.CPUCount,
		MemoryMB: a.MemoryMB - b.MemoryMB,
	}
}

func (a ComputeResource) Plus(b ComputeResource) ComputeResource {
	return ComputeResource{
		CPUCount: a.CPUCount + b.CPUCount,
		MemoryMB: a.MemoryMB + b.MemoryMB,
	}
}

func (a ComputeResource) GreaterThanZero() bool {
	return a.CPUCount > 0 && a.MemoryMB > 0
}

func (a ComputeResource) IsZero() bool {
	return a.CPUCount == 0 && a.MemoryMB == 0
}

func (a ComputeResource) Covers(b ComputeResource) bool {
	return a.CPUCount >= b.CPUCount && a.MemoryMB >= b.MemoryMB
}

type ResourceOffer struct {
	ComputeResource
	ServerLocation Location
}

type DataResource struct {
	Location   Location `json:"location,omitempty"`
	DataSizeMB int      `json:"dataSizeMB,omitempty"`
}

type ComputeRequest struct {
	ComputeResource ComputeResource `json:"compute,omitempty"`
	Inputs          []DataResource  `json:"inputs,omitempty"`
}

type Location struct {
	DataCenter string `json:"dataCenter,omitempty"`
	Rack       string `json:"rack,omitempty"`
	Server     string `json:"server,omitempty"`
	Port       int    `json:"port,omitempty"`
}

type Allocation struct {
	Location  Location        `json:"location,omitempty"`
	Allocated ComputeResource `json:"allocated,omitempty"`
}

type AllocationRequest struct {
	Requests []ComputeRequest `json:"requests,omitempty"`
}

type AllocationResult struct {
	Allocations []Allocation `json:"allocations,omitempty"`
	Error       string       `json:"error,omitempty"`
}

func (l *Location) URL() string {
	return l.Server + ":" + strconv.Itoa(l.Port)
}

func (cr *ComputeRequest) MatchScore(ro *ResourceOffer) (score float64, ok bool) {
	c := cr.ComputeResource
	r := ro.ComputeResource
	if c.CPUCount > r.CPUCount ||
		c.CPULevel > r.CPULevel ||
		c.MemoryMB > r.MemoryMB {
		return 0, false
	}
	totalCost := float64(1)
	for _, input := range cr.Inputs {
		if input.DataSizeMB > 0 {
			cost := float64(10000) / float64(input.DataSizeMB)
			cost /= input.Location.Distance(ro.ServerLocation)
			totalCost += cost
		}
	}
	return 100 / totalCost, true
}

// the distance is a relative value, similar to network lantency
func (a Location) Distance(b Location) float64 {
	if a.DataCenter != b.DataCenter {
		return 1000
	}
	if a.Rack != b.Rack {
		return 100
	}
	if a.Server != b.Server {
		return 10
	}
	return 1
}

func AddToValues(values url.Values, c *ComputeResource, allocated *ComputeResource) {
	values.Add("CPUCount", strconv.Itoa(c.CPUCount))
	values.Add("CPULevel", strconv.Itoa(c.CPULevel))
	values.Add("MemoryMB", strconv.FormatInt(c.MemoryMB, 10))
	values.Add("allocated.CPUCount", strconv.Itoa(allocated.CPUCount))
	values.Add("allocated.CPULevel", strconv.Itoa(allocated.CPULevel))
	values.Add("allocated.MemoryMB", strconv.FormatInt(allocated.MemoryMB, 10))
}

func NewComputeResourceFromRequest(r *http.Request) (ComputeResource, ComputeResource) {
	cpuCount, _ := strconv.ParseInt(r.FormValue("CPUCount"), 10, 32)
	cpuLevel, _ := strconv.ParseInt(r.FormValue("CPULevel"), 10, 32)
	memoryMB, _ := strconv.ParseInt(r.FormValue("MemoryMB"), 10, 64)
	availableCpuCount, _ := strconv.ParseInt(r.FormValue("allocated.CPUCount"), 10, 32)
	availableCpuLevel, _ := strconv.ParseInt(r.FormValue("allocated.CPULevel"), 10, 32)
	availableMemoryMB, _ := strconv.ParseInt(r.FormValue("allocated.MemoryMB"), 10, 64)
	return ComputeResource{
			CPUCount: int(cpuCount),
			CPULevel: int(cpuLevel),
			MemoryMB: memoryMB,
		}, ComputeResource{
			CPUCount: int(availableCpuCount),
			CPULevel: int(availableCpuLevel),
			MemoryMB: availableMemoryMB,
		}
}
<commit_msg>remove unused code<commit_after>package resource

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

type ComputeResource struct {
	CPUCount int   `json:"cpuCount,omitempty"`
	CPULevel int   `json:"cpuLevel,omitempty"` // higher number means higher compute power
	MemoryMB int64 `json:"memoryMB,omitempty"`
}

func (a ComputeResource) String() string {
	return fmt.Sprintf("CPUCount %d Level %d Memory %d MB", a.CPUCount, a.CPULevel, a.MemoryMB)
}

func (a ComputeResource) Minus(b ComputeResource) ComputeResource {
	return ComputeResource{
		CPUCount: a.CPUCount - b.CPUCount,
		MemoryMB: a.MemoryMB - b.MemoryMB,
	}
}

func (a ComputeResource) Plus(b ComputeResource) ComputeResource {
	return ComputeResource{
		CPUCount: a.CPUCount + b.CPUCount,
		MemoryMB: a.MemoryMB + b.MemoryMB,
	}
}

func (a ComputeResource) GreaterThanZero() bool {
	return a.CPUCount > 0 && a.MemoryMB > 0
}

func (a ComputeResource) IsZero() bool {
	return a.CPUCount == 0 && a.MemoryMB == 0
}

func (a ComputeResource) Covers(b ComputeResource) bool {
	return a.CPUCount >= b.CPUCount && a.MemoryMB >= b.MemoryMB
}

type ResourceOffer struct {
	ComputeResource
	ServerLocation Location
}

type DataResource struct {
	Location   Location `json:"location,omitempty"`
	DataSizeMB int      `json:"dataSizeMB,omitempty"`
}

type ComputeRequest struct {
	ComputeResource ComputeResource `json:"compute,omitempty"`
	Inputs          []DataResource  `json:"inputs,omitempty"`
}

type Location struct {
	DataCenter string `json:"dataCenter,omitempty"`
	Rack       string `json:"rack,omitempty"`
	Server     string `json:"server,omitempty"`
	Port       int    `json:"port,omitempty"`
}

type Allocation struct {
	Location  Location        `json:"location,omitempty"`
	Allocated ComputeResource `json:"allocated,omitempty"`
}

type AllocationRequest struct {
	Requests []ComputeRequest `json:"requests,omitempty"`
}

type AllocationResult struct {
	Allocations []Allocation `json:"allocations,omitempty"`
	Error       string       `json:"error,omitempty"`
}

func (l *Location) URL() string {
	return l.Server + ":" + strconv.Itoa(l.Port)
}

// the distance is a relative value, similar to network lantency
func (a Location) Distance(b Location) float64 {
	if a.DataCenter != b.DataCenter {
		return 1000
	}
	if a.Rack != b.Rack {
		return 100
	}
	if a.Server != b.Server {
		return 10
	}
	return 1
}

func AddToValues(values url.Values, c *ComputeResource, allocated *ComputeResource) {
	values.Add("CPUCount", strconv.Itoa(c.CPUCount))
	values.Add("CPULevel", strconv.Itoa(c.CPULevel))
	values.Add("MemoryMB", strconv.FormatInt(c.MemoryMB, 10))
	values.Add("allocated.CPUCount", strconv.Itoa(allocated.CPUCount))
	values.Add("allocated.CPULevel", strconv.Itoa(allocated.CPULevel))
	values.Add("allocated.MemoryMB", strconv.FormatInt(allocated.MemoryMB, 10))
}

func NewComputeResourceFromRequest(r *http.Request) (ComputeResource, ComputeResource) {
	cpuCount, _ := strconv.ParseInt(r.FormValue("CPUCount"), 10, 32)
	cpuLevel, _ := strconv.ParseInt(r.FormValue("CPULevel"), 10, 32)
	memoryMB, _ := strconv.ParseInt(r.FormValue("MemoryMB"), 10, 64)
	availableCpuCount, _ := strconv.ParseInt(r.FormValue("allocated.CPUCount"), 10, 32)
	availableCpuLevel, _ := strconv.ParseInt(r.FormValue("allocated.CPULevel"), 10, 32)
	availableMemoryMB, _ := strconv.ParseInt(r.FormValue("allocated.MemoryMB"), 10, 64)
	return ComputeResource{
			CPUCount: int(cpuCount),
			CPULevel: int(cpuLevel),
			MemoryMB: memoryMB,
		}, ComputeResource{
			CPUCount: int(availableCpuCount),
			CPULevel: int(availableCpuLevel),
			MemoryMB: availableMemoryMB,
		}
}
<|endoftext|>


<commit_before>package main

import (
	alks "alks-go"
	"github.com/hashicorp/terraform/helper/schema"
	"log"
)

// TODO: Find a way to NOT store 'secret_key' to TF state file.
func resourceAlksLtk() *schema.Resource {
	return &schema.Resource{
		Create: resourceAlksLtkCreate,
		Read:   resourceAlksLtkRead,
		Delete: resourceAlksLtkDelete,

		SchemaVersion: 1,
		MigrateState:  migrateState,

		Schema: map[string]*schema.Schema{
			"iam_username": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"account_id": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"role_name": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"account": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
			"role": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
			"action": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
			"added_iam_user_to_group": &schema.Schema{
				Type:     schema.TypeBool,
				Computed: true,
			},
			"partial_error": &schema.Schema{
				Type:     schema.TypeBool,
				Computed: true,
			},
			"iam_user_arn": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
			"access_key": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
			"secret_key": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
			"ltks": &schema.Schema{
				Type:     schema.TypeMap,
				Computed: true,
			},
		},
	}
}

func resourceAlksLtkCreate(d *schema.ResourceData, meta interface{}) error {
	log.Printf("[INFO] ALKS LTK User Create")

	var iamUsername = d.Get("iam_username").(string)

	client := meta.(*alks.Client)
	resp, err := client.CreateLongTermKey(iamUsername)

	if err != nil {
		return err
	}

	d.SetId(resp.Account)
	d.Set("role", resp.Role)
	d.Set("action", resp.Action)
	d.Set("added_iam_user_to_group", resp.AddedIAMUserToGroup)
	d.Set("partial_error", resp.PartialError)
	d.Set("iam_user_arn", resp.IAMUserArn)
	d.Set("access_key", resp.AccessKey)
	d.Set("secret_key", resp.SecretKey)

	log.Printf("[INFO] alks_ltk.id: %v", d.Id())

	return nil
}

func resourceAlksLtkRead(d *schema.ResourceData, meta interface{}) error {
	log.Printf("[INFO] ALKS LTK Users Read")

	var accountID = d.Get("account_id").(string)
	var roleName = d.Get("role_name").(string)

	client := meta.(*alks.Client)
	resp, err := client.GetLongTermKeys(accountID, roleName)

	if err != nil {
		return err
	}

	d.SetId(resp.RequestID)
	d.Set("ltks", resp.LongTermKeys)

	log.Printf("[INFO] alks_ltk.id: %v", d.Id())

	return nil
}

func resourceAlksLtkDelete(d *schema.ResourceData, meta interface{}) error {
	log.Printf("[INFO] ALKS LTK User Delete")

	var iamUsername = d.Get("iam_username").(string)

	client := meta.(*alks.Client)
	resp, err := client.DeleteLongTermKey(iamUsername)

	if err != nil {
		return err
	}

	d.SetId(resp.Account)
	d.Set("role", resp.Role)
	d.Set("action", resp.Action)
	d.Set("added_iam_user_to_group", resp.AddedIAMUserToGroup)
	d.Set("partial_error", resp.PartialError)

	log.Printf("[INFO] alks_ltk.id: %v", d.Id())

	return nil
}
<commit_msg>We do not need to require the vars for the GET command, this is already set by our response in the create.<commit_after>package main

import (
	alks "github.com/Cox-Automotive/alks-go"
	"github.com/hashicorp/terraform/helper/schema"
	"log"
)

// TODO: Find a way to NOT store 'secret_key' to TF state file.
func resourceAlksLtk() *schema.Resource {
	return &schema.Resource{
		Create: resourceAlksLtkCreate,
		Read:   resourceAlksLtkRead,
		Delete: resourceAlksLtkDelete,

		SchemaVersion: 1,
		MigrateState:  migrateState,

		Schema: map[string]*schema.Schema{
			"iam_username": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"account_id": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
			"role_name": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
			"account": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
			"role": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
			"action": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
			"added_iam_user_to_group": &schema.Schema{
				Type:     schema.TypeBool,
				Computed: true,
			},
			"partial_error": &schema.Schema{
				Type:     schema.TypeBool,
				Computed: true,
			},
			"iam_user_arn": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
			"access_key": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
			"secret_key": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
			"ltks": &schema.Schema{
				Type:     schema.TypeMap,
				Computed: true,
			},
		},
	}
}

func resourceAlksLtkCreate(d *schema.ResourceData, meta interface{}) error {
	log.Printf("[INFO] ALKS LTK User Create")

	var iamUsername = d.Get("iam_username").(string)

	client := meta.(*alks.Client)
	resp, err := client.CreateLongTermKey(iamUsername)

	if err != nil {
		return err
	}

	d.Set("account_id", resp.AccountDetails.Account)
	d.Set("role_name", resp.AccountDetails.Role)

	d.Set("role", resp.Role)
	d.Set("action", resp.Action)
	d.Set("added_iam_user_to_group", resp.AddedIAMUserToGroup)
	d.Set("partial_error", resp.PartialError)
	d.Set("iam_user_arn", resp.IAMUserArn)
	d.Set("access_key", resp.AccessKey)
	d.Set("secret_key", resp.SecretKey)

	log.Printf("[INFO] alks_ltk.id: %v", d.Id())

	return nil
}

func resourceAlksLtkRead(d *schema.ResourceData, meta interface{}) error {
	log.Printf("[INFO] ALKS LTK Users Read")

	var accountID = d.Get("account_id").(string)
	var roleName = d.Get("role_name").(string)

	client := meta.(*alks.Client)
	resp, err := client.GetLongTermKeys(accountID, roleName)

	if err != nil {
		return err
	}

	d.SetId(resp.RequestID)
	d.Set("ltks", resp.LongTermKeys)

	log.Printf("[INFO] alks_ltk.id: %v", d.Id())

	return nil
}

func resourceAlksLtkDelete(d *schema.ResourceData, meta interface{}) error {
	log.Printf("[INFO] ALKS LTK User Delete")

	var iamUsername = d.Get("iam_username").(string)

	client := meta.(*alks.Client)
	resp, err := client.DeleteLongTermKey(iamUsername)

	if err != nil {
		return err
	}

	d.Set("role", resp.Role)
	d.Set("action", resp.Action)
	d.Set("added_iam_user_to_group", resp.AddedIAMUserToGroup)
	d.Set("partial_error", resp.PartialError)

	log.Printf("[INFO] alks_ltk.id: %v", d.Id())

	return nil
}
<|endoftext|>


<commit_before>package aws

import (
	"log"

	"github.com/hashicorp/terraform/helper/config"
	"github.com/hashicorp/terraform/helper/multierror"
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/hashicorp/terraform/terraform"
	"github.com/mitchellh/goamz/autoscaling"
	"github.com/mitchellh/goamz/ec2"
	"github.com/mitchellh/goamz/elb"
	"github.com/mitchellh/goamz/rds"
	"github.com/mitchellh/goamz/route53"
	"github.com/mitchellh/goamz/s3"
)

type ResourceProvider struct {
	Config Config

	ec2conn         *ec2.EC2
	elbconn         *elb.ELB
	autoscalingconn *autoscaling.AutoScaling
	s3conn          *s3.S3
	rdsconn         *rds.Rds
	route53         *route53.Route53

	// This is the schema.Provider. Eventually this will replace much
	// of this structure. For now it is an element of it for compatiblity.
	p *schema.Provider
}

func (p *ResourceProvider) Validate(c *terraform.ResourceConfig) ([]string, []error) {
	return Provider().Validate(c)
}

func (p *ResourceProvider) ValidateResource(
	t string, c *terraform.ResourceConfig) ([]string, []error) {
	prov := Provider()
	if _, ok := prov.ResourcesMap[t]; ok {
		return prov.ValidateResource(t, c)
	}

	return resourceMap.Validate(t, c)
}

func (p *ResourceProvider) Configure(c *terraform.ResourceConfig) error {
	if _, err := config.Decode(&p.Config, c.Config); err != nil {
		return err
	}

	// Get the auth and region. This can fail if keys/regions were not
	// specified and we're attempting to use the environment.
	var errs []error
	log.Println("[INFO] Building AWS auth structure")
	auth, err := p.Config.AWSAuth()
	if err != nil {
		errs = append(errs, err)
	}

	log.Println("[INFO] Building AWS region structure")
	region, err := p.Config.AWSRegion()
	if err != nil {
		errs = append(errs, err)
	}

	if len(errs) == 0 {
		log.Println("[INFO] Initializing EC2 connection")
		p.ec2conn = ec2.New(auth, region)
		log.Println("[INFO] Initializing ELB connection")
		p.elbconn = elb.New(auth, region)
		log.Println("[INFO] Initializing AutoScaling connection")
		p.autoscalingconn = autoscaling.New(auth, region)
		log.Println("[INFO] Initializing S3 connection")
		p.s3conn = s3.New(auth, region)
		log.Println("[INFO] Initializing RDS connection")
		p.rdsconn = rds.New(auth, region)
		log.Println("[INFO] Initializing Route53 connection")
		p.route53 = route53.New(auth, region)
	}

	if len(errs) > 0 {
		return &multierror.Error{Errors: errs}
	}

	// Create the provider, set the meta
	p.p = Provider()
	p.p.SetMeta(p)

	return nil
}

func (p *ResourceProvider) Apply(
	info *terraform.InstanceInfo,
	s *terraform.InstanceState,
	d *terraform.InstanceDiff) (*terraform.InstanceState, error) {
	if _, ok := p.p.ResourcesMap[info.Type]; ok {
		return p.p.Apply(info, s, d)
	}

	return resourceMap.Apply(info, s, d, p)
}

func (p *ResourceProvider) Diff(
	info *terraform.InstanceInfo,
	s *terraform.InstanceState,
	c *terraform.ResourceConfig) (*terraform.InstanceDiff, error) {
	if _, ok := p.p.ResourcesMap[info.Type]; ok {
		return p.p.Diff(info, s, c)
	}

	return resourceMap.Diff(info, s, c, p)
}

func (p *ResourceProvider) Refresh(
	info *terraform.InstanceInfo,
	s *terraform.InstanceState) (*terraform.InstanceState, error) {
	if _, ok := p.p.ResourcesMap[info.Type]; ok {
		return p.p.Refresh(info, s)
	}

	return resourceMap.Refresh(info, s, p)
}

func (p *ResourceProvider) Resources() []terraform.ResourceType {
	result := resourceMap.Resources()
	result = append(result, Provider().Resources()...)
	return result
}
<commit_msg>providers/*: fix compilation for input<commit_after>package aws

import (
	"log"

	"github.com/hashicorp/terraform/helper/config"
	"github.com/hashicorp/terraform/helper/multierror"
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/hashicorp/terraform/terraform"
	"github.com/mitchellh/goamz/autoscaling"
	"github.com/mitchellh/goamz/ec2"
	"github.com/mitchellh/goamz/elb"
	"github.com/mitchellh/goamz/rds"
	"github.com/mitchellh/goamz/route53"
	"github.com/mitchellh/goamz/s3"
)

type ResourceProvider struct {
	Config Config

	ec2conn         *ec2.EC2
	elbconn         *elb.ELB
	autoscalingconn *autoscaling.AutoScaling
	s3conn          *s3.S3
	rdsconn         *rds.Rds
	route53         *route53.Route53

	// This is the schema.Provider. Eventually this will replace much
	// of this structure. For now it is an element of it for compatiblity.
	p *schema.Provider
}

func (p *ResourceProvider) Input(
	input terraform.UIInput,
	c *terraform.ResourceConfig) (*terraform.ResourceConfig, error) {
	return Provider().Input(input, c)
}

func (p *ResourceProvider) Validate(c *terraform.ResourceConfig) ([]string, []error) {
	return Provider().Validate(c)
}

func (p *ResourceProvider) ValidateResource(
	t string, c *terraform.ResourceConfig) ([]string, []error) {
	prov := Provider()
	if _, ok := prov.ResourcesMap[t]; ok {
		return prov.ValidateResource(t, c)
	}

	return resourceMap.Validate(t, c)
}

func (p *ResourceProvider) Configure(c *terraform.ResourceConfig) error {
	if _, err := config.Decode(&p.Config, c.Config); err != nil {
		return err
	}

	// Get the auth and region. This can fail if keys/regions were not
	// specified and we're attempting to use the environment.
	var errs []error
	log.Println("[INFO] Building AWS auth structure")
	auth, err := p.Config.AWSAuth()
	if err != nil {
		errs = append(errs, err)
	}

	log.Println("[INFO] Building AWS region structure")
	region, err := p.Config.AWSRegion()
	if err != nil {
		errs = append(errs, err)
	}

	if len(errs) == 0 {
		log.Println("[INFO] Initializing EC2 connection")
		p.ec2conn = ec2.New(auth, region)
		log.Println("[INFO] Initializing ELB connection")
		p.elbconn = elb.New(auth, region)
		log.Println("[INFO] Initializing AutoScaling connection")
		p.autoscalingconn = autoscaling.New(auth, region)
		log.Println("[INFO] Initializing S3 connection")
		p.s3conn = s3.New(auth, region)
		log.Println("[INFO] Initializing RDS connection")
		p.rdsconn = rds.New(auth, region)
		log.Println("[INFO] Initializing Route53 connection")
		p.route53 = route53.New(auth, region)
	}

	if len(errs) > 0 {
		return &multierror.Error{Errors: errs}
	}

	// Create the provider, set the meta
	p.p = Provider()
	p.p.SetMeta(p)

	return nil
}

func (p *ResourceProvider) Apply(
	info *terraform.InstanceInfo,
	s *terraform.InstanceState,
	d *terraform.InstanceDiff) (*terraform.InstanceState, error) {
	if _, ok := p.p.ResourcesMap[info.Type]; ok {
		return p.p.Apply(info, s, d)
	}

	return resourceMap.Apply(info, s, d, p)
}

func (p *ResourceProvider) Diff(
	info *terraform.InstanceInfo,
	s *terraform.InstanceState,
	c *terraform.ResourceConfig) (*terraform.InstanceDiff, error) {
	if _, ok := p.p.ResourcesMap[info.Type]; ok {
		return p.p.Diff(info, s, c)
	}

	return resourceMap.Diff(info, s, c, p)
}

func (p *ResourceProvider) Refresh(
	info *terraform.InstanceInfo,
	s *terraform.InstanceState) (*terraform.InstanceState, error) {
	if _, ok := p.p.ResourcesMap[info.Type]; ok {
		return p.p.Refresh(info, s)
	}

	return resourceMap.Refresh(info, s, p)
}

func (p *ResourceProvider) Resources() []terraform.ResourceType {
	result := resourceMap.Resources()
	result = append(result, Provider().Resources()...)
	return result
}
<|endoftext|>


<commit_before>package main

// +build version_embedded

import (
	"bytes"
	"flag"
	"fmt"
	"log"
	"math/rand"
	"net/http"
	"os"
	"os/exec"
	"os/signal"
	"regexp"
	"runtime"
	"strconv"
	"strings"
	"sync"
	"syscall"
	"time"

	"github.com/r7kamura/entoverse"
	"github.com/samuel/go-gettext/gettext"
)

const (
	trace = debugT(false)

	majorVersion = "0.0"
	maxGoroutine = 100

	hostPatern = "^((?P<commit>[0-9a-f]{7})\\.)?(?P<refspec>[^\\.]+)\\.(?P<repository_name>[^\\.]+)\\.(?P<repository_owner>[^\\.]+)\\.(?P<repository_service>.+)\\.(?P<moorage_server>moorage):(?P<moorage_server_port>[0-9]+)$"
	runCommand = `
cd /opt/src;
if ! (
  git clone --branch ${refspec} --single-branch --depth=1 https://${repository_service}/${repository_owner}/${repository_name}.git ${repository_service}/${repository_owner}/${repository_name}
 ); then
 ( cd ${repository_service}/${repository_owner}/${repository_name} &&
   git fetch --depth=1 --force origin ${refspec} &&
   git checkout --force origin/${refspec}
 )
fi;
docker build --tag=${repository_service}/${repository_owner}/${repository_name}:${refspec} $(pwd)/${repository_service}/${repository_owner}/${repository_name} &&
docker run --detach --publish-all --name=${refspec}.${repository_name}.${repository_owner}.${repository_service} ${repository_service}/${repository_owner}/${repository_name}:${refspec}
`
	inspectCommand = `
docker inspect --format="{{.NetworkSettings.IPAddress}}{{range \$$i, \$$e := .NetworkSettings.Ports}}:{{\$$i}}{{end}}" ${refspec}.${repository_name}.${repository_owner}.${repository_service}
`
)

type debugT bool

func (d debugT) Println(args ...interface{}) {
	if d {
		_, file, line, ok := runtime.Caller(1)
		if ok {
			if line > maxLineNumber {
				maxLineNumber = line
				maxLineDigits = len(fmt.Sprint(maxLineNumber))
			}
			args = append([]interface{}{
				file,
				fmt.Sprintf(fmt.Sprintf("%%%dd:", maxLineDigits), line),
			}, args...)
		}
		log.Println(args...)
	}
}

func (d debugT) Printf(format string, args ...interface{}) {
	if d {
		_, file, line, ok := runtime.Caller(1)
		if ok {
			if line > maxLineNumber {
				maxLineNumber = line
				maxLineDigits = len(fmt.Sprint(maxLineNumber))
			}
			args = []interface{}{
				file,
				fmt.Sprintf(fmt.Sprintf("%%%dd:", maxLineDigits), line),
				fmt.Sprintf(format, args...),
			}
			log.Println(args...)
		} else {
			log.Printf(format, args...)
		}
	}
}

func (d debugT) Do(f func()) {
	if d {
		f()
	}
}

var (
	buildAt            string
	catalog            *gettext.Catalog
	debug              bool
	develop            debugT
	interval           int
	maxLineDigits      int
	maxLineNumber      = 0
	maxProcesses       = runtime.NumCPU()
	memStats           runtime.MemStats
	minorVersion       string
	name               string
	reHostPatern       = regexp.MustCompile(hostPatern)
	semaphoreFile      chan int
	semaphoreFileCount = maxProcesses * 2 * 2
	semaphoreHTTP      chan int
	semaphoreHTTPCount = maxProcesses * 2 * 2
	version            string
	waitWG             bool
	wg                 sync.WaitGroup
	wgFile             sync.WaitGroup
)

func init() {
	runtime.GOMAXPROCS(maxProcesses)

	if semaphoreFileCount > 8 {
		semaphoreFileCount = 8
	}
	if semaphoreHTTPCount > 8 {
		semaphoreHTTPCount = 8
	}
	semaphoreFile = make(chan int, semaphoreFileCount)
	semaphoreHTTP = make(chan int, semaphoreHTTPCount)

	catalog, err := getCatalog()

	flag.BoolVar(&debug, "v", false, catalog.GetText("print debug messages"))
	flag.IntVar(&interval, "i", 0, catalog.GetText("interval"))
	flag.Usage = func() {
		fmt.Printf("Usage: %s [options]\n\n", os.Args[0])
		flag.PrintDefaults()
	}
	flag.Parse()

	develop = debugT(debug)

	if err != nil {
		develop.Println(err)
	}
	if catalog == nil || catalog == gettext.NullCatalog {
		develop.Do(func() {
			develop.Println("Failed at GetCatalog.", "LANGUAGE: ", getLANGUAGE())
		})
	}
}

func main() {
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, syscall.SIGTERM)
	go func() {
		for sig := range c {
			develop.Println("os.Signal:", sig)
			wgFile.Wait()
			os.Exit(0)
		}
	}()

	process()
	if interval > 0 {
		for {
			time.Sleep(time.Duration(interval) * time.Second)
			process()
		}
	}
}

func getCatalog() (result *gettext.Catalog, err error) {
	if catalog != nil {
		result = catalog
		return
	}

	var mo []byte

	switch getLANGUAGE() {
	}
	if mo != nil {
		catalog, err = gettext.ParseMO(bytes.NewReader(mo))
	} else {
		catalog = gettext.NullCatalog
	}
	result = catalog
	return
}

func getLANGUAGE() (lang string) {
	//refs: http://www.gnu.org/software/gettext/manual/html_node/Locale-Environment-Variables.html
	for _, key := range []string{"LANGUAGE", "LC_ALL", "LC_MESSAGES", "LANG"} {
		lang = os.Getenv(key)
		if lang != "" {
			lang = strings.SplitN(lang, "_", 2)[0]
			break
		}
	}
	return
}

func AddWaitGroup(f func()) {
	trace.Println()
	if waitWG == true {
		trace.Println()
		waitWG = false
		for {
			numGoroutine := runtime.NumGoroutine()
			if numGoroutine < maxGoroutine {
				break
			}
			develop.Println(
				"NumGoroutine:", numGoroutine,
				"semaphoreFile:", len(semaphoreFile),
				"semaphoreHTTP:", len(semaphoreHTTP),
			)
			trace.Println()
			runtime.Gosched()
			trace.Println()
		}
	} else {
		trace.Println()
		if rand.Intn(10) == 0 {
			numGoroutine := runtime.NumGoroutine()
			if numGoroutine > maxGoroutine {
				runtime.ReadMemStats(&memStats)
				develop.Println(
					"Alloc:", memStats.Alloc,
					"NumGC:", memStats.NumGC,
					"NumGoroutine:", numGoroutine,
					"semaphoreFile:", len(semaphoreFile),
					"semaphoreHTTP:", len(semaphoreHTTP),
				)
				waitWG = true
			}
		}
	}
	wg.Add(1)
	go func() {
		defer wg.Done()
		f()
	}()
}

func process() {
	start := time.Now()
	fmt.Printf("%v %v.%v (%v, %v, %v/%v)\n", name, majorVersion, minorVersion, version, buildAt, runtime.GOOS, runtime.GOARCH)
	defer func() {
		wg.Wait()
		develop.Do(func() {
			runtime.ReadMemStats(&memStats)
			develop.Println(memStats.Alloc, memStats.NumGC)
		})
		log.Println("Finished:", time.Now().Sub(start))
	}()

	var err error

	AddWaitGroup(func() {})

	hostConverter := func(originalHost string) string {

		develop.Println(originalHost)
		originalHost = "master.docker-http-server-hello-world.MiCHiLU.github.com.moorage:3000"
		//originalHost = "6d211fa.docker.timecard-rails.MiCHiLU.github.com.moorage:3000"
		originalHost = strings.ToLower(originalHost)

		if !reHostPatern.MatchString(originalHost) {
			//	return
		}

		//develop.Println(reHostPatern.ReplaceAllString(originalHost, runCommand))
		cmd := exec.Command("sh", "-c", reHostPatern.ReplaceAllString(originalHost, runCommand))
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		err := cmd.Run()
		if err != nil {
			log.Print(err)
		}

		cmd = exec.Command("sh", "-c", reHostPatern.ReplaceAllString(originalHost, inspectCommand))
		var out bytes.Buffer
		cmd.Stdout = &out
		err = cmd.Run()
		if err != nil {
			log.Print(err)
		}
		var output string
		output = out.String()
		develop.Println(reHostPatern.ReplaceAllString(originalHost, inspectCommand))
		develop.Println(out)
		var ip_port []string
		ip_port = strings.Split(output, ":")
		var ip string
		ip = ip_port[0]
		var port int
		var port_another int
		var protocol string
		for _, port_protocol_line := range ip_port[1:] {
			var port_protocol []string
			port_protocol = strings.SplitN(port_protocol_line, "/", 2)
			protocol = port_protocol[1]
			if port == 0 {
				port, err = strconv.Atoi(port_protocol[0])
			} else if protocol != "udp" {
				port_another, err = strconv.Atoi(port_protocol[0])
				if port > port_another {
					port = port_another
				}
			}
		}

		develop.Println(fmt.Sprintf("%s:%d", ip, port))
		if ip != "" && port != 0 {
			return fmt.Sprintf("%s:%d", ip, port)
		}
		return ""
	}

	// Creates an entoverse.Proxy object as an HTTP handler.
	proxy := entoverse.NewProxyWithHostConverter(hostConverter)

	// Runs a reverse-proxy server on http://localhost:3000/
	http.ListenAndServe(":3000", proxy)

	if err != nil {
		develop.Println(err)
		log.Print(err)
		return
	}
}
<commit_msg>remove debug message<commit_after>package main

// +build version_embedded

import (
	"bytes"
	"flag"
	"fmt"
	"log"
	"math/rand"
	"net/http"
	"os"
	"os/exec"
	"os/signal"
	"regexp"
	"runtime"
	"strconv"
	"strings"
	"sync"
	"syscall"
	"time"

	"github.com/r7kamura/entoverse"
	"github.com/samuel/go-gettext/gettext"
)

const (
	trace = debugT(false)

	majorVersion = "0.0"
	maxGoroutine = 100

	hostPatern = "^((?P<commit>[0-9a-f]{7})\\.)?(?P<refspec>[^\\.]+)\\.(?P<repository_name>[^\\.]+)\\.(?P<repository_owner>[^\\.]+)\\.(?P<repository_service>.+)\\.(?P<moorage_server>moorage):(?P<moorage_server_port>[0-9]+)$"
	runCommand = `
cd /opt/src;
if ! (
  git clone --branch ${refspec} --single-branch --depth=1 https://${repository_service}/${repository_owner}/${repository_name}.git ${repository_service}/${repository_owner}/${repository_name}
 ); then
 ( cd ${repository_service}/${repository_owner}/${repository_name} &&
   git fetch --depth=1 --force origin ${refspec} &&
   git checkout --force origin/${refspec}
 )
fi;
docker build --tag=${repository_service}/${repository_owner}/${repository_name}:${refspec} $(pwd)/${repository_service}/${repository_owner}/${repository_name} &&
docker run --detach --publish-all --name=${refspec}.${repository_name}.${repository_owner}.${repository_service} ${repository_service}/${repository_owner}/${repository_name}:${refspec}
`
	inspectCommand = `
docker inspect --format="{{.NetworkSettings.IPAddress}}{{range \$$i, \$$e := .NetworkSettings.Ports}}:{{\$$i}}{{end}}" ${refspec}.${repository_name}.${repository_owner}.${repository_service}
`
)

type debugT bool

func (d debugT) Println(args ...interface{}) {
	if d {
		_, file, line, ok := runtime.Caller(1)
		if ok {
			if line > maxLineNumber {
				maxLineNumber = line
				maxLineDigits = len(fmt.Sprint(maxLineNumber))
			}
			args = append([]interface{}{
				file,
				fmt.Sprintf(fmt.Sprintf("%%%dd:", maxLineDigits), line),
			}, args...)
		}
		log.Println(args...)
	}
}

func (d debugT) Printf(format string, args ...interface{}) {
	if d {
		_, file, line, ok := runtime.Caller(1)
		if ok {
			if line > maxLineNumber {
				maxLineNumber = line
				maxLineDigits = len(fmt.Sprint(maxLineNumber))
			}
			args = []interface{}{
				file,
				fmt.Sprintf(fmt.Sprintf("%%%dd:", maxLineDigits), line),
				fmt.Sprintf(format, args...),
			}
			log.Println(args...)
		} else {
			log.Printf(format, args...)
		}
	}
}

func (d debugT) Do(f func()) {
	if d {
		f()
	}
}

var (
	buildAt            string
	catalog            *gettext.Catalog
	debug              bool
	develop            debugT
	interval           int
	maxLineDigits      int
	maxLineNumber      = 0
	maxProcesses       = runtime.NumCPU()
	memStats           runtime.MemStats
	minorVersion       string
	name               string
	reHostPatern       = regexp.MustCompile(hostPatern)
	semaphoreFile      chan int
	semaphoreFileCount = maxProcesses * 2 * 2
	semaphoreHTTP      chan int
	semaphoreHTTPCount = maxProcesses * 2 * 2
	version            string
	waitWG             bool
	wg                 sync.WaitGroup
	wgFile             sync.WaitGroup
)

func init() {
	runtime.GOMAXPROCS(maxProcesses)

	if semaphoreFileCount > 8 {
		semaphoreFileCount = 8
	}
	if semaphoreHTTPCount > 8 {
		semaphoreHTTPCount = 8
	}
	semaphoreFile = make(chan int, semaphoreFileCount)
	semaphoreHTTP = make(chan int, semaphoreHTTPCount)

	catalog, err := getCatalog()

	flag.BoolVar(&debug, "v", false, catalog.GetText("print debug messages"))
	flag.IntVar(&interval, "i", 0, catalog.GetText("interval"))
	flag.Usage = func() {
		fmt.Printf("Usage: %s [options]\n\n", os.Args[0])
		flag.PrintDefaults()
	}
	flag.Parse()

	develop = debugT(debug)

	if err != nil {
		develop.Println(err)
	}
	if catalog == nil || catalog == gettext.NullCatalog {
		develop.Do(func() {
			develop.Println("Failed at GetCatalog.", "LANGUAGE: ", getLANGUAGE())
		})
	}
}

func main() {
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, syscall.SIGTERM)
	go func() {
		for sig := range c {
			develop.Println("os.Signal:", sig)
			wgFile.Wait()
			os.Exit(0)
		}
	}()

	process()
	if interval > 0 {
		for {
			time.Sleep(time.Duration(interval) * time.Second)
			process()
		}
	}
}

func getCatalog() (result *gettext.Catalog, err error) {
	if catalog != nil {
		result = catalog
		return
	}

	var mo []byte

	switch getLANGUAGE() {
	}
	if mo != nil {
		catalog, err = gettext.ParseMO(bytes.NewReader(mo))
	} else {
		catalog = gettext.NullCatalog
	}
	result = catalog
	return
}

func getLANGUAGE() (lang string) {
	//refs: http://www.gnu.org/software/gettext/manual/html_node/Locale-Environment-Variables.html
	for _, key := range []string{"LANGUAGE", "LC_ALL", "LC_MESSAGES", "LANG"} {
		lang = os.Getenv(key)
		if lang != "" {
			lang = strings.SplitN(lang, "_", 2)[0]
			break
		}
	}
	return
}

func AddWaitGroup(f func()) {
	trace.Println()
	if waitWG == true {
		trace.Println()
		waitWG = false
		for {
			numGoroutine := runtime.NumGoroutine()
			if numGoroutine < maxGoroutine {
				break
			}
			develop.Println(
				"NumGoroutine:", numGoroutine,
				"semaphoreFile:", len(semaphoreFile),
				"semaphoreHTTP:", len(semaphoreHTTP),
			)
			trace.Println()
			runtime.Gosched()
			trace.Println()
		}
	} else {
		trace.Println()
		if rand.Intn(10) == 0 {
			numGoroutine := runtime.NumGoroutine()
			if numGoroutine > maxGoroutine {
				runtime.ReadMemStats(&memStats)
				develop.Println(
					"Alloc:", memStats.Alloc,
					"NumGC:", memStats.NumGC,
					"NumGoroutine:", numGoroutine,
					"semaphoreFile:", len(semaphoreFile),
					"semaphoreHTTP:", len(semaphoreHTTP),
				)
				waitWG = true
			}
		}
	}
	wg.Add(1)
	go func() {
		defer wg.Done()
		f()
	}()
}

func process() {
	start := time.Now()
	fmt.Printf("%v %v.%v (%v, %v, %v/%v)\n", name, majorVersion, minorVersion, version, buildAt, runtime.GOOS, runtime.GOARCH)
	defer func() {
		wg.Wait()
		develop.Do(func() {
			runtime.ReadMemStats(&memStats)
			develop.Println(memStats.Alloc, memStats.NumGC)
		})
		log.Println("Finished:", time.Now().Sub(start))
	}()

	var err error

	AddWaitGroup(func() {})

	hostConverter := func(originalHost string) string {

		develop.Println(originalHost)
		originalHost = strings.ToLower(originalHost)

		if !reHostPatern.MatchString(originalHost) {
			return ""
		}

		cmd := exec.Command("sh", "-c", reHostPatern.ReplaceAllString(originalHost, runCommand))
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		err := cmd.Run()
		if err != nil {
			log.Print(err)
		}

		cmd = exec.Command("sh", "-c", reHostPatern.ReplaceAllString(originalHost, inspectCommand))
		var out bytes.Buffer
		cmd.Stdout = &out
		err = cmd.Run()
		if err != nil {
			log.Print(err)
		}
		var output string
		output = out.String()
		develop.Println(reHostPatern.ReplaceAllString(originalHost, inspectCommand))
		develop.Println(out)
		var ip_port []string
		ip_port = strings.Split(output, ":")
		var ip string
		ip = ip_port[0]
		var port int
		var port_another int
		var protocol string
		for _, port_protocol_line := range ip_port[1:] {
			var port_protocol []string
			port_protocol = strings.SplitN(port_protocol_line, "/", 2)
			protocol = port_protocol[1]
			if port == 0 {
				port, err = strconv.Atoi(port_protocol[0])
			} else if protocol != "udp" {
				port_another, err = strconv.Atoi(port_protocol[0])
				if port > port_another {
					port = port_another
				}
			}
		}

		develop.Println(fmt.Sprintf("%s:%d", ip, port))
		if ip != "" && port != 0 {
			return fmt.Sprintf("%s:%d", ip, port)
		}
		return ""
	}

	// Creates an entoverse.Proxy object as an HTTP handler.
	proxy := entoverse.NewProxyWithHostConverter(hostConverter)

	// Runs a reverse-proxy server on http://localhost:3000/
	http.ListenAndServe(":3000", proxy)

	if err != nil {
		develop.Println(err)
		log.Print(err)
		return
	}
}
<|endoftext|>


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

package common_test

import (
	gc "launchpad.net/gocheck"

	"launchpad.net/juju-core/environs"
	"launchpad.net/juju-core/environs/imagemetadata"
	"launchpad.net/juju-core/environs/simplestreams"
	"launchpad.net/juju-core/provider/common"
	"launchpad.net/juju-core/testing/testbase"
)

type archSuite struct {
	testbase.LoggingSuite
}

var _ = gc.Suite(&archSuite{})

func (s *archSuite) setupMetadata(c *gc.C, arches []string) (environs.Environ, simplestreams.CloudSpec) {
	s.PatchValue(&imagemetadata.DefaultBaseURL, "")
	stor := newStorage(s, c)
	env := &mockEnviron{
		storage: stor,
		config:  configGetter(c),
	}

	var images []*imagemetadata.ImageMetadata
	for _, arch := range arches {
		images = append(images, &imagemetadata.ImageMetadata{
			Id:         "image-id",
			Arch:       arch,
			RegionName: "Region",
			Endpoint:   "https://endpoint/",
		})
	}
	// Append an image from another region with some other arch to ensure it is ignored.
	images = append(images, &imagemetadata.ImageMetadata{
		Id:         "image-id",
		Arch:       "arch",
		RegionName: "Region-Two",
		Endpoint:   "https://endpoint/",
	})
	cloudSpec := simplestreams.CloudSpec{
		Region:   "Region",
		Endpoint: "https://endpoint/",
	}
	err := imagemetadata.MergeAndWriteMetadata("precise", images, &cloudSpec, env.Storage())
	c.Assert(err, gc.IsNil)
	return env, cloudSpec
}

func (s *archSuite) TestSupportedArchitecturesNone(c *gc.C) {
	env, cloudSpec := s.setupMetadata(c, nil)
	imageConstraint := imagemetadata.NewImageConstraint(simplestreams.LookupParams{
		CloudSpec: cloudSpec,
	})
	arches, err := common.SupportedArchitectures(env, imageConstraint)
	c.Assert(err, gc.IsNil)
	c.Assert(arches, gc.HasLen, 0)
}

func (s *archSuite) TestSupportedArchitecturesOne(c *gc.C) {
	env, cloudSpec := s.setupMetadata(c, []string{"ppc64"})
	imageConstraint := imagemetadata.NewImageConstraint(simplestreams.LookupParams{
		CloudSpec: cloudSpec,
	})
	arches, err := common.SupportedArchitectures(env, imageConstraint)
	c.Assert(err, gc.IsNil)
	c.Assert(arches, gc.DeepEquals, []string{"ppc64"})
}

func (s *archSuite) TestSupportedArchitecturesMany(c *gc.C) {
	env, cloudSpec := s.setupMetadata(c, []string{"ppc64", "amd64"})
	imageConstraint := imagemetadata.NewImageConstraint(simplestreams.LookupParams{
		CloudSpec: cloudSpec,
	})
	arches, err := common.SupportedArchitectures(env, imageConstraint)
	c.Assert(err, gc.IsNil)
	c.Assert(arches, gc.DeepEquals, []string{"amd64", "ppc64"})
}
<commit_msg>[r=dave-cheney],[bug=1305397] Fix lp 1305397<commit_after>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package common_test

import (
	gc "launchpad.net/gocheck"

	jc "github.com/juju/testing/checkers"

	"launchpad.net/juju-core/environs"
	"launchpad.net/juju-core/environs/imagemetadata"
	"launchpad.net/juju-core/environs/simplestreams"
	"launchpad.net/juju-core/provider/common"
	"launchpad.net/juju-core/testing/testbase"
)

type archSuite struct {
	testbase.LoggingSuite
}

var _ = gc.Suite(&archSuite{})

func (s *archSuite) setupMetadata(c *gc.C, arches []string) (environs.Environ, simplestreams.CloudSpec) {
	s.PatchValue(&imagemetadata.DefaultBaseURL, "")
	stor := newStorage(s, c)
	env := &mockEnviron{
		storage: stor,
		config:  configGetter(c),
	}

	var images []*imagemetadata.ImageMetadata
	for _, arch := range arches {
		images = append(images, &imagemetadata.ImageMetadata{
			Id:         "image-id",
			Arch:       arch,
			RegionName: "Region",
			Endpoint:   "https://endpoint/",
		})
	}
	// Append an image from another region with some other arch to ensure it is ignored.
	images = append(images, &imagemetadata.ImageMetadata{
		Id:         "image-id",
		Arch:       "arch",
		RegionName: "Region-Two",
		Endpoint:   "https://endpoint/",
	})
	cloudSpec := simplestreams.CloudSpec{
		Region:   "Region",
		Endpoint: "https://endpoint/",
	}
	err := imagemetadata.MergeAndWriteMetadata("precise", images, &cloudSpec, env.Storage())
	c.Assert(err, gc.IsNil)
	return env, cloudSpec
}

func (s *archSuite) TestSupportedArchitecturesNone(c *gc.C) {
	env, cloudSpec := s.setupMetadata(c, nil)
	imageConstraint := imagemetadata.NewImageConstraint(simplestreams.LookupParams{
		CloudSpec: cloudSpec,
	})
	arches, err := common.SupportedArchitectures(env, imageConstraint)
	c.Assert(err, gc.IsNil)
	c.Assert(arches, gc.HasLen, 0)
}

func (s *archSuite) TestSupportedArchitecturesOne(c *gc.C) {
	env, cloudSpec := s.setupMetadata(c, []string{"ppc64"})
	imageConstraint := imagemetadata.NewImageConstraint(simplestreams.LookupParams{
		CloudSpec: cloudSpec,
	})
	arches, err := common.SupportedArchitectures(env, imageConstraint)
	c.Assert(err, gc.IsNil)
	c.Assert(arches, jc.SameContents, []string{"ppc64"})
}

func (s *archSuite) TestSupportedArchitecturesMany(c *gc.C) {
	env, cloudSpec := s.setupMetadata(c, []string{"ppc64", "amd64"})
	imageConstraint := imagemetadata.NewImageConstraint(simplestreams.LookupParams{
		CloudSpec: cloudSpec,
	})
	arches, err := common.SupportedArchitectures(env, imageConstraint)
	c.Assert(err, gc.IsNil)
	c.Assert(arches, jc.SameContents, []string{"amd64", "ppc64"})
}
<|endoftext|>


<commit_before>package proxy

import (
	"bytes"
	"encoding/base64"
	"fmt"
	"github.com/adamdecaf/go-proxy/codec"
	"golang.org/x/net/html"
	"io"
	"log"
)

type HTMLTransformer struct {
	Transformer
}

func (t HTMLTransformer) Transform(in Response) Response {
	doc, err := html.Parse(in.Reader)
	if err != nil {
		log.Printf("error parsing html document err=%s\n", err)
	}

	var f func(*html.Node)

	f = func(n *html.Node) {
		if n.Type == html.ElementNode && n.Data == "a" {
			for i, a := range n.Attr {
				if a.Key == "href" {
					a.Val = fmt.Sprintf("/url/%s", codec.ToBase64(a.Val))
				}
				n.Attr[i] = a
			}
		}
		for c := n.FirstChild; c != nil; c = c.NextSibling {
			f(c)
		}
	}

	f(doc)

	out := new(bytes.Buffer)
	err = html.Render(out, doc)
	if err != nil {
		// log.Printf
		return in
	}

	buff := []io.Reader{out}
	combined := io.MultiReader(buff...)

	return Response{
		Reader: combined,
	}
}

// `encodeBase64` returns a UTF-8 string in it's base64 encoding
func encodeBase64(s string) string {
	bytes := []byte(s)
	return base64.StdEncoding.EncodeToString(bytes)
}

func NewHTMLTransformer() Transformer {
	return HTMLTransformer{}
}
<commit_msg>proxy: Remove more old code<commit_after>package proxy

import (
	"bytes"
	"fmt"
	"github.com/adamdecaf/go-proxy/codec"
	"golang.org/x/net/html"
	"io"
	"log"
)

type HTMLTransformer struct {
	Transformer
}

func (t HTMLTransformer) Transform(in Response) Response {
	doc, err := html.Parse(in.Reader)
	if err != nil {
		log.Printf("error parsing html document err=%s\n", err)
	}

	var f func(*html.Node)

	f = func(n *html.Node) {
		if n.Type == html.ElementNode && n.Data == "a" {
			for i, a := range n.Attr {
				if a.Key == "href" {
					a.Val = fmt.Sprintf("/url/%s", codec.ToBase64(a.Val))
				}
				n.Attr[i] = a
			}
		}
		for c := n.FirstChild; c != nil; c = c.NextSibling {
			f(c)
		}
	}

	f(doc)

	out := new(bytes.Buffer)
	err = html.Render(out, doc)
	if err != nil {
		// log.Printf
		return in
	}

	buff := []io.Reader{out}
	combined := io.MultiReader(buff...)

	return Response{
		Reader: combined,
	}
}

func NewHTMLTransformer() Transformer {
	return HTMLTransformer{}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"github.com/MariaTerzieva/gotumblr"
	"testing"
)

func makeMockPost() gotumblr.PostsResponse {
	mockBlogInfo := gotumblr.BlogInfo{
		Title: "title",
		Posts: 10,
		Name:  "name",
		Url:   "url",
	}
	mockTextPost := gotumblr.TextPost{
		Title: "title",
		Body:  "Body",
	}
	mockTextPostJson, _ := json.Marshal(&mockTextPost)
	mockTextPostJsonRawMessage := *(*json.RawMessage)(&mockTextPostJson)
	mockPostsResponse := gotumblr.PostsResponse{
		Blog:        mockBlogInfo,
		Posts:       []json.RawMessage{mockTextPostJsonRawMessage},
		Total_posts: 5,
	}
	return mockPostsResponse
}

func TestParsePosts(t *testing.T) {

}
<commit_msg>Add first test<commit_after>package main

import (
	"encoding/json"
	"github.com/MariaTerzieva/gotumblr"
	"testing"
)

func makeMockPost() gotumblr.PostsResponse {
	mockBlogInfo := gotumblr.BlogInfo{
		Title: "title",
		Posts: 10,
		Name:  "name",
		Url:   "url",
	}
	mockTextPost := gotumblr.TextPost{
		Title: "title",
		Body:  "Body",
	}
	mockTextPostJson, _ := json.Marshal(&mockTextPost)
	mockTextPostJsonRawMessage := *(*json.RawMessage)(&mockTextPostJson)
	mockPostsResponse := gotumblr.PostsResponse{
		Blog:        mockBlogInfo,
		Posts:       []json.RawMessage{mockTextPostJsonRawMessage},
		Total_posts: 5,
	}
	return mockPostsResponse
}

func TestParsePosts(t *testing.T) {
	postResponse := makeMockPost()
	textPost := parsePosts(postResponse)
	if textPost[0].Title != "title" {
		t.Fail()
	}
}
<|endoftext|>


<commit_before>package stonelizard

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

func (svc *Service) FetchEndpointHandler(proto, method, path string) (*UrlNode, []interface{}, map[string]interface{}, int) {
   var i, j int
   var pathId string
   var match []string
   var parms  []interface{}
   var authparms map[string]interface{}
   var endpoint UrlNode

   pathId = fmt.Sprintf("%s+%s:%s", strings.Split(proto,"/")[0], method, path)

   Goose.Serve.Logf(6,"Matcher will look on %#v", svc.Matcher)
   Goose.Serve.Logf(6,"Matcher will look for [%s]", pathId)
   match = svc.Matcher.FindStringSubmatch(pathId)
   Goose.Serve.Logf(6,"Matcher found this %#v\n", match)
   if len(match) == 0 {
      Goose.Serve.Logf(1,"Invalid service handler : %s", pathId)
      return nil, nil, nil, http.StatusBadRequest
   }

   parms = []interface{}{}
   authparms = map[string]interface{}{}

//   for _, endpoint = range svc.Svc {
   for i=1; i<len(match); i++ {
      Goose.Serve.Logf(6,"trying %s with endpoint:  %s",pathId,svc.Svc[svc.MatchedOps[i-1]].Path)
      if len(match[i]) > 0 {
         Goose.Serve.Logf(4,"Found endpoint %s for: %s",svc.Svc[svc.MatchedOps[i-1]].Path,pathId)
         endpoint = svc.Svc[svc.MatchedOps[i-1]]
         for j=i+1; (j<len(match)) && (len(match[j])>0); j++ {
            Goose.Serve.Logf(4,"j=%d, i=%d, endpoint.ParmNames: %#v, authparms: %#v",endpoint.ParmNames, authparms)
            authparms[endpoint.ParmNames[j-i-1]] = match[j]
         }
         for k := i+1; k<j; k++ { // parms = []interface{}(match[i+1:j])
            parms = append(parms,match[k])
         }
         j -= i + 1
         break
      }
   }

   return &endpoint, parms, authparms, 0
}

<commit_msg>@{debug}<commit_after>package stonelizard

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

func (svc *Service) FetchEndpointHandler(proto, method, path string) (*UrlNode, []interface{}, map[string]interface{}, int) {
   var i, j int
   var pathId string
   var match []string
   var parms  []interface{}
   var authparms map[string]interface{}
   var endpoint UrlNode

   pathId = fmt.Sprintf("%s+%s:%s", strings.Split(proto,"/")[0], method, path)

   Goose.Serve.Logf(6,"Matcher will look on %#v", svc.Matcher)
   Goose.Serve.Logf(6,"Matcher will look for [%s]", pathId)
   match = svc.Matcher.FindStringSubmatch(pathId)
   Goose.Serve.Logf(6,"Matcher found this %#v\n", match)
   if len(match) == 0 {
      Goose.Serve.Logf(1,"Invalid service handler : %s", pathId)
      return nil, nil, nil, http.StatusBadRequest
   }

   parms = []interface{}{}
   authparms = map[string]interface{}{}

//   for _, endpoint = range svc.Svc {
   for i=1; i<len(match); i++ {
      Goose.Serve.Logf(6,"trying %s with endpoint:  %s",pathId,svc.Svc[svc.MatchedOps[i-1]].Path)
      if len(match[i]) > 0 {
         Goose.Serve.Logf(4,"Found endpoint %s for: %s",svc.Svc[svc.MatchedOps[i-1]].Path,pathId)
         endpoint = svc.Svc[svc.MatchedOps[i-1]]
         for j=i+1; (j<len(match)) && (len(match[j])>0); j++ {
            Goose.Serve.Logf(0,"j=%d, i=%d, endpoint.ParmNames: %#v, authparms: %#v",endpoint.ParmNames, authparms)
            authparms[endpoint.ParmNames[j-i-1]] = match[j]
         }
         for k := i+1; k<j; k++ { // parms = []interface{}(match[i+1:j])
            parms = append(parms,match[k])
         }
         j -= i + 1
         break
      }
   }

   return &endpoint, parms, authparms, 0
}

<|endoftext|>


<commit_before>package controllers

import (
	"github.com/astaxie/beego"
)

type ErrorController struct {
	beego.Controller
}

func (c *ErrorController) Error404() {
	c.Data["content"] = "page not found"
	c.TplName = "error/404.tpl"
}

func (c *ErrorController) Error501() {
	c.Data["content"] = "server error"
	c.TplName = "error/501.tpl"
}

func (c *ErrorController) ErrorDb() {
	c.Data["content"] = "database is now down"
	c.TplName = "error/dberror.tpl"
}
<commit_msg>添加自定义报错控制器<commit_after>package controllers

import (
	"github.com/astaxie/beego"
)

type ErrorController struct {
	beego.Controller
}

func (this *ErrorController) Error404() {
	this.Data["content"] = "page not found"
	this.Data["Active"] = "error"
	this.Layout = "layout/default.html"
	this.TplName = "error/404.tpl"
}

func (this *ErrorController) Error501() {
	this.Data["Active"] = "error"
	this.Data["content"] = "server error"
	this.TplName = "error/501.tpl"
}

func (this *ErrorController) ErrorDb() {
	this.Data["Active"] = "error"
	this.Data["content"] = "database is now down"
	this.TplName = "error/dberror.tpl"
}
<|endoftext|>


<commit_before>package cblas

import (
	"github.com/gonum/blas/testblas"
	"testing"
)

func TestDgemv(t *testing.T) {
	testblas.DgemvTest(t, blasser)
}

func TestDger(t *testing.T) {
	testblas.DgerTest(t, blasser)
}

func TestDtrmv(t *testing.T) {
	testblas.DtbmvTest(t, blasser)
}

func TestDtbmv(t *testing.T) {
	testblas.DtbmvTest(t, blasser)
}

func TestDtpmv(t *testing.T) {
	testblas.DtpmvTest(t, blasser)
}

func TestDgbmv(t *testing.T) {
	testblas.DgbmvTest(t, blasser)
}
<commit_msg>using new test function in cblas tests<commit_after>package cblas

import (
	"github.com/gonum/blas/testblas"
	"testing"
)

func TestDgemv(t *testing.T) {
	testblas.DgemvTest(t, blasser)
}

func TestDger(t *testing.T) {
	testblas.DgerTest(t, blasser)
}

func TestDtxmv(t *testing.T) {
	testblas.DtxmvTest(t, blasser)
}

func TestDgbmv(t *testing.T) {
	testblas.DgbmvTest(t, blasser)
}
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes Authors.

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 mungers

import (
	"fmt"
	"strings"

	githubapi "github.com/google/go-github/github"
	"k8s.io/test-infra/mungegithub/features"
	"k8s.io/test-infra/mungegithub/github"
	"k8s.io/test-infra/mungegithub/mungers/testowner"

	"github.com/golang/glog"
	"github.com/spf13/cobra"
)

var (
	IssueCreatorName = "issue-creator"
)

// RepoClient is the interface IssueCreator used to interact with github.
// This interface is necessary for testing the IssueCreator with dependency injection.
type RepoClient interface {
	GetUser(login string) (*githubapi.User, error)
	GetLabels() ([]*githubapi.Label, error)
	ListAllIssues(options *githubapi.IssueListByRepoOptions) ([]*githubapi.Issue, error)
	NewIssue(title, body string, labels, owners []string) (*github.MungeObject, error)

	isDryRun() bool
	getOrg() string
	getProject() string

	// RealConfig gets the underlying *github.Config or returns nil if the RepoClient is a testing instance.
	RealConfig() *github.Config
}

// gihubConfig is a type alias of github.Config that implements the RepoClient interface.
type githubConfig github.Config

func (c *githubConfig) RealConfig() *github.Config {
	return (*github.Config)(c)
}

func (c *githubConfig) getOrg() string {
	return c.Org
}

func (c *githubConfig) getProject() string {
	return c.Project
}

func (c *githubConfig) isDryRun() bool {
	return c.DryRun
}

func (c *githubConfig) GetUser(login string) (*githubapi.User, error) {
	return ((*github.Config)(c)).GetUser(login)
}

func (c *githubConfig) GetLabels() ([]*githubapi.Label, error) {
	return ((*github.Config)(c)).GetLabels()
}

func (c *githubConfig) ListAllIssues(options *githubapi.IssueListByRepoOptions) ([]*githubapi.Issue, error) {
	return ((*github.Config)(c)).ListAllIssues(options)
}

func (c *githubConfig) NewIssue(title, body string, labels, owners []string) (*github.MungeObject, error) {
	return ((*github.Config)(c)).NewIssue(title, body, labels, owners)
}

// OwnerMapper finds an owner for a given test name.
type OwnerMapper interface {
	// TestOwner returns a GitHub username for a test, or "" if none are found.
	TestOwner(testName string) string

	// TestSIG returns the name of the Special Interest Group (SIG) which owns the test , or "" if none are found.
	TestSIG(testName string) string
}

// Issue is an interface implemented by structs that can be synced with github issues via the IssueCreator.
type Issue interface {
	// Title yields the initial title text of the github issue.
	Title() string
	// Body yields the body text of the github issue and *must* contain the output of ID().
	// closedIssues is a (potentially empty) slice containing all closed
	// issues authored by this bot that contain ID() in their body.
	// if Body returns an empty string no issue is created.
	Body(closedIssues []*githubapi.Issue) string
	// ID returns a string that uniquely identifies this issue.
	// This ID must appear in the body of the issue.
	// DO NOT CHANGE how this ID is formatted or duplicate issues will be created
	// on github for this issue
	ID() string
	// Labels specifies the set of labels to apply to this issue on github.
	Labels() []string
	// Owners returns the github usernames to assign the issue to or nil/empty for no assignment.
	Owners() []string
	// Priority calculates and returns the priority of this issue
	// The returned bool indicates if the returned priority is valid and can be used
	Priority() (string, bool)
}

// IssueCreator handles syncing identified issues with github issues.
// This includes finding existing github issues, creating new ones, and ensuring that duplicate
// github issues are not created.
type IssueCreator struct {
	// config is the github client that is used to interact with github.
	config RepoClient
	// validLabels is the set of labels that are valid for the current repo (populated from github).
	validLabels []*githubapi.Label
	// authorName is the name of the current bot.
	authorName string
	// allIssues is a local cache of all issues in the repo authored by the currently authenticated user.
	// Issues are keyed by issue number.
	allIssues map[int]*githubapi.Issue

	// ownerPath is the path the the test owners csv file or "" if no assignments or SIG areas should be used.
	ownerPath string
	// maxSIGCount is the maximum number of SIG areas to include on a single github issue.
	maxSIGCount int
	// maxAssignees is the maximum number of user to assign to a single github issue.
	maxAssignees int

	// owners is an OwnerMapper that maps test names to owners and SIG areas.
	owners OwnerMapper
}

func init() {
	RegisterMungerOrDie(&IssueCreator{})
}

// Initialize prepares an IssueCreator for use by other mungers.
// This includes determining the currently authenticated user, fetching all issues created by that user
// from github, fetching the labels that are valid for the repo, and initializing the test owner and sig data.
func (c *IssueCreator) Initialize(config *github.Config, feats *features.Features) error {
	cfg := githubConfig(*config)
	c.config = RepoClient(&cfg)

	var err error
	if c.ownerPath != "" {
		c.owners, err = testowner.NewReloadingOwnerList(c.ownerPath)
		if err != nil {
			return err
		}
	}
	if err = c.loadCache(); err != nil {
		return err
	}
	return nil
}

// loadCache loads the valid labels for the repo, the currently authenticated user, and the issue cache from github.
func (c *IssueCreator) loadCache() error {
	user, err := c.config.GetUser("")
	if err != nil {
		return fmt.Errorf("failed to fetch the User struct for the current authenticated user. errmsg: %v\n", err)
	}
	if user == nil {
		return fmt.Errorf("received a nil User struct pointer when trying to look up the currently authenticated user.")
	}
	if user.Login == nil {
		return fmt.Errorf("the user struct for the currently authenticated user does not specify a login.")
	}
	c.authorName = *user.Login

	// Try to get the list of valid labels for the repo.
	if c.validLabels, err = c.config.GetLabels(); err != nil {
		c.validLabels = nil
		glog.Warningf("Failed to retreive the list of valid labels for repo '%s/%s'. Allowing all labels. errmsg: %v\n", c.config.getOrg(), c.config.getProject(), err)
	}

	// Populate the issue cache (allIssues).
	issues, err := c.config.ListAllIssues(&githubapi.IssueListByRepoOptions{
		State:   "all",
		Creator: c.authorName,
	})
	if err != nil {
		return fmt.Errorf("failed to refresh the list of all issues created by %s in repo '%s/%s'. errmsg: %v\n", c.authorName, c.config.getOrg(), c.config.getProject(), err)
	}
	if len(issues) == 0 {
		glog.Warningf("IssueCreator found no issues in the repo '%s/%s' authored by %s.\n", c.config.getOrg(), c.config.getProject(), c.authorName)
	}
	c.allIssues = make(map[int]*githubapi.Issue)
	for _, i := range issues {
		c.allIssues[*i.Number] = i
	}
	return nil
}

// Name specifies the name of this munger to be used with the --pr-mungers flag.
func (c *IssueCreator) Name() string { return IssueCreatorName }

// RequiredFeatures specifies the features required by the IssueCreator (none needed).
func (c *IssueCreator) RequiredFeatures() []string { return []string{} }

// EachLoop is called at the start of every munge loop. The IssueCreator does not use this.
func (c *IssueCreator) EachLoop() error { return nil }

// AddFlags adds flags needed by the IssueCreator to the combra `cmd`.
func (c *IssueCreator) AddFlags(cmd *cobra.Command, config *github.Config) {
	cmd.Flags().StringVar(&c.ownerPath, "test-owners-csv", "", "file containing a CSV-exported test-owners spreadsheet")
	cmd.Flags().IntVar(&c.maxSIGCount, "maxSIGs", 3, "The maximum number of SIG labels to attach to an issue.")
	cmd.Flags().IntVar(&c.maxAssignees, "maxAssignees", 3, "The maximum number of users to assign to an issue.")
}

// Munge updates the IssueCreator's cache of issues if the munge object provided is an issue authored by the currently authenticated user.
func (c *IssueCreator) Munge(obj *github.MungeObject) {
	if obj.IsPR() {
		return
	}
	if *obj.Issue.User.Login != c.authorName {
		return
	}
	c.allIssues[*obj.Issue.Number] = obj.Issue
}

// filterValidLabels extracts the labels that are valid for the current repo from a set of labels.
// If a candidate label is not valid, an error is logged, but execution continues and the invalid
// label is ignored.
func (c *IssueCreator) filterValidLabels(candidates []string) []string {
	if c.validLabels == nil {
		// Failed to fetch list of valid labels for this repo so trust that labels are valid.
		return candidates
	}
	var validCandidates []string
	for _, l := range candidates {
		found := false
		for _, validLabel := range c.validLabels {
			if l == *validLabel.Name {
				found = true
				break
			}
		}
		if !found {
			glog.Errorf("The label '%s' is invalid for the repo '%s/%s'. Dropping label.", l, c.config.getOrg(), c.config.getProject())
		} else {
			validCandidates = append(validCandidates, l)
		}
	}
	return validCandidates
}

// Sync checks to see if an issue is already on github and tries to create a new issue for it if it is not.
func (c *IssueCreator) Sync(issue Issue) {
	// First look for existing issues with this ID.
	id := issue.ID()
	var closedIssues []*githubapi.Issue
	for _, i := range c.allIssues {
		if strings.Contains(*i.Body, id) {
			switch *i.State {
			case "open":
				//if an open issue is found with the ID then the issue is already synced
				return
			case "closed":
				closedIssues = append(closedIssues, i)
			default:
				glog.Errorf("Unrecognized issue state '%s' for issue #%d. Ignoring this issue.\n", *i.State, *i.Number)
			}
		}
	}
	// No open issues exist for the ID.
	body := issue.Body(closedIssues)
	if body == "" {
		// Issue indicated that it should not be synced.
		return
	}
	if !strings.Contains(body, id) {
		glog.Fatalf("Programmer error: The following body text does not contain id '%s'.\n%s\n", id, body)
	}

	title := issue.Title()
	owners := issue.Owners()
	labels := issue.Labels()
	if prio, ok := issue.Priority(); ok {
		labels = append(labels, "priority/"+prio)
	}
	labels = c.filterValidLabels(labels)

	if c.config.isDryRun() {
		glog.Infof("DryRun--Create Issue:\nTitle:%s\nBody:\n%s\nLabels:%v\nAssigned to:%s\n", title, body, labels, owners)
		return
	}
	obj, err := c.config.NewIssue(title, body, labels, owners)
	if err != nil {
		glog.Errorf("Failed to create a new github issue for issue ID '%s'.\n", id)
		return
	}
	c.allIssues[*obj.Issue.Number] = obj.Issue
}

// TestSIG uses the IssueCreator's OwnerMapper to look up the SIG for a test.
func (c *IssueCreator) TestSIG(testName string) string {
	if c.owners == nil {
		return ""
	}
	return c.owners.TestSIG(testName)
}

// TestOwner uses the IssueCreator's OwnerMapper to look up the user assigned to a test.
func (c *IssueCreator) TestOwner(testName string) string {
	if c.owners == nil {
		return ""
	}
	return c.owners.TestOwner(testName)
}

// TestSIG uses the IssueCreator's OwnerMapper to look up the SIGs for a list of tests.
// The number of SIGs returned is limited by maxSIGCount.
func (c *IssueCreator) TestsSIGs(testNames []string) []string {
	if c.owners == nil {
		return []string{}
	}
	var sigs []string
	for _, test := range testNames {
		sig := c.owners.TestSIG(test)
		if sig == "" {
			continue
		}
		found := false
		for _, oldsig := range sigs {
			if sig == oldsig {
				found = true
				break
			}
		}
		if !found {
			sigs = append(sigs, sig)
			if len(sigs) >= c.maxSIGCount {
				break
			}
		}
	}
	return sigs
}

// TestOwner uses the IssueCreator's OwnerMapper to look up the users assigned to a list of tests.
// The number of users returned is limited by maxAssignees.
func (c *IssueCreator) TestsOwners(testNames []string) []string {
	if c.owners == nil {
		return []string{}
	}
	var users []string
	for _, test := range testNames {
		user := c.owners.TestOwner(test)
		if user == "" {
			continue
		}
		found := false
		for _, olduser := range users {
			if olduser == user {
				found = true
				break
			}
		}
		if !found {
			users = append(users, user)
			if len(users) >= c.maxAssignees {
				break
			}
		}
	}
	return users
}
<commit_msg>Improved logging of issue creation to log all issue fields.<commit_after>/*
Copyright 2017 The Kubernetes Authors.

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 mungers

import (
	"fmt"
	"strings"

	githubapi "github.com/google/go-github/github"
	"k8s.io/test-infra/mungegithub/features"
	"k8s.io/test-infra/mungegithub/github"
	"k8s.io/test-infra/mungegithub/mungers/testowner"

	"github.com/golang/glog"
	"github.com/spf13/cobra"
)

var (
	IssueCreatorName = "issue-creator"
)

// RepoClient is the interface IssueCreator used to interact with github.
// This interface is necessary for testing the IssueCreator with dependency injection.
type RepoClient interface {
	GetUser(login string) (*githubapi.User, error)
	GetLabels() ([]*githubapi.Label, error)
	ListAllIssues(options *githubapi.IssueListByRepoOptions) ([]*githubapi.Issue, error)
	NewIssue(title, body string, labels, owners []string) (*github.MungeObject, error)

	isDryRun() bool
	getOrg() string
	getProject() string

	// RealConfig gets the underlying *github.Config or returns nil if the RepoClient is a testing instance.
	RealConfig() *github.Config
}

// gihubConfig is a type alias of github.Config that implements the RepoClient interface.
type githubConfig github.Config

func (c *githubConfig) RealConfig() *github.Config {
	return (*github.Config)(c)
}

func (c *githubConfig) getOrg() string {
	return c.Org
}

func (c *githubConfig) getProject() string {
	return c.Project
}

func (c *githubConfig) isDryRun() bool {
	return c.DryRun
}

func (c *githubConfig) GetUser(login string) (*githubapi.User, error) {
	return ((*github.Config)(c)).GetUser(login)
}

func (c *githubConfig) GetLabels() ([]*githubapi.Label, error) {
	return ((*github.Config)(c)).GetLabels()
}

func (c *githubConfig) ListAllIssues(options *githubapi.IssueListByRepoOptions) ([]*githubapi.Issue, error) {
	return ((*github.Config)(c)).ListAllIssues(options)
}

func (c *githubConfig) NewIssue(title, body string, labels, owners []string) (*github.MungeObject, error) {
	return ((*github.Config)(c)).NewIssue(title, body, labels, owners)
}

// OwnerMapper finds an owner for a given test name.
type OwnerMapper interface {
	// TestOwner returns a GitHub username for a test, or "" if none are found.
	TestOwner(testName string) string

	// TestSIG returns the name of the Special Interest Group (SIG) which owns the test , or "" if none are found.
	TestSIG(testName string) string
}

// Issue is an interface implemented by structs that can be synced with github issues via the IssueCreator.
type Issue interface {
	// Title yields the initial title text of the github issue.
	Title() string
	// Body yields the body text of the github issue and *must* contain the output of ID().
	// closedIssues is a (potentially empty) slice containing all closed
	// issues authored by this bot that contain ID() in their body.
	// if Body returns an empty string no issue is created.
	Body(closedIssues []*githubapi.Issue) string
	// ID returns a string that uniquely identifies this issue.
	// This ID must appear in the body of the issue.
	// DO NOT CHANGE how this ID is formatted or duplicate issues will be created
	// on github for this issue
	ID() string
	// Labels specifies the set of labels to apply to this issue on github.
	Labels() []string
	// Owners returns the github usernames to assign the issue to or nil/empty for no assignment.
	Owners() []string
	// Priority calculates and returns the priority of this issue
	// The returned bool indicates if the returned priority is valid and can be used
	Priority() (string, bool)
}

// IssueCreator handles syncing identified issues with github issues.
// This includes finding existing github issues, creating new ones, and ensuring that duplicate
// github issues are not created.
type IssueCreator struct {
	// config is the github client that is used to interact with github.
	config RepoClient
	// validLabels is the set of labels that are valid for the current repo (populated from github).
	validLabels []*githubapi.Label
	// authorName is the name of the current bot.
	authorName string
	// allIssues is a local cache of all issues in the repo authored by the currently authenticated user.
	// Issues are keyed by issue number.
	allIssues map[int]*githubapi.Issue

	// ownerPath is the path the the test owners csv file or "" if no assignments or SIG areas should be used.
	ownerPath string
	// maxSIGCount is the maximum number of SIG areas to include on a single github issue.
	maxSIGCount int
	// maxAssignees is the maximum number of user to assign to a single github issue.
	maxAssignees int

	// owners is an OwnerMapper that maps test names to owners and SIG areas.
	owners OwnerMapper
}

func init() {
	RegisterMungerOrDie(&IssueCreator{})
}

// Initialize prepares an IssueCreator for use by other mungers.
// This includes determining the currently authenticated user, fetching all issues created by that user
// from github, fetching the labels that are valid for the repo, and initializing the test owner and sig data.
func (c *IssueCreator) Initialize(config *github.Config, feats *features.Features) error {
	cfg := githubConfig(*config)
	c.config = RepoClient(&cfg)

	var err error
	if c.ownerPath != "" {
		c.owners, err = testowner.NewReloadingOwnerList(c.ownerPath)
		if err != nil {
			return err
		}
	}
	if err = c.loadCache(); err != nil {
		return err
	}
	return nil
}

// loadCache loads the valid labels for the repo, the currently authenticated user, and the issue cache from github.
func (c *IssueCreator) loadCache() error {
	user, err := c.config.GetUser("")
	if err != nil {
		return fmt.Errorf("failed to fetch the User struct for the current authenticated user. errmsg: %v\n", err)
	}
	if user == nil {
		return fmt.Errorf("received a nil User struct pointer when trying to look up the currently authenticated user.")
	}
	if user.Login == nil {
		return fmt.Errorf("the user struct for the currently authenticated user does not specify a login.")
	}
	c.authorName = *user.Login

	// Try to get the list of valid labels for the repo.
	if c.validLabels, err = c.config.GetLabels(); err != nil {
		c.validLabels = nil
		glog.Warningf("Failed to retreive the list of valid labels for repo '%s/%s'. Allowing all labels. errmsg: %v\n", c.config.getOrg(), c.config.getProject(), err)
	}

	// Populate the issue cache (allIssues).
	issues, err := c.config.ListAllIssues(&githubapi.IssueListByRepoOptions{
		State:   "all",
		Creator: c.authorName,
	})
	if err != nil {
		return fmt.Errorf("failed to refresh the list of all issues created by %s in repo '%s/%s'. errmsg: %v\n", c.authorName, c.config.getOrg(), c.config.getProject(), err)
	}
	if len(issues) == 0 {
		glog.Warningf("IssueCreator found no issues in the repo '%s/%s' authored by %s.\n", c.config.getOrg(), c.config.getProject(), c.authorName)
	}
	c.allIssues = make(map[int]*githubapi.Issue)
	for _, i := range issues {
		c.allIssues[*i.Number] = i
	}
	return nil
}

// Name specifies the name of this munger to be used with the --pr-mungers flag.
func (c *IssueCreator) Name() string { return IssueCreatorName }

// RequiredFeatures specifies the features required by the IssueCreator (none needed).
func (c *IssueCreator) RequiredFeatures() []string { return []string{} }

// EachLoop is called at the start of every munge loop. The IssueCreator does not use this.
func (c *IssueCreator) EachLoop() error { return nil }

// AddFlags adds flags needed by the IssueCreator to the combra `cmd`.
func (c *IssueCreator) AddFlags(cmd *cobra.Command, config *github.Config) {
	cmd.Flags().StringVar(&c.ownerPath, "test-owners-csv", "", "file containing a CSV-exported test-owners spreadsheet")
	cmd.Flags().IntVar(&c.maxSIGCount, "maxSIGs", 3, "The maximum number of SIG labels to attach to an issue.")
	cmd.Flags().IntVar(&c.maxAssignees, "maxAssignees", 3, "The maximum number of users to assign to an issue.")
}

// Munge updates the IssueCreator's cache of issues if the munge object provided is an issue authored by the currently authenticated user.
func (c *IssueCreator) Munge(obj *github.MungeObject) {
	if obj.IsPR() {
		return
	}
	if *obj.Issue.User.Login != c.authorName {
		return
	}
	c.allIssues[*obj.Issue.Number] = obj.Issue
}

// filterValidLabels extracts the labels that are valid for the current repo from a set of labels.
// If a candidate label is not valid, an error is logged, but execution continues and the invalid
// label is ignored.
func (c *IssueCreator) filterValidLabels(candidates []string) []string {
	if c.validLabels == nil {
		// Failed to fetch list of valid labels for this repo so trust that labels are valid.
		return candidates
	}
	var validCandidates []string
	for _, l := range candidates {
		found := false
		for _, validLabel := range c.validLabels {
			if l == *validLabel.Name {
				found = true
				break
			}
		}
		if !found {
			glog.Errorf("The label '%s' is invalid for the repo '%s/%s'. Dropping label.", l, c.config.getOrg(), c.config.getProject())
		} else {
			validCandidates = append(validCandidates, l)
		}
	}
	return validCandidates
}

// Sync checks to see if an issue is already on github and tries to create a new issue for it if it is not.
func (c *IssueCreator) Sync(issue Issue) {
	// First look for existing issues with this ID.
	id := issue.ID()
	var closedIssues []*githubapi.Issue
	for _, i := range c.allIssues {
		if strings.Contains(*i.Body, id) {
			switch *i.State {
			case "open":
				//if an open issue is found with the ID then the issue is already synced
				return
			case "closed":
				closedIssues = append(closedIssues, i)
			default:
				glog.Errorf("Unrecognized issue state '%s' for issue #%d. Ignoring this issue.\n", *i.State, *i.Number)
			}
		}
	}
	// No open issues exist for the ID.
	body := issue.Body(closedIssues)
	if body == "" {
		// Issue indicated that it should not be synced.
		return
	}
	if !strings.Contains(body, id) {
		glog.Fatalf("Programmer error: The following body text does not contain id '%s'.\n%s\n", id, body)
	}

	title := issue.Title()
	owners := issue.Owners()
	labels := issue.Labels()
	if prio, ok := issue.Priority(); ok {
		labels = append(labels, "priority/"+prio)
	}
	labels = c.filterValidLabels(labels)

	glog.Infof("Create Issue:\nTitle:%s\nBody:\n%s\nLabels:%v\nAssigned to:%v\n", title, body, labels, owners)
	if c.config.isDryRun() {
		return
	}

	obj, err := c.config.NewIssue(title, body, labels, owners)
	if err != nil {
		glog.Errorf("Failed to create a new github issue for issue ID '%s'.\n", id)
		return
	}
	c.allIssues[*obj.Issue.Number] = obj.Issue
}

// TestSIG uses the IssueCreator's OwnerMapper to look up the SIG for a test.
func (c *IssueCreator) TestSIG(testName string) string {
	if c.owners == nil {
		return ""
	}
	return c.owners.TestSIG(testName)
}

// TestOwner uses the IssueCreator's OwnerMapper to look up the user assigned to a test.
func (c *IssueCreator) TestOwner(testName string) string {
	if c.owners == nil {
		return ""
	}
	return c.owners.TestOwner(testName)
}

// TestSIG uses the IssueCreator's OwnerMapper to look up the SIGs for a list of tests.
// The number of SIGs returned is limited by maxSIGCount.
func (c *IssueCreator) TestsSIGs(testNames []string) []string {
	if c.owners == nil {
		return []string{}
	}
	var sigs []string
	for _, test := range testNames {
		sig := c.owners.TestSIG(test)
		if sig == "" {
			continue
		}
		found := false
		for _, oldsig := range sigs {
			if sig == oldsig {
				found = true
				break
			}
		}
		if !found {
			sigs = append(sigs, sig)
			if len(sigs) >= c.maxSIGCount {
				break
			}
		}
	}
	return sigs
}

// TestOwner uses the IssueCreator's OwnerMapper to look up the users assigned to a list of tests.
// The number of users returned is limited by maxAssignees.
func (c *IssueCreator) TestsOwners(testNames []string) []string {
	if c.owners == nil {
		return []string{}
	}
	var users []string
	for _, test := range testNames {
		user := c.owners.TestOwner(test)
		if user == "" {
			continue
		}
		found := false
		for _, olduser := range users {
			if olduser == user {
				found = true
				break
			}
		}
		if !found {
			users = append(users, user)
			if len(users) >= c.maxAssignees {
				break
			}
		}
	}
	return users
}
<|endoftext|>