<commit_before>// Copyright (c) 2015 The btcsuite developers
// Copyright (c) 2015-2016 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package dcrjson

// AccountFetchAddressesResult models the data returned from the
// accountfetchaddresses command.
type AccountFetchAddressesResult struct {
	Addresses []string `json:"addresses"`
}

// GetMultisigOutInfoResult models the data returned from the getmultisigoutinfo
// command.
type GetMultisigOutInfoResult struct {
	Address      string   `json:"address"`
	RedeemScript string   `json:"redeemscript"`
	M            uint8    `json:"m"`
	N            uint8    `json:"n"`
	Pubkeys      []string `json:"pubkeys"`
	TxHash       string   `json:"txhash"`
	BlockHeight  uint32   `json:"blockheight"`
	BlockHash    string   `json:"blockhash"`
	Spent        bool     `json:"spent"`
	SpentBy      string   `json:"spentby"`
	SpentByIndex uint32   `json:"spentbyindex"`
	Amount       float64  `json:"amount"`
}

// GetStakeInfoResult models the data returned from the getstakeinfo
// command.
type GetStakeInfoResult struct {
	BlockHeight      int64   `json:"blockheight"`
	PoolSize         uint32  `json:"poolsize"`
	Difficulty       float64 `json:"difficulty"`
	AllMempoolTix    uint32  `json:"allmempooltix"`
	OwnMempoolTix    uint32  `json:"ownmempooltix"`
	Immature         uint32  `json:"immature"`
	Live             uint32  `json:"live"`
	ProportionLive   float64 `json:"proportionlive"`
	Voted            uint32  `json:"voted"`
	TotalSubsidy     float64 `json:"totalsubsidy"`
	Missed           uint32  `json:"missed"`
	ProportionMissed float64 `json:"proportionmissed"`
	Revoked          uint32  `json:"revoked"`
	Expired          uint32  `json:"expired"`
}

// GetTicketsResult models the data returned from the gettickets
// command.
type GetTicketsResult struct {
	Hashes []string `json:"hashes"`
}

// VoteBitsData models the data stored for any given voteBits for a ticket.
type VoteBitsData struct {
	VoteBits    uint16 `json:"votebits"`
	VoteBitsExt string `json:"votebitsext"`
}

// GetTicketVoteBitsResult models the data returned from the getticketvotebits
// command.
type GetTicketVoteBitsResult struct {
	VoteBitsData
}

// GetTicketsVoteBitsResult models the data returned from the getticketsvotebits
// command.
type GetTicketsVoteBitsResult struct {
	VoteBitsList []VoteBitsData `json:"votebitslist"`
}

// ScriptInfo is the structure representing a redeem script, its hash,
// and its address.
type ScriptInfo struct {
	Hash160      string `json:"hash160"`
	Address      string `json:"address"`
	RedeemScript string `json:"redeemscript"`
}

// ListScriptsResult models the data returned from the listscripts
// command.
type ListScriptsResult struct {
	Scripts []ScriptInfo `json:"scripts"`
}

// RedeemMultiSigOutResult models the data returned from the redeemmultisigout
// command.
type RedeemMultiSigOutResult struct {
	Hex      string                    `json:"hex"`
	Complete bool                      `json:"complete"`
	Errors   []SignRawTransactionError `json:"errors,omitempty"`
}

// RedeemMultiSigOutsResult models the data returned from the redeemmultisigouts
// command.
type RedeemMultiSigOutsResult struct {
	Results []RedeemMultiSigOutResult `json:"results"`
}

// SendToMultiSigResult models the data returned from the sendtomultisig
// command.
type SendToMultiSigResult struct {
	TxHash       string `json:"txhash"`
	Address      string `json:"address"`
	RedeemScript string `json:"redeemscript"`
}

// SignedTransaction is a signed transaction resulting from a signrawtransactions
// command.
type SignedTransaction struct {
	SigningResult SignRawTransactionResult `json:"signingresult"`
	Sent          bool                     `json:"sent"`
	TxHash        *string                  `json:"txhash,omitempty"`
}

// SignRawTransactionsResult models the data returned from the signrawtransactions
// command.
type SignRawTransactionsResult struct {
	Results []SignedTransaction `json:"results"`
}

// PoolUserTicket is the JSON struct corresponding to a stake pool user ticket
// object.
type PoolUserTicket struct {
	Status        string `json:"status"`
	Ticket        string `json:"ticket"`
	TicketHeight  uint32 `json:"ticketheight"`
	SpentBy       string `json:"spentby"`
	SpentByHeight uint32 `json:"spentbyheight"`
}

// StakePoolUserInfoResult models the data returned from the stakepooluserinfo
// command.
type StakePoolUserInfoResult struct {
	Tickets        []PoolUserTicket `json:"tickets"`
	InvalidTickets []string         `json:"invalid"`
}

// WalletInfoResult models the data returned from the walletinfo
// command.
type WalletInfoResult struct {
	DaemonConnected   bool    `json:"daemonconnected"`
	Unlocked          bool    `json:"unlocked"`
	TxFee             float64 `json:"txfee"`
	TicketFee         float64 `json:"ticketfee"`
	TicketMaxPrice    float64 `json:"ticketmaxprice"`
	BalanceToMaintain float64 `json:"balancetomaintain"`
	TicketPurchasing  bool    `json:"ticketpurchasing"`
	VoteBits          uint16  `json:"votebits"`
	VoteBitsExtended  string  `json:"votebitsextended"`
	VoteVersion       uint32  `json:"voteversion"`
	Voting            bool    `json:"voting"`
}
<commit_msg>remove walletinfo fields related to stakemining purchaser (#612)<commit_after>// Copyright (c) 2015 The btcsuite developers
// Copyright (c) 2015-2016 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package dcrjson

// AccountFetchAddressesResult models the data returned from the
// accountfetchaddresses command.
type AccountFetchAddressesResult struct {
	Addresses []string `json:"addresses"`
}

// GetMultisigOutInfoResult models the data returned from the getmultisigoutinfo
// command.
type GetMultisigOutInfoResult struct {
	Address      string   `json:"address"`
	RedeemScript string   `json:"redeemscript"`
	M            uint8    `json:"m"`
	N            uint8    `json:"n"`
	Pubkeys      []string `json:"pubkeys"`
	TxHash       string   `json:"txhash"`
	BlockHeight  uint32   `json:"blockheight"`
	BlockHash    string   `json:"blockhash"`
	Spent        bool     `json:"spent"`
	SpentBy      string   `json:"spentby"`
	SpentByIndex uint32   `json:"spentbyindex"`
	Amount       float64  `json:"amount"`
}

// GetStakeInfoResult models the data returned from the getstakeinfo
// command.
type GetStakeInfoResult struct {
	BlockHeight      int64   `json:"blockheight"`
	PoolSize         uint32  `json:"poolsize"`
	Difficulty       float64 `json:"difficulty"`
	AllMempoolTix    uint32  `json:"allmempooltix"`
	OwnMempoolTix    uint32  `json:"ownmempooltix"`
	Immature         uint32  `json:"immature"`
	Live             uint32  `json:"live"`
	ProportionLive   float64 `json:"proportionlive"`
	Voted            uint32  `json:"voted"`
	TotalSubsidy     float64 `json:"totalsubsidy"`
	Missed           uint32  `json:"missed"`
	ProportionMissed float64 `json:"proportionmissed"`
	Revoked          uint32  `json:"revoked"`
	Expired          uint32  `json:"expired"`
}

// GetTicketsResult models the data returned from the gettickets
// command.
type GetTicketsResult struct {
	Hashes []string `json:"hashes"`
}

// VoteBitsData models the data stored for any given voteBits for a ticket.
type VoteBitsData struct {
	VoteBits    uint16 `json:"votebits"`
	VoteBitsExt string `json:"votebitsext"`
}

// GetTicketVoteBitsResult models the data returned from the getticketvotebits
// command.
type GetTicketVoteBitsResult struct {
	VoteBitsData
}

// GetTicketsVoteBitsResult models the data returned from the getticketsvotebits
// command.
type GetTicketsVoteBitsResult struct {
	VoteBitsList []VoteBitsData `json:"votebitslist"`
}

// ScriptInfo is the structure representing a redeem script, its hash,
// and its address.
type ScriptInfo struct {
	Hash160      string `json:"hash160"`
	Address      string `json:"address"`
	RedeemScript string `json:"redeemscript"`
}

// ListScriptsResult models the data returned from the listscripts
// command.
type ListScriptsResult struct {
	Scripts []ScriptInfo `json:"scripts"`
}

// RedeemMultiSigOutResult models the data returned from the redeemmultisigout
// command.
type RedeemMultiSigOutResult struct {
	Hex      string                    `json:"hex"`
	Complete bool                      `json:"complete"`
	Errors   []SignRawTransactionError `json:"errors,omitempty"`
}

// RedeemMultiSigOutsResult models the data returned from the redeemmultisigouts
// command.
type RedeemMultiSigOutsResult struct {
	Results []RedeemMultiSigOutResult `json:"results"`
}

// SendToMultiSigResult models the data returned from the sendtomultisig
// command.
type SendToMultiSigResult struct {
	TxHash       string `json:"txhash"`
	Address      string `json:"address"`
	RedeemScript string `json:"redeemscript"`
}

// SignedTransaction is a signed transaction resulting from a signrawtransactions
// command.
type SignedTransaction struct {
	SigningResult SignRawTransactionResult `json:"signingresult"`
	Sent          bool                     `json:"sent"`
	TxHash        *string                  `json:"txhash,omitempty"`
}

// SignRawTransactionsResult models the data returned from the signrawtransactions
// command.
type SignRawTransactionsResult struct {
	Results []SignedTransaction `json:"results"`
}

// PoolUserTicket is the JSON struct corresponding to a stake pool user ticket
// object.
type PoolUserTicket struct {
	Status        string `json:"status"`
	Ticket        string `json:"ticket"`
	TicketHeight  uint32 `json:"ticketheight"`
	SpentBy       string `json:"spentby"`
	SpentByHeight uint32 `json:"spentbyheight"`
}

// StakePoolUserInfoResult models the data returned from the stakepooluserinfo
// command.
type StakePoolUserInfoResult struct {
	Tickets        []PoolUserTicket `json:"tickets"`
	InvalidTickets []string         `json:"invalid"`
}

// WalletInfoResult models the data returned from the walletinfo
// command.
type WalletInfoResult struct {
	DaemonConnected  bool    `json:"daemonconnected"`
	Unlocked         bool    `json:"unlocked"`
	TxFee            float64 `json:"txfee"`
	TicketFee        float64 `json:"ticketfee"`
	TicketPurchasing bool    `json:"ticketpurchasing"`
	VoteBits         uint16  `json:"votebits"`
	VoteBitsExtended string  `json:"votebitsextended"`
	VoteVersion      uint32  `json:"voteversion"`
	Voting           bool    `json:"voting"`
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"sync"

	log "github.com/Sirupsen/logrus"
	"github.com/datasektionen/taitan/pages"
)

var (
	debug     bool   // Show debug level messages.
	info      bool   // Show info level messages.
	responses Atomic // Our parsed responses.
)

func usage() {
	fmt.Fprintf(os.Stderr, "Usage: %s [OPTIONS] ROOT\n", os.Args[0])
	flag.PrintDefaults()
	os.Exit(1)
}

func init() {
	flag.BoolVar(&debug, "vv", false, "Print debug messages.")
	flag.BoolVar(&info, "v", false, "Print info messages.")
	flag.Usage = usage
	flag.Parse()
}

func getEnv(env string) string {
	e := os.Getenv(env)
	if e == "" {
		log.Fatalf("$%s environmental variable is not set.\n", env)
	}
	return e
}

func getRoot() string {
	content := getEnv("CONTENT_URL")
	u, err := url.Parse(content)
	if err != nil {
		log.Fatalln("getContent: ", err)
	}

	// https://<token>@github.com/username/repo.git
	u.User = url.User(getEnv("TOKEN"))

	base := filepath.Base(u.Path)
	return strings.TrimSuffix(base, filepath.Ext(base))
}

func getContent() {
	content := getEnv("CONTENT_URL")
	u, err := url.Parse(content)
	if err != nil {
		log.Fatalln("getContent: ", err)
	}

	// https://<token>@github.com/username/repo.git
	u.User = url.User(getEnv("TOKEN"))

	root := getRoot()
	if _, err = os.Stat(root); os.IsNotExist(err) {
		runGit("clone", []string{"clone", u.String()})
	} else {
		runGit("pull", []string{fmt.Sprintf("-C %s", root), "pull"})
	}
}

func runGit(action string, args []string) {
	log.Infof("Found root directory - %sing updates!", action)
	cmd := exec.Command("git", args...)
	err := cmd.Start()
	if err != nil {
		log.Fatal(err)
	}
	log.Infof("Waiting for git %s to finish...", action)
	err = cmd.Wait()
	if err != nil {
		log.Warnf("%sed with error: %v\n", action, err)
	}
	log.Infof("Git %s finished!", action)
}

// setVerbosity sets the amount of messages printed.
func setVerbosity() {
	switch {
	case debug:
		log.SetLevel(log.DebugLevel)
	case info:
		log.SetLevel(log.InfoLevel)
	default:
		log.SetLevel(log.WarnLevel)
	}
}

// Atomic responses.
type Atomic struct {
	sync.Mutex
	Resps map[string]*pages.Resp
}

func validRoot(root string) {
	fi, err := os.Stat(root)
	if err != nil {
		if os.IsNotExist(err) {
			log.Fatalf("Directory doesn't exist: %q", root)
		}
		log.Fatalln(err)
	}
	if !fi.IsDir() {
		log.Fatalf("Supplied path is not a directory: %q", root)
	}
}

func main() {
	setVerbosity()

	// Get port or die.
	port := getEnv("PORT")

	// Get content or die.
	getContent()

	root := getRoot()
	log.WithField("Root", root).Info("Our root directory")

	// We'll parse and store the responses ahead of time.
	resps, err := pages.Load(root)
	if err != nil {
		log.Fatalf("pages.Load: unexpected error: %s", err)
	}
	log.WithField("Resps", resps).Debug("The parsed responses")
	responses = Atomic{Resps: resps}

	log.Info("Starting server.")
	log.Info("Listening on port: ", port)

	// Our request handler.
	http.HandleFunc("/", handler)

	// Listen on port and serve with our handler.
	err = http.ListenAndServe(":"+port, nil)
	if err != nil {
		panic(err)
	}
}

// handler parses and serves responses to our file queries.
func handler(res http.ResponseWriter, req *http.Request) {
	if req.Header.Get("X-Github-Event") == "push" {
		var err error
		log.Infoln("Push hook")
		getContent()
		responses.Lock()
		responses.Resps = map[string]*pages.Resp{}
		log.WithField("Resps", responses.Resps).Infoln("lol")
		responses.Resps, err = pages.Load(getRoot())
		if err != nil {
			log.Error(err)
		}
		log.WithField("Resps", responses.Resps).Infoln("lol")
		responses.Unlock()
		return
	}
	// Requested URL. We extract the path.
	query := req.URL.Path
	log.WithField("query", query).Info("Recieved query")

	clean := filepath.Clean(query)
	log.WithField("clean", clean).Info("Sanitized path")

	responses.Lock()
	r, ok := responses.Resps[clean]
	responses.Unlock()
	if !ok {
		log.WithField("page", clean).Warn("Page doesn't exist")
		res.WriteHeader(http.StatusNotFound)
		return
	}
	log.Info("Marshaling the response.")
	buf, err := json.Marshal(r)
	if err != nil {
		log.Warnf("handler: unexpected error: %#v\n", err)
		res.WriteHeader(http.StatusInternalServerError)
		return
	}
	log.Info("Serve the response.")
	log.Debug("Response: %#v\n", string(buf))
	res.Header().Set("Content-Type", "application/json")
	res.Write(buf)
}
<commit_msg>fix git flag<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"sync"

	log "github.com/Sirupsen/logrus"
	"github.com/datasektionen/taitan/pages"
)

var (
	debug     bool   // Show debug level messages.
	info      bool   // Show info level messages.
	responses Atomic // Our parsed responses.
)

func usage() {
	fmt.Fprintf(os.Stderr, "Usage: %s [OPTIONS] ROOT\n", os.Args[0])
	flag.PrintDefaults()
	os.Exit(1)
}

func init() {
	flag.BoolVar(&debug, "vv", false, "Print debug messages.")
	flag.BoolVar(&info, "v", false, "Print info messages.")
	flag.Usage = usage
	flag.Parse()
}

func getEnv(env string) string {
	e := os.Getenv(env)
	if e == "" {
		log.Fatalf("$%s environmental variable is not set.\n", env)
	}
	return e
}

func getRoot() string {
	content := getEnv("CONTENT_URL")
	u, err := url.Parse(content)
	if err != nil {
		log.Fatalln("getContent: ", err)
	}

	// https://<token>@github.com/username/repo.git
	u.User = url.User(getEnv("TOKEN"))

	base := filepath.Base(u.Path)
	return strings.TrimSuffix(base, filepath.Ext(base))
}

func getContent() {
	content := getEnv("CONTENT_URL")
	u, err := url.Parse(content)
	if err != nil {
		log.Fatalln("getContent: ", err)
	}

	// https://<token>@github.com/username/repo.git
	u.User = url.User(getEnv("TOKEN"))

	root := getRoot()
	if _, err = os.Stat(root); os.IsNotExist(err) {
		runGit("clone", []string{"clone", u.String()})
	} else {
		runGit("pull", []string{"-C", root, "pull"})
	}
}

func runGit(action string, args []string) {
	log.Infof("Found root directory - %sing updates!", action)
	log.Infof("Commands %#v!", args)
	cmd := exec.Command("git", args...)
	err := cmd.Start()
	if err != nil {
		log.Fatal(err)
	}
	log.Infof("Waiting for git %s to finish...", action)
	err = cmd.Wait()
	if err != nil {
		log.Warnf("%sed with error: %v\n", action, err)
	}
	log.Infof("Git %s finished!", action)
}

// setVerbosity sets the amount of messages printed.
func setVerbosity() {
	switch {
	case debug:
		log.SetLevel(log.DebugLevel)
	case info:
		log.SetLevel(log.InfoLevel)
	default:
		log.SetLevel(log.WarnLevel)
	}
}

// Atomic responses.
type Atomic struct {
	sync.Mutex
	Resps map[string]*pages.Resp
}

func validRoot(root string) {
	fi, err := os.Stat(root)
	if err != nil {
		if os.IsNotExist(err) {
			log.Fatalf("Directory doesn't exist: %q", root)
		}
		log.Fatalln(err)
	}
	if !fi.IsDir() {
		log.Fatalf("Supplied path is not a directory: %q", root)
	}
}

func main() {
	setVerbosity()

	// Get port or die.
	port := getEnv("PORT")

	// Get content or die.
	getContent()

	root := getRoot()
	log.WithField("Root", root).Info("Our root directory")

	// We'll parse and store the responses ahead of time.
	resps, err := pages.Load(root)
	if err != nil {
		log.Fatalf("pages.Load: unexpected error: %s", err)
	}
	log.WithField("Resps", resps).Debug("The parsed responses")
	responses = Atomic{Resps: resps}

	log.Info("Starting server.")
	log.Info("Listening on port: ", port)

	// Our request handler.
	http.HandleFunc("/", handler)

	// Listen on port and serve with our handler.
	err = http.ListenAndServe(":"+port, nil)
	if err != nil {
		panic(err)
	}
}

// handler parses and serves responses to our file queries.
func handler(res http.ResponseWriter, req *http.Request) {
	if req.Header.Get("X-Github-Event") == "push" {
		var err error
		log.Infoln("Push hook")
		getContent()
		responses.Lock()
		responses.Resps = map[string]*pages.Resp{}
		log.WithField("Resps", responses.Resps).Infoln("lol")
		responses.Resps, err = pages.Load(getRoot())
		if err != nil {
			log.Error(err)
		}
		log.WithField("Resps", responses.Resps).Infoln("lol")
		responses.Unlock()
		return
	}
	// Requested URL. We extract the path.
	query := req.URL.Path
	log.WithField("query", query).Info("Recieved query")

	clean := filepath.Clean(query)
	log.WithField("clean", clean).Info("Sanitized path")

	responses.Lock()
	r, ok := responses.Resps[clean]
	responses.Unlock()
	if !ok {
		log.WithField("page", clean).Warn("Page doesn't exist")
		res.WriteHeader(http.StatusNotFound)
		return
	}
	log.Info("Marshaling the response.")
	buf, err := json.Marshal(r)
	if err != nil {
		log.Warnf("handler: unexpected error: %#v\n", err)
		res.WriteHeader(http.StatusInternalServerError)
		return
	}
	log.Info("Serve the response.")
	log.Debug("Response: %#v\n", string(buf))
	res.Header().Set("Content-Type", "application/json")
	res.Write(buf)
}
<|endoftext|>


<commit_before>package order

import (
	"fmt"

	"github.com/bitfinexcom/bitfinex-api-go/pkg/convert"
)

type Order struct {
	ID            int64
	GID           int64
	CID           int64
	Symbol        string
	MTSCreated    int64
	MTSUpdated    int64
	Amount        float64
	AmountOrig    float64
	Type          string
	TypePrev      string
	MTSTif        int64
	Flags         int64
	Status        string
	Price         float64
	PriceAvg      float64
	PriceTrailing float64
	PriceAuxLimit float64
	Notify        bool
	Hidden        bool
	PlacedID      int64
	Routing       string
	Meta          map[string]interface{}
}

// Snapshot is a collection of Orders that would usually be sent on
// inital connection.
type Snapshot struct {
	Snapshot []*Order
}

// Update is an Order that gets sent out after every change to an order.
type Update Order

// New gets sent out after an Order was created successfully.
type New Order

// Cancel gets sent out after an Order was cancelled successfully.
type Cancel Order

// FromRaw takes the raw list of values as returned from the websocket
// service and tries to convert it into an Order.
func FromRaw(raw []interface{}) (o *Order, err error) {
	if len(raw) < 32 {
		return o, fmt.Errorf("data slice too short for order: %#v", raw)
	}

	o = &Order{
		ID:            convert.I64ValOrZero(raw[0]),
		GID:           convert.I64ValOrZero(raw[1]),
		CID:           convert.I64ValOrZero(raw[2]),
		Symbol:        convert.SValOrEmpty(raw[3]),
		MTSCreated:    convert.I64ValOrZero(raw[4]),
		MTSUpdated:    convert.I64ValOrZero(raw[5]),
		Amount:        convert.F64ValOrZero(raw[6]),
		AmountOrig:    convert.F64ValOrZero(raw[7]),
		Type:          convert.SValOrEmpty(raw[8]),
		TypePrev:      convert.SValOrEmpty(raw[9]),
		MTSTif:        convert.I64ValOrZero(raw[10]),
		Flags:         convert.I64ValOrZero(raw[12]),
		Status:        convert.SValOrEmpty(raw[13]),
		Price:         convert.F64ValOrZero(raw[16]),
		PriceAvg:      convert.F64ValOrZero(raw[17]),
		PriceTrailing: convert.F64ValOrZero(raw[18]),
		PriceAuxLimit: convert.F64ValOrZero(raw[19]),
		Notify:        convert.BValOrFalse(raw[23]),
		Hidden:        convert.BValOrFalse(raw[24]),
		PlacedID:      convert.I64ValOrZero(raw[25]),
		Routing:       convert.SValOrEmpty(raw[28]),
	}

	if meta, ok := raw[31].(map[string]interface{}); ok {
		o.Meta = meta
	}

	return
}

// NewFromRaw reds "on" type message from data sream and
// maps it to order.New data structure
func NewFromRaw(raw []interface{}) (New, error) {
	o, err := FromRaw(raw)
	if err != nil {
		return New{}, err
	}
	return New(*o), nil
}

// UpdateFromRaw reds "ou" type message from data sream and
// maps it to order.Update data structure
func UpdateFromRaw(raw []interface{}) (Update, error) {
	o, err := FromRaw(raw)
	if err != nil {
		return Update{}, err
	}
	return Update(*o), nil
}

// CancelFromRaw reds "oc" type message from data sream and
// maps it to order.Cancel data structure
func CancelFromRaw(raw []interface{}) (Cancel, error) {
	o, err := FromRaw(raw)
	if err != nil {
		return Cancel{}, err
	}
	return Cancel(*o), nil
}

// SnapshotFromRaw takes a raw list of values as returned from the websocket
// service and tries to convert it into an Snapshot.
func SnapshotFromRaw(raw []interface{}) (s *Snapshot, err error) {
	if len(raw) == 0 {
		return s, fmt.Errorf("data slice too short for order: %#v", raw)
	}

	os := make([]*Order, 0)
	switch raw[0].(type) {
	case []interface{}:
		for _, v := range raw {
			if l, ok := v.([]interface{}); ok {
				o, err := FromRaw(l)
				if err != nil {
					return s, err
				}
				os = append(os, o)
			}
		}
	default:
		return s, fmt.Errorf("not an order snapshot")
	}
	s = &Snapshot{Snapshot: os}

	return
}
<commit_msg>fixed typo<commit_after>package order

import (
	"fmt"

	"github.com/bitfinexcom/bitfinex-api-go/pkg/convert"
)

type Order struct {
	ID            int64
	GID           int64
	CID           int64
	Symbol        string
	MTSCreated    int64
	MTSUpdated    int64
	Amount        float64
	AmountOrig    float64
	Type          string
	TypePrev      string
	MTSTif        int64
	Flags         int64
	Status        string
	Price         float64
	PriceAvg      float64
	PriceTrailing float64
	PriceAuxLimit float64
	Notify        bool
	Hidden        bool
	PlacedID      int64
	Routing       string
	Meta          map[string]interface{}
}

// Snapshot is a collection of Orders that would usually be sent on
// inital connection.
type Snapshot struct {
	Snapshot []*Order
}

// Update is an Order that gets sent out after every change to an order.
type Update Order

// New gets sent out after an Order was created successfully.
type New Order

// Cancel gets sent out after an Order was cancelled successfully.
type Cancel Order

// FromRaw takes the raw list of values as returned from the websocket
// service and tries to convert it into an Order.
func FromRaw(raw []interface{}) (o *Order, err error) {
	if len(raw) < 32 {
		return o, fmt.Errorf("data slice too short for order: %#v", raw)
	}

	o = &Order{
		ID:            convert.I64ValOrZero(raw[0]),
		GID:           convert.I64ValOrZero(raw[1]),
		CID:           convert.I64ValOrZero(raw[2]),
		Symbol:        convert.SValOrEmpty(raw[3]),
		MTSCreated:    convert.I64ValOrZero(raw[4]),
		MTSUpdated:    convert.I64ValOrZero(raw[5]),
		Amount:        convert.F64ValOrZero(raw[6]),
		AmountOrig:    convert.F64ValOrZero(raw[7]),
		Type:          convert.SValOrEmpty(raw[8]),
		TypePrev:      convert.SValOrEmpty(raw[9]),
		MTSTif:        convert.I64ValOrZero(raw[10]),
		Flags:         convert.I64ValOrZero(raw[12]),
		Status:        convert.SValOrEmpty(raw[13]),
		Price:         convert.F64ValOrZero(raw[16]),
		PriceAvg:      convert.F64ValOrZero(raw[17]),
		PriceTrailing: convert.F64ValOrZero(raw[18]),
		PriceAuxLimit: convert.F64ValOrZero(raw[19]),
		Notify:        convert.BValOrFalse(raw[23]),
		Hidden:        convert.BValOrFalse(raw[24]),
		PlacedID:      convert.I64ValOrZero(raw[25]),
		Routing:       convert.SValOrEmpty(raw[28]),
	}

	if meta, ok := raw[31].(map[string]interface{}); ok {
		o.Meta = meta
	}

	return
}

// NewFromRaw reds "on" type message from data stream and
// maps it to order.New data structure
func NewFromRaw(raw []interface{}) (New, error) {
	o, err := FromRaw(raw)
	if err != nil {
		return New{}, err
	}
	return New(*o), nil
}

// UpdateFromRaw reds "ou" type message from data stream and
// maps it to order.Update data structure
func UpdateFromRaw(raw []interface{}) (Update, error) {
	o, err := FromRaw(raw)
	if err != nil {
		return Update{}, err
	}
	return Update(*o), nil
}

// CancelFromRaw reds "oc" type message from data stream and
// maps it to order.Cancel data structure
func CancelFromRaw(raw []interface{}) (Cancel, error) {
	o, err := FromRaw(raw)
	if err != nil {
		return Cancel{}, err
	}
	return Cancel(*o), nil
}

// SnapshotFromRaw takes a raw list of values as returned from the websocket
// service and tries to convert it into an Snapshot.
func SnapshotFromRaw(raw []interface{}) (s *Snapshot, err error) {
	if len(raw) == 0 {
		return s, fmt.Errorf("data slice too short for order: %#v", raw)
	}

	os := make([]*Order, 0)
	switch raw[0].(type) {
	case []interface{}:
		for _, v := range raw {
			if l, ok := v.([]interface{}); ok {
				o, err := FromRaw(l)
				if err != nil {
					return s, err
				}
				os = append(os, o)
			}
		}
	default:
		return s, fmt.Errorf("not an order snapshot")
	}
	s = &Snapshot{Snapshot: os}

	return
}
<|endoftext|>


<commit_before>// Copyright 2016 The prometheus-operator 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 prometheus

import (
	"fmt"
	"strings"

	yaml "gopkg.in/yaml.v2"
	"k8s.io/client-go/1.5/pkg/api/unversioned"

	"github.com/coreos/prometheus-operator/pkg/spec"
)

func generateConfig(p *spec.Prometheus, mons map[string]*spec.ServiceMonitor) ([]byte, error) {
	cfg := map[string]interface{}{}

	cfg["global"] = map[string]string{
		"evaluation_interval": "30s",
		"scrape_interval":     "30s",
	}

	cfg["rule_files"] = []string{"/etc/prometheus/rules/*.rules"}

	var scrapeConfigs []interface{}
	for _, mon := range mons {
		for i, ep := range mon.Spec.Endpoints {
			scrapeConfigs = append(scrapeConfigs, generateServiceMonitorConfig(mon, ep, i))
		}
	}
	var alertmanagerConfigs []interface{}
	for _, am := range p.Spec.Alerting.Alertmanagers {
		alertmanagerConfigs = append(alertmanagerConfigs, generateAlertmanagerConfig(am))
	}

	cfg["scrape_configs"] = scrapeConfigs
	cfg["alerting"] = map[string]interface{}{
		"alertmanagers": alertmanagerConfigs,
	}

	return yaml.Marshal(cfg)
}

func generateServiceMonitorConfig(m *spec.ServiceMonitor, ep spec.Endpoint, i int) interface{} {
	cfg := map[string]interface{}{
		"job_name": fmt.Sprintf("%s/%s/%d", m.Namespace, m.Name, i),
		"kubernetes_sd_configs": []map[string]interface{}{
			{
				"role": "endpoints",
			},
		},
	}

	if ep.Interval != "" {
		cfg["scrape_interval"] = ep.Interval
	}
	if ep.Path != "" {
		cfg["metrics_path"] = ep.Path
	}
	if ep.Scheme != "" {
		cfg["scheme"] = ep.Scheme
	}

	var relabelings []interface{}

	// Filter targets by services selected by the monitor.

	// Exact label matches.
	for k, v := range m.Spec.Selector.MatchLabels {
		relabelings = append(relabelings, map[string]interface{}{
			"action":        "keep",
			"source_labels": []string{"__meta_kubernetes_service_label_" + k},
			"regex":         v,
		})
	}
	// Set based label matching. We have to map the valid relations
	// `In`, `NotIn`, `Exists`, and `DoesNotExist`, into relabeling rules.
	for _, exp := range m.Spec.Selector.MatchExpressions {
		switch exp.Operator {
		case unversioned.LabelSelectorOpIn:
			relabelings = append(relabelings, map[string]interface{}{
				"action":        "keep",
				"source_labels": []string{"__meta_kubernetes_service_label_" + exp.Key},
				"regex":         strings.Join(exp.Values, "|"),
			})
		case unversioned.LabelSelectorOpNotIn:
			relabelings = append(relabelings, map[string]interface{}{
				"action":        "drop",
				"source_labels": []string{"__meta_kubernetes_service_label_" + exp.Key},
				"regex":         strings.Join(exp.Values, "|"),
			})
		case unversioned.LabelSelectorOpExists:
			relabelings = append(relabelings, map[string]interface{}{
				"action":        "keep",
				"source_labels": []string{"__meta_kubernetes_service_label_" + exp.Key},
				"regex":         ".+",
			})
		case unversioned.LabelSelectorOpDoesNotExist:
			relabelings = append(relabelings, map[string]interface{}{
				"action":        "drop",
				"source_labels": []string{"__meta_kubernetes_service_label_" + exp.Key},
				"regex":         ".+",
			})
		}
	}

	// Filter targets based on the namespace selection configuration.
	// By default we only discover services within the namespace of the
	// ServiceMonitor.
	// Selections allow extending this to all namespaces or to a subset
	// of them specified by label or name matching.
	//
	// Label selections are not supported yet as they require either supported
	// in the upstream SD integration or require out-of-band implementation
	// in the operator with configuration reload.
	//
	// There's no explicit nil for the selector, we decide for the default
	// case if it's all zero values.
	nsel := m.Spec.NamespaceSelector

	if !nsel.Any && len(nsel.MatchNames) == 0 {
		relabelings = append(relabelings, map[string]interface{}{
			"action":        "keep",
			"source_labels": []string{"__meta_kubernetes_namespace"},
			"regex":         m.Namespace,
		})
	} else if len(nsel.MatchNames) > 0 {
		relabelings = append(relabelings, map[string]interface{}{
			"action":        "keep",
			"source_labels": []string{"__meta_kubernetes_namespace"},
			"regex":         strings.Join(nsel.MatchNames, "|"),
		})
	}

	// Filter targets based on correct port for the endpoint.
	if ep.Port != "" {
		relabelings = append(relabelings, map[string]interface{}{
			"action":        "keep",
			"source_labels": []string{"__meta_kubernetes_endpoint_port_name"},
			"regex":         ep.Port,
		})
	} else if ep.TargetPort.StrVal != "" {
		relabelings = append(relabelings, map[string]interface{}{
			"action":        "keep",
			"source_labels": []string{"__meta_kubernetes_container_port_name"},
			"regex":         ep.TargetPort.String(),
		})
	} else if ep.TargetPort.IntVal != 0 {
		relabelings = append(relabelings, map[string]interface{}{
			"action":        "keep",
			"source_labels": []string{"__meta_kubernetes_container_port_number"},
			"regex":         ep.TargetPort.String(),
		})
	}

	// Relabel namespace and pod and service labels into proper labels.
	relabelings = append(relabelings, []interface{}{
		map[string]interface{}{
			"source_labels": []string{"__meta_kubernetes_namespace"},
			"target_label":  "namespace",
		},
		map[string]interface{}{
			"action":      "labelmap",
			"regex":       "__meta_kubernetes_service_label_(.+)",
			"replacement": "svc_$1",
		},
		map[string]interface{}{
			"action":       "replace",
			"target_label": "__meta_kubernetes_pod_label_pod_template_hash",
			"replacement":  "",
		},
		map[string]interface{}{
			"action":      "labelmap",
			"regex":       "__meta_kubernetes_pod_label_(.+)",
			"replacement": "pod_$1",
		},
	}...)

	// By default, generate a safe job name from the service name and scraped port.
	// We also keep this around if a jobLabel is set in case the targets don't actually
	// have a value for it.
	if ep.Port != "" {
		relabelings = append(relabelings, map[string]interface{}{
			"source_labels": []string{"__meta_kubernetes_service_name"},
			"target_label":  "job",
			"replacement":   "${1}-" + ep.Port,
		})
	} else if ep.TargetPort.String() != "" {
		relabelings = append(relabelings, map[string]interface{}{
			"source_labels": []string{"__meta_kubernetes_service_name"},
			"target_label":  "job",
			"replacement":   "${1}-" + ep.TargetPort.String(),
		})
	}
	// Generate a job name with a base label. Same as above, just that we
	// get the base from the label, if present.
	if m.Spec.JobLabel != "" {
		if ep.Port != "" {
			relabelings = append(relabelings, map[string]interface{}{
				"source_labels": []string{"__meta_kubernetes_service_label_" + m.Spec.JobLabel},
				"target_label":  "job",
				"regex":         "(.+)",
				"replacement":   "${1}-" + ep.Port,
			})
		} else if ep.TargetPort.String() != "" {
			relabelings = append(relabelings, map[string]interface{}{
				"source_labels": []string{"__meta_kubernetes_service_label_" + m.Spec.JobLabel},
				"target_label":  "job",
				"regex":         "(.+)",
				"replacement":   "${1}-" + ep.TargetPort.String(),
			})
		}
	}

	cfg["relabel_configs"] = relabelings

	return cfg
}

func generateAlertmanagerConfig(am spec.AlertmanagerEndpoints) interface{} {
	if am.Scheme == "" {
		am.Scheme = "http"
	}
	cfg := map[string]interface{}{
		"kubernetes_sd_configs": []map[string]interface{}{
			{
				"role": "endpoints",
			},
		},
		"scheme": am.Scheme,
	}

	var relabelings []interface{}

	relabelings = append(relabelings, map[string]interface{}{
		"action":        "keep",
		"source_labels": []string{"__meta_kubernetes_service_name"},
		"regex":         am.Name,
	})
	relabelings = append(relabelings, map[string]interface{}{
		"action":        "keep",
		"source_labels": []string{"__meta_kubernetes_namespace"},
		"regex":         am.Namespace,
	})

	if am.Port.StrVal != "" {
		relabelings = append(relabelings, map[string]interface{}{
			"action":        "keep",
			"source_labels": []string{"__meta_kubernetes_endpoint_port_name"},
			"regex":         am.Port.String(),
		})
	} else if am.Port.IntVal != 0 {
		relabelings = append(relabelings, map[string]interface{}{
			"action":        "keep",
			"source_labels": []string{"__meta_kubernetes_container_port_number"},
			"regex":         am.Port.String(),
		})
	}

	cfg["relabel_configs"] = relabelings

	return cfg
}
<commit_msg>pkg/prometheus: sanitize labels when generating config<commit_after>// Copyright 2016 The prometheus-operator 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 prometheus

import (
	"fmt"
	"regexp"
	"strings"

	yaml "gopkg.in/yaml.v2"
	"k8s.io/client-go/1.5/pkg/api/unversioned"

	"github.com/coreos/prometheus-operator/pkg/spec"
)

var (
	invalidLabelCharRE = regexp.MustCompile(`[^a-zA-Z0-9_]`)
)

func sanitizeLabelName(name string) string {
	return invalidLabelCharRE.ReplaceAllString(name, "_")
}

func generateConfig(p *spec.Prometheus, mons map[string]*spec.ServiceMonitor) ([]byte, error) {
	cfg := map[string]interface{}{}

	cfg["global"] = map[string]string{
		"evaluation_interval": "30s",
		"scrape_interval":     "30s",
	}

	cfg["rule_files"] = []string{"/etc/prometheus/rules/*.rules"}

	var scrapeConfigs []interface{}
	for _, mon := range mons {
		for i, ep := range mon.Spec.Endpoints {
			scrapeConfigs = append(scrapeConfigs, generateServiceMonitorConfig(mon, ep, i))
		}
	}
	var alertmanagerConfigs []interface{}
	for _, am := range p.Spec.Alerting.Alertmanagers {
		alertmanagerConfigs = append(alertmanagerConfigs, generateAlertmanagerConfig(am))
	}

	cfg["scrape_configs"] = scrapeConfigs
	cfg["alerting"] = map[string]interface{}{
		"alertmanagers": alertmanagerConfigs,
	}

	return yaml.Marshal(cfg)
}

func generateServiceMonitorConfig(m *spec.ServiceMonitor, ep spec.Endpoint, i int) interface{} {
	cfg := map[string]interface{}{
		"job_name": fmt.Sprintf("%s/%s/%d", m.Namespace, m.Name, i),
		"kubernetes_sd_configs": []map[string]interface{}{
			{
				"role": "endpoints",
			},
		},
	}

	if ep.Interval != "" {
		cfg["scrape_interval"] = ep.Interval
	}
	if ep.Path != "" {
		cfg["metrics_path"] = ep.Path
	}
	if ep.Scheme != "" {
		cfg["scheme"] = ep.Scheme
	}

	var relabelings []interface{}

	// Filter targets by services selected by the monitor.

	// Exact label matches.
	for k, v := range m.Spec.Selector.MatchLabels {
		relabelings = append(relabelings, map[string]interface{}{
			"action":        "keep",
			"source_labels": []string{"__meta_kubernetes_service_label_" + sanitizeLabelName(k)},
			"regex":         v,
		})
	}
	// Set based label matching. We have to map the valid relations
	// `In`, `NotIn`, `Exists`, and `DoesNotExist`, into relabeling rules.
	for _, exp := range m.Spec.Selector.MatchExpressions {
		switch exp.Operator {
		case unversioned.LabelSelectorOpIn:
			relabelings = append(relabelings, map[string]interface{}{
				"action":        "keep",
				"source_labels": []string{"__meta_kubernetes_service_label_" + sanitizeLabelName(exp.Key)},
				"regex":         strings.Join(exp.Values, "|"),
			})
		case unversioned.LabelSelectorOpNotIn:
			relabelings = append(relabelings, map[string]interface{}{
				"action":        "drop",
				"source_labels": []string{"__meta_kubernetes_service_label_" + sanitizeLabelName(exp.Key)},
				"regex":         strings.Join(exp.Values, "|"),
			})
		case unversioned.LabelSelectorOpExists:
			relabelings = append(relabelings, map[string]interface{}{
				"action":        "keep",
				"source_labels": []string{"__meta_kubernetes_service_label_" + sanitizeLabelName(exp.Key)},
				"regex":         ".+",
			})
		case unversioned.LabelSelectorOpDoesNotExist:
			relabelings = append(relabelings, map[string]interface{}{
				"action":        "drop",
				"source_labels": []string{"__meta_kubernetes_service_label_" + sanitizeLabelName(exp.Key)},
				"regex":         ".+",
			})
		}
	}

	// Filter targets based on the namespace selection configuration.
	// By default we only discover services within the namespace of the
	// ServiceMonitor.
	// Selections allow extending this to all namespaces or to a subset
	// of them specified by label or name matching.
	//
	// Label selections are not supported yet as they require either supported
	// in the upstream SD integration or require out-of-band implementation
	// in the operator with configuration reload.
	//
	// There's no explicit nil for the selector, we decide for the default
	// case if it's all zero values.
	nsel := m.Spec.NamespaceSelector

	if !nsel.Any && len(nsel.MatchNames) == 0 {
		relabelings = append(relabelings, map[string]interface{}{
			"action":        "keep",
			"source_labels": []string{"__meta_kubernetes_namespace"},
			"regex":         m.Namespace,
		})
	} else if len(nsel.MatchNames) > 0 {
		relabelings = append(relabelings, map[string]interface{}{
			"action":        "keep",
			"source_labels": []string{"__meta_kubernetes_namespace"},
			"regex":         strings.Join(nsel.MatchNames, "|"),
		})
	}

	// Filter targets based on correct port for the endpoint.
	if ep.Port != "" {
		relabelings = append(relabelings, map[string]interface{}{
			"action":        "keep",
			"source_labels": []string{"__meta_kubernetes_endpoint_port_name"},
			"regex":         ep.Port,
		})
	} else if ep.TargetPort.StrVal != "" {
		relabelings = append(relabelings, map[string]interface{}{
			"action":        "keep",
			"source_labels": []string{"__meta_kubernetes_container_port_name"},
			"regex":         ep.TargetPort.String(),
		})
	} else if ep.TargetPort.IntVal != 0 {
		relabelings = append(relabelings, map[string]interface{}{
			"action":        "keep",
			"source_labels": []string{"__meta_kubernetes_container_port_number"},
			"regex":         ep.TargetPort.String(),
		})
	}

	// Relabel namespace and pod and service labels into proper labels.
	relabelings = append(relabelings, []interface{}{
		map[string]interface{}{
			"source_labels": []string{"__meta_kubernetes_namespace"},
			"target_label":  "namespace",
		},
		map[string]interface{}{
			"action":      "labelmap",
			"regex":       "__meta_kubernetes_service_label_(.+)",
			"replacement": "svc_$1",
		},
		map[string]interface{}{
			"action":       "replace",
			"target_label": "__meta_kubernetes_pod_label_pod_template_hash",
			"replacement":  "",
		},
		map[string]interface{}{
			"action":      "labelmap",
			"regex":       "__meta_kubernetes_pod_label_(.+)",
			"replacement": "pod_$1",
		},
	}...)

	// By default, generate a safe job name from the service name and scraped port.
	// We also keep this around if a jobLabel is set in case the targets don't actually
	// have a value for it.
	if ep.Port != "" {
		relabelings = append(relabelings, map[string]interface{}{
			"source_labels": []string{"__meta_kubernetes_service_name"},
			"target_label":  "job",
			"replacement":   "${1}-" + ep.Port,
		})
	} else if ep.TargetPort.String() != "" {
		relabelings = append(relabelings, map[string]interface{}{
			"source_labels": []string{"__meta_kubernetes_service_name"},
			"target_label":  "job",
			"replacement":   "${1}-" + ep.TargetPort.String(),
		})
	}
	// Generate a job name with a base label. Same as above, just that we
	// get the base from the label, if present.
	if m.Spec.JobLabel != "" {
		if ep.Port != "" {
			relabelings = append(relabelings, map[string]interface{}{
				"source_labels": []string{"__meta_kubernetes_service_label_" + sanitizeLabelName(m.Spec.JobLabel)},
				"target_label":  "job",
				"regex":         "(.+)",
				"replacement":   "${1}-" + ep.Port,
			})
		} else if ep.TargetPort.String() != "" {
			relabelings = append(relabelings, map[string]interface{}{
				"source_labels": []string{"__meta_kubernetes_service_label_" + sanitizeLabelName(m.Spec.JobLabel)},
				"target_label":  "job",
				"regex":         "(.+)",
				"replacement":   "${1}-" + ep.TargetPort.String(),
			})
		}
	}

	cfg["relabel_configs"] = relabelings

	return cfg
}

func generateAlertmanagerConfig(am spec.AlertmanagerEndpoints) interface{} {
	if am.Scheme == "" {
		am.Scheme = "http"
	}
	cfg := map[string]interface{}{
		"kubernetes_sd_configs": []map[string]interface{}{
			{
				"role": "endpoints",
			},
		},
		"scheme": am.Scheme,
	}

	var relabelings []interface{}

	relabelings = append(relabelings, map[string]interface{}{
		"action":        "keep",
		"source_labels": []string{"__meta_kubernetes_service_name"},
		"regex":         am.Name,
	})
	relabelings = append(relabelings, map[string]interface{}{
		"action":        "keep",
		"source_labels": []string{"__meta_kubernetes_namespace"},
		"regex":         am.Namespace,
	})

	if am.Port.StrVal != "" {
		relabelings = append(relabelings, map[string]interface{}{
			"action":        "keep",
			"source_labels": []string{"__meta_kubernetes_endpoint_port_name"},
			"regex":         am.Port.String(),
		})
	} else if am.Port.IntVal != 0 {
		relabelings = append(relabelings, map[string]interface{}{
			"action":        "keep",
			"source_labels": []string{"__meta_kubernetes_container_port_number"},
			"regex":         am.Port.String(),
		})
	}

	cfg["relabel_configs"] = relabelings

	return cfg
}
<|endoftext|>


<commit_before>package stats

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

	statsd "gopkg.in/alexcesaro/statsd.v2"
)

type StatsClient struct {
	StatsDClient *statsd.Client
}

// NewStatsClient returns initialised stats client instance
func NewStatsClient(statsdClient *statsd.Client) *StatsClient {
	return &StatsClient{statsdClient}
}

// TrackRequest tracks stats for generic request
func (sc *StatsClient) TrackRequest(timing statsd.Timing, req *http.Request) {
	bucket := "request." + sc.getStatsdMetricName(req.Method, req.URL)

	timing.Send(bucket)
	sc.StatsDClient.Increment(bucket)
}

// TrackRoundTrip tracks stats for round trip request
func (sc *StatsClient) TrackRoundTrip(timing statsd.Timing, req *http.Request, success bool) {
	prefix := fmt.Sprintf("round-%s.", map[bool]string{true: "ok", false: "fail"}[success])
	bucket := prefix + sc.getStatsdMetricName(req.Method, req.URL)

	timing.Send(bucket)
	sc.StatsDClient.Increment(bucket)
}

// Returns metric name for StatsD in "<request method>.<request path>" format
func (sc *StatsClient) getStatsdMetricName(method string, url *url.URL) string {
	path := strings.Replace(
		// Double underscores
		strings.Replace(url.Path, "_", "__", -1),
		// and replace dots with single underscore
		".",
		"_",
		-1,
	)

	metricFragments := []string{"-", "-"}
	if path != "/" {
		fragmentsFilled := 0
		for _, fragment := range strings.Split(path, "/") {
			if fragment == "" {
				continue
			}

			metricFragments[fragmentsFilled] = fragment
			fragmentsFilled++
			if fragmentsFilled >= len(metricFragments) {
				break
			}
		}
	}
	return fmt.Sprintf("%s.%s", strings.ToLower(method), strings.Join(metricFragments, "."))
}
<commit_msg>Added more general purpose stats in case we have some problems with stats names generated from path<commit_after>package stats

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

	statsd "gopkg.in/alexcesaro/statsd.v2"
)

type StatsClient struct {
	StatsDClient *statsd.Client
}

const (
	bucketTotalRequests = "total.requests"
	bucketTotalRound    = "total.round"
)

// NewStatsClient returns initialised stats client instance
func NewStatsClient(statsdClient *statsd.Client) *StatsClient {
	return &StatsClient{statsdClient}
}

// TrackRequest tracks stats for generic request
func (sc *StatsClient) TrackRequest(timing statsd.Timing, req *http.Request) {
	bucket := "request." + sc.getStatsdMetricName(req.Method, req.URL)

	timing.Send(bucket)
	sc.StatsDClient.Increment(bucket)
	sc.StatsDClient.Increment(bucketTotalRequests)
}

// TrackRoundTrip tracks stats for round trip request
func (sc *StatsClient) TrackRoundTrip(timing statsd.Timing, req *http.Request, success bool) {
	okSuffix := map[bool]string{true: "ok", false: "fail"}[success]
	prefix := fmt.Sprintf("round-%s.", okSuffix)
	bucket := prefix + sc.getStatsdMetricName(req.Method, req.URL)

	timing.Send(bucket)
	sc.StatsDClient.Increment(bucket)
	sc.StatsDClient.Increment(bucketTotalRound)
	sc.StatsDClient.Increment(fmt.Sprintf("%s-%s", bucketTotalRound, okSuffix))
}

// Returns metric name for StatsD in "<request method>.<request path>" format
func (sc *StatsClient) getStatsdMetricName(method string, url *url.URL) string {
	path := strings.Replace(
		// Double underscores
		strings.Replace(url.Path, "_", "__", -1),
		// and replace dots with single underscore
		".",
		"_",
		-1,
	)

	metricFragments := []string{"-", "-"}
	if path != "/" {
		fragmentsFilled := 0
		for _, fragment := range strings.Split(path, "/") {
			if fragment == "" {
				continue
			}

			metricFragments[fragmentsFilled] = fragment
			fragmentsFilled++
			if fragmentsFilled >= len(metricFragments) {
				break
			}
		}
	}
	return fmt.Sprintf("%s.%s", strings.ToLower(method), strings.Join(metricFragments, "."))
}
<|endoftext|>


<commit_before>// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package migrations

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

	"code.gitea.io/gitea/modules/git"
	"code.gitea.io/gitea/modules/log"
	"code.gitea.io/gitea/modules/setting"

	"xorm.io/xorm"
)

// Copy paste from models/repo.go because we cannot import models package
func repoPath(userName, repoName string) string {
	return filepath.Join(userPath(userName), strings.ToLower(repoName)+".git")
}

func userPath(userName string) string {
	return filepath.Join(setting.RepoRootPath, strings.ToLower(userName))
}

func fixPublisherIDforTagReleases(x *xorm.Engine) error {

	type Release struct {
		ID          int64
		RepoID      int64
		Sha1        string
		TagName     string
		PublisherID int64
	}

	type Repository struct {
		ID        int64
		OwnerID   int64
		OwnerName string
		Name      string
	}

	type User struct {
		ID    int64
		Name  string
		Email string
	}

	const batchSize = 100
	sess := x.NewSession()
	defer sess.Close()

	var (
		repo    *Repository
		gitRepo *git.Repository
	)
	defer func() {
		if gitRepo != nil {
			gitRepo.Close()
		}
	}()
	for start := 0; ; start += batchSize {
		releases := make([]*Release, 0, batchSize)

		if err := sess.Begin(); err != nil {
			return err
		}

		if err := sess.Limit(batchSize, start).Asc("repo_id", "id").Where("is_tag=?", true).Find(&releases); err != nil {
			return err
		}

		if len(releases) == 0 {
			break
		}

		for _, release := range releases {
			if repo == nil || repo.ID != release.RepoID {
				if gitRepo != nil {
					gitRepo.Close()
					gitRepo = nil
				}
				repo = new(Repository)
				has, err := sess.ID(release.RepoID).Get(repo)
				if err != nil {
					return err
				} else if !has {
					log.Warn("Release[%d] is orphaned and refers to non-existing repository %d", release.ID, release.RepoID)
					log.Warn("This release should be deleted")
					continue
				}

				if repo.OwnerName == "" {
					// v120.go migration may not have been run correctly - we'll just replicate it here
					// because this appears to be a common-ish problem.
					if _, err := sess.Exec("UPDATE repository SET owner_name = (SELECT name FROM `user` WHERE `user`.id = repository.owner_id)"); err != nil {
						return err
					}

					if _, err := sess.ID(release.RepoID).Get(repo); err != nil {
						return err
					}
				}
				gitRepo, err = git.OpenRepository(repoPath(repo.OwnerName, repo.Name))
				if err != nil {
					return err
				}
			}

			commit, err := gitRepo.GetTagCommit(release.TagName)
			if err != nil {
				return fmt.Errorf("GetTagCommit: %v", err)
			}

			u := new(User)
			exists, err := sess.Where("email=?", commit.Author.Email).Get(u)
			if err != nil {
				return err
			}

			if !exists {
				continue
			}

			release.PublisherID = u.ID
			if _, err := sess.ID(release.ID).Cols("publisher_id").Update(release); err != nil {
				return err
			}
		}

		if err := sess.Commit(); err != nil {
			return err
		}
	}

	return nil
}
<commit_msg>Fix bug on release publisherid migrations (#13410)<commit_after>// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package migrations

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

	"code.gitea.io/gitea/modules/git"
	"code.gitea.io/gitea/modules/log"
	"code.gitea.io/gitea/modules/setting"

	"xorm.io/xorm"
)

// Copy paste from models/repo.go because we cannot import models package
func repoPath(userName, repoName string) string {
	return filepath.Join(userPath(userName), strings.ToLower(repoName)+".git")
}

func userPath(userName string) string {
	return filepath.Join(setting.RepoRootPath, strings.ToLower(userName))
}

func fixPublisherIDforTagReleases(x *xorm.Engine) error {

	type Release struct {
		ID          int64
		RepoID      int64
		Sha1        string
		TagName     string
		PublisherID int64
	}

	type Repository struct {
		ID        int64
		OwnerID   int64
		OwnerName string
		Name      string
	}

	type User struct {
		ID    int64
		Name  string
		Email string
	}

	const batchSize = 100
	sess := x.NewSession()
	defer sess.Close()

	var (
		repo    *Repository
		gitRepo *git.Repository
	)
	defer func() {
		if gitRepo != nil {
			gitRepo.Close()
		}
	}()
	for start := 0; ; start += batchSize {
		releases := make([]*Release, 0, batchSize)

		if err := sess.Begin(); err != nil {
			return err
		}

		if err := sess.Limit(batchSize, start).
			Where("publisher_id = 0").
			Asc("repo_id", "id").Where("is_tag=?", true).
			Find(&releases); err != nil {
			return err
		}

		if len(releases) == 0 {
			break
		}

		for _, release := range releases {
			if repo == nil || repo.ID != release.RepoID {
				if gitRepo != nil {
					gitRepo.Close()
					gitRepo = nil
				}
				repo = new(Repository)
				has, err := sess.ID(release.RepoID).Get(repo)
				if err != nil {
					return err
				} else if !has {
					log.Warn("Release[%d] is orphaned and refers to non-existing repository %d", release.ID, release.RepoID)
					log.Warn("This release should be deleted")
					continue
				}

				if repo.OwnerName == "" {
					// v120.go migration may not have been run correctly - we'll just replicate it here
					// because this appears to be a common-ish problem.
					if _, err := sess.Exec("UPDATE repository SET owner_name = (SELECT name FROM `user` WHERE `user`.id = repository.owner_id)"); err != nil {
						return err
					}

					if _, err := sess.ID(release.RepoID).Get(repo); err != nil {
						return err
					}
				}
				gitRepo, err = git.OpenRepository(repoPath(repo.OwnerName, repo.Name))
				if err != nil {
					return err
				}
			}

			commit, err := gitRepo.GetTagCommit(release.TagName)
			if err != nil {
				return fmt.Errorf("GetTagCommit: %v", err)
			}

			u := new(User)
			exists, err := sess.Where("email=?", commit.Author.Email).Get(u)
			if err != nil {
				return err
			}

			if !exists {
				continue
			}

			release.PublisherID = u.ID
			if _, err := sess.ID(release.ID).Cols("publisher_id").Update(release); err != nil {
				return err
			}
		}

		if err := sess.Commit(); err != nil {
			return err
		}
	}

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package migrations

import (
	"xorm.io/xorm"
)

func convertTaskTypeToString(x *xorm.Engine) error {
	const (
		GOGS int = iota + 1
		SLACK
		GITEA
		DISCORD
		DINGTALK
		TELEGRAM
		MSTEAMS
		FEISHU
		MATRIX
		WECHATWORK
	)

	hookTaskTypes := map[int]string{
		GITEA:      "gitea",
		GOGS:       "gogs",
		SLACK:      "slack",
		DISCORD:    "discord",
		DINGTALK:   "dingtalk",
		TELEGRAM:   "telegram",
		MSTEAMS:    "msteams",
		FEISHU:     "feishu",
		MATRIX:     "matrix",
		WECHATWORK: "wechatwork",
	}

	type HookTask struct {
		Typ string `xorm:"VARCHAR(16) index"`
	}
	if err := x.Sync2(new(HookTask)); err != nil {
		return err
	}

	for i, s := range hookTaskTypes {
		if _, err := x.Exec("UPDATE hook_task set typ = ? where type=?", s, i); err != nil {
			return err
		}
	}

	sess := x.NewSession()
	defer sess.Close()
	if err := sess.Begin(); err != nil {
		return err
	}
	if err := dropTableColumns(sess, "hook_task", "type"); err != nil {
		return err
	}

	return sess.Commit()
}
<commit_msg>Fix database keyword quote problem on migration v161 (#17522)<commit_after>// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package migrations

import (
	"context"

	"xorm.io/xorm"
)

func convertTaskTypeToString(x *xorm.Engine) error {
	const (
		GOGS int = iota + 1
		SLACK
		GITEA
		DISCORD
		DINGTALK
		TELEGRAM
		MSTEAMS
		FEISHU
		MATRIX
		WECHATWORK
	)

	hookTaskTypes := map[int]string{
		GITEA:      "gitea",
		GOGS:       "gogs",
		SLACK:      "slack",
		DISCORD:    "discord",
		DINGTALK:   "dingtalk",
		TELEGRAM:   "telegram",
		MSTEAMS:    "msteams",
		FEISHU:     "feishu",
		MATRIX:     "matrix",
		WECHATWORK: "wechatwork",
	}

	type HookTask struct {
		Typ string `xorm:"VARCHAR(16) index"`
	}
	if err := x.Sync2(new(HookTask)); err != nil {
		return err
	}

	// to keep the migration could be rerun
	exist, err := x.Dialect().IsColumnExist(x.DB(), context.Background(), "hook_task", "type")
	if err != nil {
		return err
	}
	if !exist {
		return nil
	}

	for i, s := range hookTaskTypes {
		if _, err := x.Exec("UPDATE hook_task set typ = ? where `type`=?", s, i); err != nil {
			return err
		}
	}

	sess := x.NewSession()
	defer sess.Close()
	if err := sess.Begin(); err != nil {
		return err
	}
	if err := dropTableColumns(sess, "hook_task", "type"); err != nil {
		return err
	}

	return sess.Commit()
}
<|endoftext|>


<commit_before>package isolated

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"

	"code.cloudfoundry.org/cli/integration/helpers"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"
)

var _ = Describe("create-app-manifest command", func() {
	var appName string
	var manifestFilePath string
	var tempDir string

	BeforeEach(func() {
		appName = helpers.NewAppName()
		var err error
		tempDir, err = ioutil.TempDir("", "create-manifest")
		Expect(err).ToNot(HaveOccurred())

		manifestFilePath = filepath.Join(tempDir, fmt.Sprintf("%s_manifest.yml", appName))
	})

	AfterEach(func() {
		os.RemoveAll(tempDir)
	})

	Context("Help", func() {
		It("displays the help information", func() {
			session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: tempDir}, "create-app-manifest", "--help")
			Eventually(session).Should(Say("NAME:"))
			Eventually(session).Should(Say("create-app-manifest - Create an app manifest for an app that has been pushed successfully"))
			Eventually(session).Should(Say("USAGE:"))
			Eventually(session).Should(Say(`cf create-app-manifest APP_NAME \[-p \/path\/to\/<app-name>_manifest\.yml\]`))
			Eventually(session).Should(Say(""))
			Eventually(session).Should(Say("OPTIONS:"))
			Eventually(session).Should(Say("-p      Specify a path for file creation. If path not specified, manifest file is created in current working directory."))
			Eventually(session).Should(Say("SEE ALSO:"))
			Eventually(session).Should(Say("apps, push"))

			Eventually(session).Should(Exit(0))
		})
	})

	When("the environment is not setup correctly", func() {
		It("fails with the appropriate errors", func() {
			helpers.CheckEnvironmentTargetedCorrectly(true, true, ReadOnlyOrg, "create-app-manifest", "some-app-name")
		})
	})

	When("app name not provided", func() {
		It("displays a usage error", func() {
			session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: tempDir}, "create-app-manifest")
			Eventually(session.Err).Should(Say("Incorrect Usage: the required argument `APP_NAME` was not provided"))
			Eventually(session).Should(Say("USAGE:"))

			Eventually(session).Should(Exit(1))
		})
	})

	When("the environment is setup correctly", func() {
		var (
			orgName   string
			spaceName string
			userName  string
		)

		BeforeEach(func() {
			orgName = helpers.NewOrgName()
			spaceName = helpers.NewSpaceName()

			helpers.SetupCF(orgName, spaceName)
			userName, _ = helpers.GetCredentials()
		})

		AfterEach(func() {
			helpers.QuickDeleteOrg(orgName)
		})

		When("the app does not exist", func() {
			It("displays an app not found error", func() {
				session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: tempDir}, "create-app-manifest", appName)
				Eventually(session).Should(Say(`Creating an app manifest from current settings of app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName))
				Eventually(session.Err).Should(Say("App %s not found", appName))
				Eventually(session).Should(Say("FAILED"))

				Eventually(session).Should(Exit(1))
			})
		})

		When("the app exists", func() {
			BeforeEach(func() {
				helpers.WithHelloWorldApp(func(appDir string) {
					Eventually(helpers.CustomCF(helpers.CFEnv{WorkingDirectory: appDir}, "push", appName)).Should(Exit(0))
				})
			})

			It("creates the manifest", func() {
				session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: tempDir}, "create-app-manifest", appName)
				Eventually(session).Should(Say(`Creating an app manifest from current settings of app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName))
				Eventually(session).Should(Say("Manifest file created successfully at %s", helpers.OSAgnosticPath(tempDir, "%s_manifest.yml", appName)))
				Eventually(session).Should(Say("OK"))
				Eventually(session).Should(Exit(0))

				createdFile, err := ioutil.ReadFile(manifestFilePath)
				Expect(err).ToNot(HaveOccurred())
				Expect(createdFile).To(MatchRegexp("---"))
				Expect(createdFile).To(MatchRegexp("applications:"))
				Expect(createdFile).To(MatchRegexp("name: %s", appName))
			})

			When("the -p flag is provided", func() {
				When("the specified file is a directory", func() {
					It("displays a file creation error", func() {
						session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: tempDir}, "create-app-manifest", appName, "-p", tempDir)
						Eventually(session).Should(Say(`Creating an app manifest from current settings of app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName))
						Eventually(session).Should(Say("FAILED"))
						Eventually(session.Err).Should(Say("Error creating manifest file: open %s: is a directory", regexp.QuoteMeta(tempDir)))

						Eventually(session).Should(Exit(1))
					})
				})

				When("the specified file does not exist", func() {
					var newFile string

					BeforeEach(func() {
						newFile = filepath.Join(tempDir, "new-file.yml")
					})

					It("creates the manifest in the file", func() {
						session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: tempDir}, "create-app-manifest", appName, "-p", newFile)
						Eventually(session).Should(Say(`Creating an app manifest from current settings of app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName))
						Eventually(session).Should(Say("Manifest file created successfully at %s", helpers.ConvertPathToRegularExpression(newFile)))
						Eventually(session).Should(Say("OK"))
						Eventually(session).Should(Exit(0))

						createdFile, err := ioutil.ReadFile(newFile)
						Expect(err).ToNot(HaveOccurred())
						Expect(createdFile).To(MatchRegexp("---"))
						Expect(createdFile).To(MatchRegexp("applications:"))
						Expect(createdFile).To(MatchRegexp("name: %s", appName))
					})
				})

				When("the specified file exists", func() {
					var existingFile string

					BeforeEach(func() {
						existingFile = filepath.Join(tempDir, "some-file")
						f, err := os.Create(existingFile)
						Expect(err).ToNot(HaveOccurred())
						Expect(f.Close()).To(Succeed())
					})

					It("overrides the previous file with the new manifest", func() {
						session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: tempDir}, "create-app-manifest", appName, "-p", existingFile)
						Eventually(session).Should(Say(`Creating an app manifest from current settings of app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName))
						Eventually(session).Should(Say("Manifest file created successfully at %s", helpers.ConvertPathToRegularExpression(existingFile)))
						Eventually(session).Should(Say("OK"))
						Eventually(session).Should(Exit(0))

						createdFile, err := ioutil.ReadFile(existingFile)
						Expect(err).ToNot(HaveOccurred())
						Expect(createdFile).To(MatchRegexp("---"))
						Expect(createdFile).To(MatchRegexp("applications:"))
						Expect(createdFile).To(MatchRegexp("name: %s", appName))
					})
				})
			})
		})
	})
})
<commit_msg>Add integration test for v7 create-app-manifest with invalid path<commit_after>package isolated

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"

	"code.cloudfoundry.org/cli/integration/helpers"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"
)

var _ = Describe("create-app-manifest command", func() {
	var appName string
	var manifestFilePath string
	var tempDir string

	BeforeEach(func() {
		appName = helpers.NewAppName()
		var err error
		tempDir, err = ioutil.TempDir("", "create-manifest")
		Expect(err).ToNot(HaveOccurred())

		manifestFilePath = filepath.Join(tempDir, fmt.Sprintf("%s_manifest.yml", appName))
	})

	AfterEach(func() {
		os.RemoveAll(tempDir)
	})

	Context("Help", func() {
		It("displays the help information", func() {
			session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: tempDir}, "create-app-manifest", "--help")
			Eventually(session).Should(Say("NAME:"))
			Eventually(session).Should(Say("create-app-manifest - Create an app manifest for an app that has been pushed successfully"))
			Eventually(session).Should(Say("USAGE:"))
			Eventually(session).Should(Say(`cf create-app-manifest APP_NAME \[-p \/path\/to\/<app-name>_manifest\.yml\]`))
			Eventually(session).Should(Say(""))
			Eventually(session).Should(Say("OPTIONS:"))
			Eventually(session).Should(Say("-p      Specify a path for file creation. If path not specified, manifest file is created in current working directory."))
			Eventually(session).Should(Say("SEE ALSO:"))
			Eventually(session).Should(Say("apps, push"))

			Eventually(session).Should(Exit(0))
		})
	})

	When("the environment is not setup correctly", func() {
		It("fails with the appropriate errors", func() {
			helpers.CheckEnvironmentTargetedCorrectly(true, true, ReadOnlyOrg, "create-app-manifest", "some-app-name")
		})
	})

	When("app name not provided", func() {
		It("displays a usage error", func() {
			session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: tempDir}, "create-app-manifest")
			Eventually(session.Err).Should(Say("Incorrect Usage: the required argument `APP_NAME` was not provided"))
			Eventually(session).Should(Say("USAGE:"))

			Eventually(session).Should(Exit(1))
		})
	})

	When("the environment is setup correctly", func() {
		var (
			orgName   string
			spaceName string
			userName  string
		)

		BeforeEach(func() {
			orgName = helpers.NewOrgName()
			spaceName = helpers.NewSpaceName()

			helpers.SetupCF(orgName, spaceName)
			userName, _ = helpers.GetCredentials()
		})

		AfterEach(func() {
			helpers.QuickDeleteOrg(orgName)
		})

		When("the app does not exist", func() {
			It("displays an app not found error", func() {
				session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: tempDir}, "create-app-manifest", appName)
				Eventually(session).Should(Say(`Creating an app manifest from current settings of app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName))
				Eventually(session.Err).Should(Say("App %s not found", appName))
				Eventually(session).Should(Say("FAILED"))

				Eventually(session).Should(Exit(1))
			})
		})

		When("the app exists", func() {
			BeforeEach(func() {
				helpers.WithHelloWorldApp(func(appDir string) {
					Eventually(helpers.CustomCF(helpers.CFEnv{WorkingDirectory: appDir}, "push", appName)).Should(Exit(0))
				})
			})

			It("creates the manifest", func() {
				session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: tempDir}, "create-app-manifest", appName)
				Eventually(session).Should(Say(`Creating an app manifest from current settings of app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName))
				Eventually(session).Should(Say("Manifest file created successfully at %s", helpers.OSAgnosticPath(tempDir, "%s_manifest.yml", appName)))
				Eventually(session).Should(Say("OK"))
				Eventually(session).Should(Exit(0))

				createdFile, err := ioutil.ReadFile(manifestFilePath)
				Expect(err).ToNot(HaveOccurred())
				Expect(createdFile).To(MatchRegexp("---"))
				Expect(createdFile).To(MatchRegexp("applications:"))
				Expect(createdFile).To(MatchRegexp("name: %s", appName))
			})

			When("the -p flag is provided", func() {
				When("the specified file is a directory", func() {
					It("displays a file creation error", func() {
						session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: tempDir}, "create-app-manifest", appName, "-p", tempDir)
						Eventually(session).Should(Say(`Creating an app manifest from current settings of app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName))
						Eventually(session).Should(Say("FAILED"))
						Eventually(session.Err).Should(Say("Error creating manifest file: open %s: is a directory", regexp.QuoteMeta(tempDir)))

						Eventually(session).Should(Exit(1))
					})
				})

				When("the specified path is invalid", func() {
					It("displays a file creation error", func() {
						invalidPath := filepath.Join(tempDir, "invalid", "path.yml")
						session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: tempDir}, "create-app-manifest", appName, "-p", invalidPath)
						Eventually(session).Should(Say(`Creating an app manifest from current settings of app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName))
						Eventually(session).Should(Say("FAILED"))
						Eventually(session.Err).Should(Say("Error creating manifest file: open %s: no such file or directory", regexp.QuoteMeta(invalidPath)))

						Eventually(session).Should(Exit(1))
					})
				})

				When("the specified file does not exist", func() {
					var newFile string

					BeforeEach(func() {
						newFile = filepath.Join(tempDir, "new-file.yml")
					})

					It("creates the manifest in the file", func() {
						session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: tempDir}, "create-app-manifest", appName, "-p", newFile)
						Eventually(session).Should(Say(`Creating an app manifest from current settings of app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName))
						Eventually(session).Should(Say("Manifest file created successfully at %s", helpers.ConvertPathToRegularExpression(newFile)))
						Eventually(session).Should(Say("OK"))
						Eventually(session).Should(Exit(0))

						createdFile, err := ioutil.ReadFile(newFile)
						Expect(err).ToNot(HaveOccurred())
						Expect(createdFile).To(MatchRegexp("---"))
						Expect(createdFile).To(MatchRegexp("applications:"))
						Expect(createdFile).To(MatchRegexp("name: %s", appName))
					})
				})

				When("the specified file exists", func() {
					var existingFile string

					BeforeEach(func() {
						existingFile = filepath.Join(tempDir, "some-file")
						f, err := os.Create(existingFile)
						Expect(err).ToNot(HaveOccurred())
						Expect(f.Close()).To(Succeed())
					})

					It("overrides the previous file with the new manifest", func() {
						session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: tempDir}, "create-app-manifest", appName, "-p", existingFile)
						Eventually(session).Should(Say(`Creating an app manifest from current settings of app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName))
						Eventually(session).Should(Say("Manifest file created successfully at %s", helpers.ConvertPathToRegularExpression(existingFile)))
						Eventually(session).Should(Say("OK"))
						Eventually(session).Should(Exit(0))

						createdFile, err := ioutil.ReadFile(existingFile)
						Expect(err).ToNot(HaveOccurred())
						Expect(createdFile).To(MatchRegexp("---"))
						Expect(createdFile).To(MatchRegexp("applications:"))
						Expect(createdFile).To(MatchRegexp("name: %s", appName))
					})
				})
			})
		})
	})
})
<|endoftext|>


<commit_before>package models_test

import (
  "testing"
  "github.com/yawnt/index.spacedock/config"
  "github.com/yawnt/index.spacedock/couch"
  "github.com/yawnt/index.spacedock/models"
)

func init() {
  config.Global = config.Load("test")
  couch.Couch = couch.New()
}

func TestUserGetNoSuchUser(t *testing.T) {
  err, user := models.GetUser("404")
  if err != nil {
    t.Error("Error while getting user")
  }
  if user != nil {
    t.Error("User should be `nil`")
  }
}
<commit_msg>More detailed tests<commit_after>package models_test

import (
  "testing"
  "github.com/yawnt/index.spacedock/config"
  "github.com/yawnt/index.spacedock/couch"
  "github.com/yawnt/index.spacedock/models"
)

func init() {
  config.Global = config.Load("test")
  couch.Couch = couch.New()
}

func TestUserGetNoSuchUser(t *testing.T) {
  err, user := models.GetUser("404")
  if err != nil {
    t.Errorf("Error should be `nil`, got: %s", err)
  }
  if user != nil {
    t.Errorf("User should be `nil`, got: %s", user)
  }
}
<|endoftext|>


<commit_before>package command

import (
	"../"
	"fmt"
	irc "github.com/fluffle/goirc/client"
	"github.com/kballard/gocallback/callback"
	"strings"
	"unicode"
	"unicode/utf8"
)

func init() {
	plugin.RegisterSetup(setup)
}

const commandPrefix = "!"

func setup(conn *irc.Conn, reg *callback.Registry) error {
	conn.AddHandler("PRIVMSG", func(conn *irc.Conn, line *irc.Line) {
		if len(line.Args) != 2 {
			// malformed line?
			return
		}
		dst := line.Args[0]
		text := line.Args[1]

		if strings.HasPrefix(text, commandPrefix) &&
			len(text) > len(commandPrefix) &&
			func() bool { r, _ := utf8.DecodeRuneInString(text[len(commandPrefix):]); return unicode.IsLetter(r) }() {
			// this is a command
			words := strings.SplitN(text, " ", 2)
			cmd, arg := words[0][len(commandPrefix):], ""
			if len(words) > 1 {
				arg = words[1]
			}
			reply, isPrivate := dst, false
			if !strings.HasPrefix(reply, "#") {
				reply, isPrivate = line.Nick, true
			}
			reg.Dispatch("COMMAND", conn, line, cmd, arg, reply, isPrivate)
		} else if strings.HasPrefix(dst, "#") {
			reg.Dispatch("PRIVMSG", conn, line, dst, text)
		} else if dst == conn.Me.Nick {
			reg.Dispatch("WHISPER", conn, line, text)
		} else {
			fmt.Println("Unknown destination on PRIVMSG:", line.Raw)
		}
	})
	return nil
}
<commit_msg>Better channel detection<commit_after>package command

import (
	"../"
	"fmt"
	irc "github.com/fluffle/goirc/client"
	"github.com/kballard/gocallback/callback"
	"strings"
	"unicode"
	"unicode/utf8"
)

func init() {
	plugin.RegisterSetup(setup)
}

const commandPrefix = "!"

func setup(conn *irc.Conn, reg *callback.Registry) error {
	conn.AddHandler("PRIVMSG", func(conn *irc.Conn, line *irc.Line) {
		if len(line.Args) != 2 {
			// malformed line?
			return
		}
		dst := line.Args[0]
		text := line.Args[1]

		if strings.HasPrefix(text, commandPrefix) &&
			len(text) > len(commandPrefix) &&
			func() bool { r, _ := utf8.DecodeRuneInString(text[len(commandPrefix):]); return unicode.IsLetter(r) }() {
			// this is a command
			words := strings.SplitN(text, " ", 2)
			cmd, arg := words[0][len(commandPrefix):], ""
			if len(words) > 1 {
				arg = words[1]
			}
			reply, isPrivate := dst, false
			if !isChannelName(reply) {
				reply, isPrivate = line.Nick, true
			}
			reg.Dispatch("COMMAND", conn, line, cmd, arg, reply, isPrivate)
		} else if strings.HasPrefix(dst, "#") {
			reg.Dispatch("PRIVMSG", conn, line, dst, text)
		} else if dst == conn.Me.Nick {
			reg.Dispatch("WHISPER", conn, line, text)
		} else {
			fmt.Println("Unknown destination on PRIVMSG:", line.Raw)
		}
	})
	return nil
}

func isChannelName(name string) bool {
	return len(name) > 0 && (name[0] == '#' || name[0] == '&' || name[0] == '!' || name[0] == '+')
}
<|endoftext|>


<commit_before>// Package erratic implements a plugin that returns erratic answers (delayed, dropped).
package erratic

import (
	"context"
	"sync/atomic"
	"time"

	"github.com/coredns/coredns/request"

	"github.com/miekg/dns"
)

// Erratic is a plugin that returns erratic repsonses to each client.
type Erratic struct {
	drop uint64

	delay    uint64
	duration time.Duration

	truncate uint64

	q uint64 // counter of queries
}

// ServeDNS implements the plugin.Handler interface.
func (e *Erratic) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
	state := request.Request{W: w, Req: r}
	drop := false
	delay := false
	trunc := false

	queryNr := atomic.LoadUint64(&e.q)
	atomic.AddUint64(&e.q, 1)

	if e.drop > 0 && queryNr%e.drop == 0 {
		drop = true
	}
	if e.delay > 0 && queryNr%e.delay == 0 {
		delay = true
	}
	if e.truncate > 0 && queryNr&e.truncate == 0 {
		trunc = true
	}

	m := new(dns.Msg)
	m.SetReply(r)
	m.Authoritative = true
	if trunc {
		m.Truncated = true
	}

	// small dance to copy rrA or rrAAAA into a non-pointer var that allows us to overwrite the ownername
	// in a non-racy way.
	switch state.QType() {
	case dns.TypeA:
		rr := *(rrA.(*dns.A))
		rr.Header().Name = state.QName()
		m.Answer = append(m.Answer, &rr)
	case dns.TypeAAAA:
		rr := *(rrAAAA.(*dns.AAAA))
		rr.Header().Name = state.QName()
		m.Answer = append(m.Answer, &rr)
	default:
		if !drop {
			if delay {
				time.Sleep(e.duration)
			}
			// coredns will return error.
			return dns.RcodeServerFailure, nil
		}
	}

	if drop {
		return 0, nil
	}

	if delay {
		time.Sleep(e.duration)
	}

	state.SizeAndDo(m)
	w.WriteMsg(m)

	return 0, nil
}

// Name implements the Handler interface.
func (e *Erratic) Name() string { return "erratic" }

var (
	rrA, _    = dns.NewRR(". IN 0 A 192.0.2.53")
	rrAAAA, _ = dns.NewRR(". IN 0 AAAA 2001:DB8::53")
)
<commit_msg>Fix typo in erratic.go (#1812)<commit_after>// Package erratic implements a plugin that returns erratic answers (delayed, dropped).
package erratic

import (
	"context"
	"sync/atomic"
	"time"

	"github.com/coredns/coredns/request"

	"github.com/miekg/dns"
)

// Erratic is a plugin that returns erratic responses to each client.
type Erratic struct {
	drop uint64

	delay    uint64
	duration time.Duration

	truncate uint64

	q uint64 // counter of queries
}

// ServeDNS implements the plugin.Handler interface.
func (e *Erratic) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
	state := request.Request{W: w, Req: r}
	drop := false
	delay := false
	trunc := false

	queryNr := atomic.LoadUint64(&e.q)
	atomic.AddUint64(&e.q, 1)

	if e.drop > 0 && queryNr%e.drop == 0 {
		drop = true
	}
	if e.delay > 0 && queryNr%e.delay == 0 {
		delay = true
	}
	if e.truncate > 0 && queryNr&e.truncate == 0 {
		trunc = true
	}

	m := new(dns.Msg)
	m.SetReply(r)
	m.Authoritative = true
	if trunc {
		m.Truncated = true
	}

	// small dance to copy rrA or rrAAAA into a non-pointer var that allows us to overwrite the ownername
	// in a non-racy way.
	switch state.QType() {
	case dns.TypeA:
		rr := *(rrA.(*dns.A))
		rr.Header().Name = state.QName()
		m.Answer = append(m.Answer, &rr)
	case dns.TypeAAAA:
		rr := *(rrAAAA.(*dns.AAAA))
		rr.Header().Name = state.QName()
		m.Answer = append(m.Answer, &rr)
	default:
		if !drop {
			if delay {
				time.Sleep(e.duration)
			}
			// coredns will return error.
			return dns.RcodeServerFailure, nil
		}
	}

	if drop {
		return 0, nil
	}

	if delay {
		time.Sleep(e.duration)
	}

	state.SizeAndDo(m)
	w.WriteMsg(m)

	return 0, nil
}

// Name implements the Handler interface.
func (e *Erratic) Name() string { return "erratic" }

var (
	rrA, _    = dns.NewRR(". IN 0 A 192.0.2.53")
	rrAAAA, _ = dns.NewRR(". IN 0 AAAA 2001:DB8::53")
)
<|endoftext|>


<commit_before>package docker

import (
	"fmt"
	"os"

	"github.com/hashicorp/packer/common"
	"github.com/hashicorp/packer/helper/communicator"
	"github.com/hashicorp/packer/helper/config"
	"github.com/hashicorp/packer/packer"
	"github.com/hashicorp/packer/template/interpolate"
	"github.com/mitchellh/mapstructure"
)

var (
	errArtifactNotUsed     = fmt.Errorf("No instructions given for handling the artifact; expected commit, discard, or export_path")
	errArtifactUseConflict = fmt.Errorf("Cannot specify more than one of commit, discard, and export_path")
	errExportPathNotFile   = fmt.Errorf("export_path must be a file, not a directory")
	errImageNotSpecified   = fmt.Errorf("Image must be specified")
)

type Config struct {
	common.PackerConfig `mapstructure:",squash"`
	Comm                communicator.Config `mapstructure:",squash"`

	Author         string
	Changes        []string
	Commit         bool
	ContainerDir   string `mapstructure:"container_dir"`
	Discard        bool
	ExecUser       string `mapstructure:"exec_user"`
	ExportPath     string `mapstructure:"export_path"`
	Image          string
	Message        string
	Privileged     bool `mapstructure:"privileged"`
	Pty            bool
	Pull           bool
	RunCommand     []string `mapstructure:"run_command"`
	Volumes        map[string]string
	FixUploadOwner bool `mapstructure:"fix_upload_owner"`

	// This is used to login to dockerhub to pull a private base container. For
	// pushing to dockerhub, see the docker post-processors
	Login           bool
	LoginPassword   string `mapstructure:"login_password"`
	LoginServer     string `mapstructure:"login_server"`
	LoginUsername   string `mapstructure:"login_username"`
	EcrLogin        bool   `mapstructure:"ecr_login"`
	AwsAccessConfig `mapstructure:",squash"`

	ctx interpolate.Context
}

func NewConfig(raws ...interface{}) (*Config, []string, error) {
	c := new(Config)

	c.FixUploadOwner = true

	var md mapstructure.Metadata
	err := config.Decode(c, &config.DecodeOpts{
		Metadata:           &md,
		Interpolate:        true,
		InterpolateContext: &c.ctx,
		InterpolateFilter: &interpolate.RenderFilter{
			Exclude: []string{
				"run_command",
			},
		},
	}, raws...)
	if err != nil {
		return nil, nil, err
	}

	// Defaults
	if len(c.RunCommand) == 0 {
		c.RunCommand = []string{"-d", "-i", "-t", "{{.Image}}", "/bin/bash"}
	}

	// Default Pull if it wasn't set
	hasPull := false
	for _, k := range md.Keys {
		if k == "Pull" {
			hasPull = true
			break
		}
	}

	if !hasPull {
		c.Pull = true
	}

	// Default to the normal Docker type
	if c.Comm.Type == "" {
		c.Comm.Type = "docker"
	}

	var errs *packer.MultiError
	if es := c.Comm.Prepare(&c.ctx); len(es) > 0 {
		errs = packer.MultiErrorAppend(errs, es...)
	}
	if c.Image == "" {
		errs = packer.MultiErrorAppend(errs, errImageNotSpecified)
	}

	if (c.ExportPath != "" && c.Commit) || (c.ExportPath != "" && c.Discard) || (c.Commit && c.Discard) {
		errs = packer.MultiErrorAppend(errs, errArtifactUseConflict)
	}

	if c.ExportPath == "" && !c.Commit && !c.Discard {
		errs = packer.MultiErrorAppend(errs, errArtifactNotUsed)
	}

	if c.ExportPath != "" {
		if fi, err := os.Stat(c.ExportPath); err == nil && fi.IsDir() {
			errs = packer.MultiErrorAppend(errs, errExportPathNotFile)
		}
	}

	if c.ContainerDir == "" {
		c.ContainerDir = "/packer-files"
	}

	if c.EcrLogin && c.LoginServer == "" {
		errs = packer.MultiErrorAppend(errs, fmt.Errorf("ECR login requires login server to be provided."))
	}

	if errs != nil && len(errs.Errors) > 0 {
		return nil, nil, errs
	}

	return c, nil, nil
}
<commit_msg>Updated docker's default config to use regular bourne shell instead of bourne again. Closes #6920.<commit_after>package docker

import (
	"fmt"
	"os"

	"github.com/hashicorp/packer/common"
	"github.com/hashicorp/packer/helper/communicator"
	"github.com/hashicorp/packer/helper/config"
	"github.com/hashicorp/packer/packer"
	"github.com/hashicorp/packer/template/interpolate"
	"github.com/mitchellh/mapstructure"
)

var (
	errArtifactNotUsed     = fmt.Errorf("No instructions given for handling the artifact; expected commit, discard, or export_path")
	errArtifactUseConflict = fmt.Errorf("Cannot specify more than one of commit, discard, and export_path")
	errExportPathNotFile   = fmt.Errorf("export_path must be a file, not a directory")
	errImageNotSpecified   = fmt.Errorf("Image must be specified")
)

type Config struct {
	common.PackerConfig `mapstructure:",squash"`
	Comm                communicator.Config `mapstructure:",squash"`

	Author         string
	Changes        []string
	Commit         bool
	ContainerDir   string `mapstructure:"container_dir"`
	Discard        bool
	ExecUser       string `mapstructure:"exec_user"`
	ExportPath     string `mapstructure:"export_path"`
	Image          string
	Message        string
	Privileged     bool `mapstructure:"privileged"`
	Pty            bool
	Pull           bool
	RunCommand     []string `mapstructure:"run_command"`
	Volumes        map[string]string
	FixUploadOwner bool `mapstructure:"fix_upload_owner"`

	// This is used to login to dockerhub to pull a private base container. For
	// pushing to dockerhub, see the docker post-processors
	Login           bool
	LoginPassword   string `mapstructure:"login_password"`
	LoginServer     string `mapstructure:"login_server"`
	LoginUsername   string `mapstructure:"login_username"`
	EcrLogin        bool   `mapstructure:"ecr_login"`
	AwsAccessConfig `mapstructure:",squash"`

	ctx interpolate.Context
}

func NewConfig(raws ...interface{}) (*Config, []string, error) {
	c := new(Config)

	c.FixUploadOwner = true

	var md mapstructure.Metadata
	err := config.Decode(c, &config.DecodeOpts{
		Metadata:           &md,
		Interpolate:        true,
		InterpolateContext: &c.ctx,
		InterpolateFilter: &interpolate.RenderFilter{
			Exclude: []string{
				"run_command",
			},
		},
	}, raws...)
	if err != nil {
		return nil, nil, err
	}

	// Defaults
	if len(c.RunCommand) == 0 {
		c.RunCommand = []string{"-d", "-i", "-t", "{{.Image}}", "/bin/sh"}
	}

	// Default Pull if it wasn't set
	hasPull := false
	for _, k := range md.Keys {
		if k == "Pull" {
			hasPull = true
			break
		}
	}

	if !hasPull {
		c.Pull = true
	}

	// Default to the normal Docker type
	if c.Comm.Type == "" {
		c.Comm.Type = "docker"
	}

	var errs *packer.MultiError
	if es := c.Comm.Prepare(&c.ctx); len(es) > 0 {
		errs = packer.MultiErrorAppend(errs, es...)
	}
	if c.Image == "" {
		errs = packer.MultiErrorAppend(errs, errImageNotSpecified)
	}

	if (c.ExportPath != "" && c.Commit) || (c.ExportPath != "" && c.Discard) || (c.Commit && c.Discard) {
		errs = packer.MultiErrorAppend(errs, errArtifactUseConflict)
	}

	if c.ExportPath == "" && !c.Commit && !c.Discard {
		errs = packer.MultiErrorAppend(errs, errArtifactNotUsed)
	}

	if c.ExportPath != "" {
		if fi, err := os.Stat(c.ExportPath); err == nil && fi.IsDir() {
			errs = packer.MultiErrorAppend(errs, errExportPathNotFile)
		}
	}

	if c.ContainerDir == "" {
		c.ContainerDir = "/packer-files"
	}

	if c.EcrLogin && c.LoginServer == "" {
		errs = packer.MultiErrorAppend(errs, fmt.Errorf("ECR login requires login server to be provided."))
	}

	if errs != nil && len(errs.Errors) > 0 {
		return nil, nil, errs
	}

	return c, nil, nil
}
<|endoftext|>