<commit_before>/*
** spend.go
**
** cs4501 Fall 2015
** Problem Set 1
*/

/*
For this program to execute correctly the following needs to be provided:

- An internet connection
- A private key
- A receiving address
- The raw json of the funding transaction
- The index into that transaction that funds your private key.

The program will formulate a transaction from these provided parameters
and then it will dump the newly formed tx to the command line as well as
try to broadcast the transaction into the bitcoin network. The raw hex dumped
by the program can parsed into a 'semi' human readable format using services
like: https://blockchain.info/decode-tx

*/

package main

import (
	"bytes"
	"encoding/hex"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"

	"github.com/btcsuite/btcd/btcec"
	"github.com/btcsuite/btcd/chaincfg"
	"github.com/btcsuite/btcd/txscript"
	"github.com/btcsuite/btcutil"
	"github.com/btcsuite/btcd/wire"
)

var toaddress = flag.String("toaddress", "", "The address to send Bitcoin to.")
var privkey = flag.String("privkey", "", "The private key of the input tx.")
var txid = flag.String("txid", "", "The transaction id corresponding to the funding Bitcoin transaction.")
var vout = flag.Int("vout", -1, "The index into the funding transaction.")
var amount = flag.Int64("amount", -1, "The number of satoshis for the transaction" )

// Use 10,000 satoshi as the standard transaction fee.
const TX_FEE = 10000

type requiredArgs struct {
	txid      *wire.ShaHash
	vout      uint32
	toAddress btcutil.Address
	privKey   *btcec.PrivateKey
  amount    int64
}

// getArgs parses command line args and asserts that a private key and an
// address are present and correctly formatted.
func getArgs() requiredArgs {
	flag.Parse()
	if *toaddress == "" || *privkey == "" || *txid == "" || *vout == -1 || *amount == -1 {
		fmt.Println("\nThis program generates a bitcoin trans action that moves coins from an input to an output.\n" +
			"You must provide a key, a receiving address, a transaction id (the hash\n" +
			"of a tx), the amount to be transferred (in satoshis), and the index into\n" +
      "the outputs of that tx that fund your address. Use http://blockchain.info/pushtx\n" +
			"to send the raw transaction.\n")
		flag.PrintDefaults()
		fmt.Println("")
		os.Exit(0)
	}

	pkBytes, err := hex.DecodeString(*privkey)
	if err != nil {
		log.Fatal(err)
	}

	// PrivKeyFromBytes returns public key as a separate result, but can ignore it here.
	key, _ := btcec.PrivKeyFromBytes(btcec.S256(), pkBytes)

	addr, err := btcutil.DecodeAddress(*toaddress, &chaincfg.MainNetParams)
	if err != nil {
		log.Fatal(err)
	}

	txid, err := wire.NewShaHashFromStr(*txid)
	if err != nil {
		log.Fatal(err)
	}

	args := requiredArgs{
		txid:      txid,
		vout:      uint32(*vout),
		toAddress: addr,
		privKey:   key,
    amount:    int64(*amount),
	}

	return args
}

type BlockChainInfoTxOut struct {
	Value     int    `json:"value"`
	ScriptHex string `json:"script"`
}

type blockChainInfoTx struct {
	Ver     int                   `json:"ver"`
	Hash    string                `json:"hash"`
	Outputs []BlockChainInfoTxOut `json:"out"`
}

// Uses the txid of the target funding transaction and asks blockchain.info's
// api for information (in json) relaated to that transaction.
func lookupTxid(hash *wire.ShaHash) *blockChainInfoTx {

	url := "https://blockchain.info/rawtx/" + hash.String()
	resp, err := http.Get(url)
	if err != nil {
		log.Fatal(fmt.Errorf("Tx Lookup failed: %v", err))
	}

	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(fmt.Errorf("TxInfo read failed: %s", err))
	}

	//fmt.Printf("%s\n", b)
	txinfo := &blockChainInfoTx{}
	err = json.Unmarshal(b, txinfo)
	if err != nil {
		log.Fatal(err)
	}

	if txinfo.Ver != 1 {
		log.Fatal(fmt.Errorf("Blockchain.info's response seems bad: %v", txinfo))
	}

	return txinfo
}

// getFundingParams pulls the relevant transaction information from the json returned by blockchain.info
// To generate a new valid transaction all of the parameters of the TxOut we are
// spending from must be used.
func getFundingParams(rawtx *blockChainInfoTx, vout uint32) (*wire.TxOut, *wire.OutPoint) {
	blkChnTxOut := rawtx.Outputs[vout]

	hash, err := wire.NewShaHashFromStr(rawtx.Hash)
	if err != nil {
		log.Fatal(err)
	}

	// Then convert it to a btcutil amount
	amnt := btcutil.Amount(int64(blkChnTxOut.Value))

	if err != nil {
		log.Fatal(err)
	}

	outpoint := wire.NewOutPoint(hash, vout)

	subscript, err := hex.DecodeString(blkChnTxOut.ScriptHex)
	if err != nil {
		log.Fatal(err)
	}

	oldTxOut := wire.NewTxOut(int64(amnt), subscript)

	return oldTxOut, outpoint
}

func main() {
	// Pull the required arguments off of the command line.
	reqArgs := getArgs()

	// Get the bitcoin tx from blockchain.info's api
	rawFundingTx := lookupTxid(reqArgs.txid)

	// Get the parameters we need from the funding transaction
	oldTxOut, outpoint := getFundingParams(rawFundingTx, reqArgs.vout)

	// Formulate a new transaction from the provided parameters
	tx := wire.NewMsgTx()

	// Create the TxIn
	txin := createTxIn(outpoint)
	tx.AddTxIn(txin)

	// Create the TxOut
	txout := createTxOut(oldTxOut.Value, reqArgs.toAddress)
	tx.AddTxOut(txout)

	// Generate a signature over the whole tx.
	sig := generateSig(tx, reqArgs.privKey, oldTxOut.PkScript)
	tx.TxIn[0].SignatureScript = sig

	// Dump the bytes to stdout
	dumpHex(tx)

	// Send the transaction to the network
  broadcastTx(tx)
}

// createTxIn pulls the outpoint out of the funding TxOut and uses it as a reference
// for the txin that will be placed in a new transaction.
func createTxIn(outpoint *wire.OutPoint) *wire.TxIn {
	// The second arg is the txin's signature script, which we are leaving empty
	// until the entire transaction is ready.
	txin := wire.NewTxIn(outpoint, []byte{})
	return txin
}

// createTxOut generates a TxOut that can be added to a transaction.
func createTxOut(inCoin int64, addr btcutil.Address) *wire.TxOut {
	// Pay the minimum network fee so that nodes will broadcast the tx.
	outCoin := *amount
  fmt.Printf("inCoin: %v", inCoin)
  if outCoin == 0 {
    log.Fatal("You probably don't want to transfer 0 satoshis")
  }
  if outCoin > inCoin - TX_FEE {
    log.Fatal("Can't complete transaction--the request amount" +
    " is larger than available funds after transaction fee")
  }
	// Take the address and generate a PubKeyScript out of it
	script, err := txscript.PayToAddrScript(addr)
	if err != nil {
		log.Fatal(err)
	}
	txout := wire.NewTxOut(outCoin, script)
	return txout
}

// generateSig requires a transaction, a private key, and the bytes of the raw
// scriptPubKey. It will then generate a signature over all of the outputs of
// the provided tx. This is the last step of creating a valid transaction.
func generateSig(tx *wire.MsgTx, privkey *btcec.PrivateKey, scriptPubKey []byte) []byte {

	// The all important signature. Each input is documented below.
	scriptSig, err := txscript.SignatureScript(
		tx,                   // The tx to be signed.
		0,                    // The index of the txin the signature is for.
		scriptPubKey,         // The other half of the script from the PubKeyHash.
		txscript.SigHashAll,  // The signature flags that indicate what the sig covers.
		privkey,              // The key to generate the signature with.
		true,                 // The compress sig flag. This saves space on the blockchain.
	)
	if err != nil {
		log.Fatal(err)
	}

	return scriptSig
}

// dumpHex dumps the raw bytes of a Bitcoin transaction to stdout. This is the
// format that Bitcoin wire's protocol accepts, so you could connect to a node,
// send them these bytes, and if the tx was valid, the node would forward the
// tx through the network.
func dumpHex(tx *wire.MsgTx) {
	buf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize()))
	tx.Serialize(buf)
	hexstr := hex.EncodeToString(buf.Bytes())
	fmt.Println("Here is your raw bitcoin transaction:")
	fmt.Println(hexstr)
}

type sendTxJson struct {
	RawTx string `json:"rawtx"`
}

// broadcastTx tries to send the transaction using an api that will broadcast
// a submitted transaction on behalf of the user.
//
// The transaction is broadcast to the bitcoin network using this API:
//    https://github.com/bitpay/insight-api
//
func broadcastTx(tx *wire.MsgTx) {
	buf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize()))
	tx.Serialize(buf)
	hexstr := hex.EncodeToString(buf.Bytes())

	url := "https://insight.bitpay.com/api/tx/send"
	contentType := "application/json"

	fmt.Printf("Sending transaction to: %s\n", url)
	sendTxJson := &sendTxJson{RawTx: hexstr}
	j, err := json.Marshal(sendTxJson)
	if err != nil {
		log.Fatal(fmt.Errorf("Broadcasting the tx failed: %v", err))
	}
	buf = bytes.NewBuffer(j)
	resp, err := http.Post(url, contentType, buf)
	if err != nil {
		log.Fatal(fmt.Errorf("Broadcasting the tx failed: %v", err))
	}

	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("The sending api responded with:\n%s\n", b)
}
<commit_msg>remainder redirection implemented<commit_after>/*
** spend.go
**
** cs4501 Fall 2015
** Problem Set 1
*/

/*
For this program to execute correctly the following needs to be provided:

- An internet connection
- A private key
- A receiving address
- The raw json of the funding transaction
- The index into that transaction that funds your private key.

The program will formulate a transaction from these provided parameters
and then it will dump the newly formed tx to the command line as well as
try to broadcast the transaction into the bitcoin network. The raw hex dumped
by the program can parsed into a 'semi' human readable format using services
like: https://blockchain.info/decode-tx

*/

package main

import (
	"bytes"
	"encoding/hex"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"

	"github.com/btcsuite/btcd/btcec"
	"github.com/btcsuite/btcd/chaincfg"
	"github.com/btcsuite/btcd/txscript"
	"github.com/btcsuite/btcutil"
	"github.com/btcsuite/btcd/wire"
)

var toaddress = flag.String("toaddress", "", "The address to send Bitcoin to.")
var privkey = flag.String("privkey", "", "The private key of the input tx.")
var txid = flag.String("txid", "", "The transaction id corresponding to the funding Bitcoin transaction.")
var vout = flag.Int("vout", -1, "The index into the funding transaction.")
var amount = flag.Int64("amount", -1, "The number of satoshis for the transaction" )

// Use 10,000 satoshi as the standard transaction fee.
const TX_FEE = 10000

type requiredArgs struct {
	txid      *wire.ShaHash
	vout      uint32
	toAddress btcutil.Address
	privKey   *btcec.PrivateKey
  amount    int64
}

// getArgs parses command line args and asserts that a private key and an
// address are present and correctly formatted.
func getArgs() requiredArgs {
	flag.Parse()
	if *toaddress == "" || *privkey == "" || *txid == "" || *vout == -1 || *amount == -1 {
		fmt.Println("\nThis program generates a bitcoin trans action that moves coins from an input to an output.\n" +
			"You must provide a key, a receiving address, a transaction id (the hash\n" +
			"of a tx), the amount to be transferred (in satoshis), and the index into\n" +
      "the outputs of that tx that fund your address. Use http://blockchain.info/pushtx\n" +
			"to send the raw transaction.\n")
		flag.PrintDefaults()
		fmt.Println("")
		os.Exit(0)
	}

	pkBytes, err := hex.DecodeString(*privkey)
	if err != nil {
		log.Fatal(err)
	}

	// PrivKeyFromBytes returns public key as a separate result, but can ignore it here.
	key, _ := btcec.PrivKeyFromBytes(btcec.S256(), pkBytes)

	addr, err := btcutil.DecodeAddress(*toaddress, &chaincfg.MainNetParams)
	if err != nil {
		log.Fatal(err)
	}

	txid, err := wire.NewShaHashFromStr(*txid)
	if err != nil {
		log.Fatal(err)
	}

	args := requiredArgs{
		txid:      txid,
		vout:      uint32(*vout),
		toAddress: addr,
		privKey:   key,
    amount:    int64(*amount),
	}

	return args
}

type BlockChainInfoTxOut struct {
	Value     int    `json:"value"`
	ScriptHex string `json:"script"`
}

type blockChainInfoTx struct {
	Ver     int                   `json:"ver"`
	Hash    string                `json:"hash"`
	Outputs []BlockChainInfoTxOut `json:"out"`
}

// Uses the txid of the target funding transaction and asks blockchain.info's
// api for information (in json) relaated to that transaction.
func lookupTxid(hash *wire.ShaHash) *blockChainInfoTx {

	url := "https://blockchain.info/rawtx/" + hash.String()
	resp, err := http.Get(url)
	if err != nil {
		log.Fatal(fmt.Errorf("Tx Lookup failed: %v", err))
	}

	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(fmt.Errorf("TxInfo read failed: %s", err))
	}

	//fmt.Printf("%s\n", b)
	txinfo := &blockChainInfoTx{}
	err = json.Unmarshal(b, txinfo)
	if err != nil {
		log.Fatal(err)
	}

	if txinfo.Ver != 1 {
		log.Fatal(fmt.Errorf("Blockchain.info's response seems bad: %v", txinfo))
	}

	return txinfo
}

// getFundingParams pulls the relevant transaction information from the json returned by blockchain.info
// To generate a new valid transaction all of the parameters of the TxOut we are
// spending from must be used.
func getFundingParams(rawtx *blockChainInfoTx, vout uint32) (*wire.TxOut, *wire.OutPoint) {
	blkChnTxOut := rawtx.Outputs[vout]

	hash, err := wire.NewShaHashFromStr(rawtx.Hash)
	if err != nil {
		log.Fatal(err)
	}

	// Then convert it to a btcutil amount
	amnt := btcutil.Amount(int64(blkChnTxOut.Value))

	if err != nil {
		log.Fatal(err)
	}

	outpoint := wire.NewOutPoint(hash, vout)

	subscript, err := hex.DecodeString(blkChnTxOut.ScriptHex)
	if err != nil {
		log.Fatal(err)
	}

	oldTxOut := wire.NewTxOut(int64(amnt), subscript)

	return oldTxOut, outpoint
}

func main() {
	// Pull the required arguments off of the command line.
	reqArgs := getArgs()

	// Get the bitcoin tx from blockchain.info's api
	rawFundingTx := lookupTxid(reqArgs.txid)

	// Get the parameters we need from the funding transaction
	oldTxOut, outpoint := getFundingParams(rawFundingTx, reqArgs.vout)

	// Formulate a new transaction from the provided parameters
	tx := wire.NewMsgTx()

	// Create the TxIn
	txin := createTxIn(outpoint)
	tx.AddTxIn(txin)

	// Create the TxOut
	txout := createTxOut(oldTxOut.Value, reqArgs.toAddress)
	txrem := createTxRemainder(oldTxOut.Value)
	tx.AddTxOut(txout)
  tx.AddTxOut(txrem)

	// Generate a signature over the whole tx.
	sig := generateSig(tx, reqArgs.privKey, oldTxOut.PkScript)
	tx.TxIn[0].SignatureScript = sig

	// Dump the bytes to stdout
	dumpHex(tx)

	// Send the transaction to the network
  broadcastTx(tx)
}

// createTxIn pulls the outpoint out of the funding TxOut and uses it as a reference
// for the txin that will be placed in a new transaction.
func createTxIn(outpoint *wire.OutPoint) *wire.TxIn {
	// The second arg is the txin's signature script, which we are leaving empty
	// until the entire transaction is ready.
	txin := wire.NewTxIn(outpoint, []byte{})
	return txin
}

// createTxOut generates a TxOut that can be added to a transaction.
func createTxOut(inCoin int64, addr btcutil.Address) *wire.TxOut {
	// Pay the minimum network fee so that nodes will broadcast the tx.
	outCoin := *amount
  if outCoin == 0 {
    log.Fatal("You probably don't want to transfer 0 satoshis")
  }
  if outCoin > inCoin - TX_FEE {
    log.Fatal("Can't complete transaction--the request amount" +
    " is larger than available funds after transaction fee")
  }
	// Take the address and generate a PubKeyScript out of it
	script, err := txscript.PayToAddrScript(addr)
	if err != nil {
		log.Fatal(err)
	}
	txout := wire.NewTxOut(outCoin, script)
	return txout
}

func createTxRemainder(inCoin int64) *wire.TxOut {
  remainder := inCoin - *amount - TX_FEE

  // Put the remainder back in our wallet
	pkBytes, err := hex.DecodeString(*privkey)
	if err != nil {
		log.Fatal(err)
	}
  // Get pubkey object
	_, pubkey := btcec.PrivKeyFromBytes(btcec.S256(), pkBytes)

  // Get an address object from WIF string
  changeAddress := generateAddr(pubkey)

  script, err := txscript.PayToAddrScript(changeAddress)
  if err != nil {
    log.Fatal(err)
  }
  remtx := wire.NewTxOut(remainder, script)
  return remtx
}

//taken from address.go
func generateAddr(pub *btcec.PublicKey) *btcutil.AddressPubKeyHash {

  net := &chaincfg.MainNetParams

  // Serialize the public key into bytes and then run ripemd160(sha256(b)) on it
  b := btcutil.Hash160(pub.SerializeCompressed())

  // Convert the hashed public key into the btcsuite type so that the library
  // will handle the base58 encoding when we call addr.String()
  addr, err := btcutil.NewAddressPubKeyHash(b, net)
  if err != nil {
    log.Fatal(err)
  }

  return addr
}

// generateSig requires a transaction, a private key, and the bytes of the raw
// scriptPubKey. It will then generate a signature over all of the outputs of
// the provided tx. This is the last step of creating a valid transaction.
func generateSig(tx *wire.MsgTx, privkey *btcec.PrivateKey, scriptPubKey []byte) []byte {

	// The all important signature. Each input is documented below.
	scriptSig, err := txscript.SignatureScript(
		tx,                   // The tx to be signed.
		0,                    // The index of the txin the signature is for.
		scriptPubKey,         // The other half of the script from the PubKeyHash.
		txscript.SigHashAll,  // The signature flags that indicate what the sig covers.
		privkey,              // The key to generate the signature with.
		true,                 // The compress sig flag. This saves space on the blockchain.
	)
	if err != nil {
		log.Fatal(err)
	}

	return scriptSig
}

// dumpHex dumps the raw bytes of a Bitcoin transaction to stdout. This is the
// format that Bitcoin wire's protocol accepts, so you could connect to a node,
// send them these bytes, and if the tx was valid, the node would forward the
// tx through the network.
func dumpHex(tx *wire.MsgTx) {
	buf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize()))
	tx.Serialize(buf)
	hexstr := hex.EncodeToString(buf.Bytes())
	fmt.Println("Here is your raw bitcoin transaction:")
	fmt.Println(hexstr)
}

type sendTxJson struct {
	RawTx string `json:"rawtx"`
}

// broadcastTx tries to send the transaction using an api that will broadcast
// a submitted transaction on behalf of the user.
//
// The transaction is broadcast to the bitcoin network using this API:
//    https://github.com/bitpay/insight-api
//
func broadcastTx(tx *wire.MsgTx) {
	buf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize()))
	tx.Serialize(buf)
	hexstr := hex.EncodeToString(buf.Bytes())

	url := "https://insight.bitpay.com/api/tx/send"
	contentType := "application/json"

	fmt.Printf("Sending transaction to: %s\n", url)
	sendTxJson := &sendTxJson{RawTx: hexstr}
	j, err := json.Marshal(sendTxJson)
	if err != nil {
		log.Fatal(fmt.Errorf("Broadcasting the tx failed: %v", err))
	}
	buf = bytes.NewBuffer(j)
	resp, err := http.Post(url, contentType, buf)
	if err != nil {
		log.Fatal(fmt.Errorf("Broadcasting the tx failed: %v", err))
	}

	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("The sending api responded with:\n%s\n", b)
}
<|endoftext|>


<commit_before>// Package srest contains utilyties for sites creation and web services.
/*
	RESTfuler interface:
		One(w http.ResponseWriter, r *http.Request)
		List(w http.ResponseWriter, r *http.Request)
		Create(w http.ResponseWriter, r *http.Request)
		Update(w http.ResponseWriter, r *http.Request)
		Delete(w http.ResponseWriter, r *http.Request)

	Modeler interface:
		IsValid() error
*/
// The MIT License (MIT)
//
// Copyright (c) 2016 Angel Del Castillo
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
package srest

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"html/template"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"os/signal"
	"path"
	"path/filepath"
	"strings"
	"sync"
	"syscall"

	"github.com/bmizerany/pat"
	"github.com/gorilla/schema"
)

var (
	debug        bool
	templatesDir string

	// DefaultFuncMap can be used with LoadViews for common template tasks like:
	//
	// cap: capitalize strings
	// eqs: compare value of two types.
	DefaultFuncMap = deffuncmap()

	// ErrModeler error returned when modeler interface is
	// not implemented.
	ErrModeler = errors.New("srest: modeler interface not found")

	// ErrTemplatesInited error returned when LoadViews
	// function is called twice.
	ErrTemplatesInited = errors.New("srest: templates already inited")

	// ErrTemplatesNil error returned when not template files
	// were loaded.
	ErrTemplatesNil = errors.New("srest: not templates found")

	// ErrTemplateNotFound error returned when template name
	// is not present.
	ErrTemplateNotFound = errors.New("srest: template not found")
)

func deffuncmap() template.FuncMap {
	return template.FuncMap{
		"cap": func(s string) string {
			if len(s) < 1 {
				return s
			}
			return strings.ToUpper(s[:1]) + s[1:]
		},
		// eqs validates x and y are equal no matter type.
		"eqs": func(x, y interface{}) bool {
			return fmt.Sprintf("%v", x) == fmt.Sprintf("%v", y)
		},
	}
}

// Options struct
type Options struct {
	UseTLS bool
	TLSCer string
	TLSKey string
}

var (
	// DefaultConf contains default configuration without TLS.
	DefaultConf = &Options{
		UseTLS: false,
	}
)

// SREST struct.
type SREST struct {
	Mux     *pat.PatternServeMux
	Options *Options
}

// New returns a new server.
func New(options *Options) *SREST {
	if options == nil {
		options = DefaultConf
	}
	m := &SREST{
		Mux:     pat.New(),
		Options: options,
	}
	return m
}

// Get wrapper useful for add middleware like Use method.
func (m *SREST) Get(uri string, hf http.Handler, mws ...func(http.Handler) http.Handler) {
	uri = clean(uri)
	m.Mux.Get(uri, chainHandler(hf, mws...))
}

// Post wrapper useful for add middleware like Use method.
func (m *SREST) Post(uri string, hf http.Handler, mws ...func(http.Handler) http.Handler) {
<<<<<<< HEAD
	// FIXME; make test for clean POST endpoint.
=======
>>>>>>> release/v0.0.2
	uri = filepath.Clean(uri)
	m.Mux.Post(uri, chainHandler(hf, mws...))
}

// Put wrapper useful for add middleware like Use method.
func (m *SREST) Put(uri string, hf http.Handler, mws ...func(http.Handler) http.Handler) {
	uri = clean(uri)
	m.Mux.Put(uri, chainHandler(hf, mws...))
}

// Del wrapper useful for add middleware like Use method.
func (m *SREST) Del(uri string, hf http.Handler, mws ...func(http.Handler) http.Handler) {
	uri = clean(uri)
	m.Mux.Del(uri, chainHandler(hf, mws...))
}

// Use receives a RESTfuler interface and generates endpoints for:
//
// GET /:id
// GET /
// POST /
// PUT /:id
// DELETE /:id
func (m *SREST) Use(uri string, n RESTfuler, mws ...func(http.Handler) http.Handler) {
	uri = clean(uri)
	m.Get(uri+"/:id", http.HandlerFunc(n.One), mws...)
	m.Get(uri, http.HandlerFunc(n.List), mws...)
	m.Post(uri, http.HandlerFunc(n.Create), mws...)
	m.Put(uri+"/:id", http.HandlerFunc(n.Update), mws...)
	m.Del(uri+"/:id", http.HandlerFunc(n.Delete), mws...)
}

// Run start a server listening with http.ListenAndServe or http.ListenAndServeTLS
// returns a channel bind it to SIGTERM and SIGINT signal
// you will block this way: <-m.Run()
func (m *SREST) Run(port int) chan os.Signal {
	// TODO; change logic to allow server stop without leaking a goroutine and handle graceful shutdown.
	c := make(chan os.Signal)
	signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
	go func() {
		addrs := fmt.Sprintf(":%v", port)
		log.Printf("srest: Run %v", addrs)
		var err error
		if m.Options.UseTLS {
			err = http.ListenAndServeTLS(addrs, m.Options.TLSCer, m.Options.TLSKey, m.Mux)
		} else {
			err = http.ListenAndServe(addrs, m.Mux)
		}
		if err != nil {
			log.Printf("srest: Run : ListenAndServe : err [%s]", err)
		}
	}()
	return c
}

// Debug enables template files reload on every request.
func (m *SREST) Debug(ok bool) {
	debug = ok
}

// Debug enables template files reload on every request.
func Debug(ok bool) {
	debug = ok
}

// clean uri path.
func clean(uri string) string {
	if uri == "/" {
		return uri
	}
	return path.Clean(uri) + "/"
}

// Static handler.
//
// Usage:
// Get("/public", Static("/public", "mydir"))
func Static(uri, dir string) http.Handler {
	uri = path.Clean(uri) + "/"
	dir = path.Clean(dir) + "/"
	return http.StripPrefix(uri, http.FileServer(http.Dir(dir)))
}

func chainHandler(fh http.Handler, mws ...func(http.Handler) http.Handler) http.Handler {
	// no middlewares then return handler
	if len(mws) < 1 {
		return fh
	}

	var cs []func(http.Handler) http.Handler
	cs = append(cs, mws...)
	var h http.Handler
	h = fh // this disable linter warning
	for i := range cs {
		h = cs[len(cs)-1-i](h)
	}
	return h
}

// RESTfuler interface
type RESTfuler interface {
	Create(w http.ResponseWriter, r *http.Request)
	One(w http.ResponseWriter, r *http.Request)
	List(w http.ResponseWriter, r *http.Request)
	Update(w http.ResponseWriter, r *http.Request)
	Delete(w http.ResponseWriter, r *http.Request)
}

var (
	// schDecoder default gorilla schema decoder.
	schDecoder = schema.NewDecoder()
)

// Bind implements gorilla schema and runs IsValid method from data.
func Bind(vars url.Values, dst interface{}) error {
	err := schDecoder.Decode(dst, vars)
	if err != nil {
		return err
	}
	// check model is valid
	mo, ok := dst.(Modeler)
	if !ok {
		return ErrModeler
	}
	return mo.IsValid()
}

// JSON writes v to response writer.
func JSON(w http.ResponseWriter, v interface{}) error {
	w.Header().Set("Content-Type", "application/json")
	return json.NewEncoder(w).Encode(v)
}

var (
	// templates collection.
	templates  = map[string]*template.Template{}
	tmplInited bool
	mut        sync.RWMutex
)

// LoadViews read html files on dir tree and parses it
// as templates.
// In order to render templates you need to call Render
// function passing <file.html> or <subdir>/<file.html>
// as name for template.
//
// funcMap will overwrite DefaultFuncMap.
func LoadViews(dir string, funcMap template.FuncMap) error {
	if tmplInited {
		return ErrTemplatesInited
	}

	dir = filepath.Clean(dir)
	templatesDir = dir

	var files []string
	var data []byte
	err := filepath.Walk(dir, func(name string, info os.FileInfo, err error) error {
		// take template name from subdir+filename
		tname := strings.Replace(name, dir+"/", "", -1)
		ext := filepath.Ext(name)
		// ommit files not .html
		if ext != ".html" {
			return nil
		}
		b, err := ioutil.ReadFile(name)
		if err != nil {
			return err
		}
		// append to unique template data
		data = append(data, []byte(fmt.Sprintf(`{{define "%s"}}`, tname))...)
		data = append(data, b...)
		data = append(data, []byte(`{{end}}`)...)
		// wee need this after for template parsing
		files = append(files, tname)
		return nil
	})
	if err != nil {
		return err
	}

	DefaultFuncMap = funcMap
	for _, k := range files {
		// template parsing
		templates[k] = template.Must(template.New(k).Funcs(funcMap).Parse(string(data)))
	}

	tmplInited = true
	return nil
}

// Render writes a template to http response.
// In order to render templates you need to call Render
// function passing <file.html> or <subdir>/<file.html>
// as name for template.
func Render(w http.ResponseWriter, name string, v interface{}) error {
	// for now use a mutex, later implementations can use sync.Pool of templates.
	mut.RLock()
	defer mut.RUnlock()

	if debug {
		// clean templates
		for k := range templates {
			delete(templates, k)
		}
		tmplInited = false
		// load templates again
		// this generates a race condition. TODO; check later if a really trouble
		// on debug mode, this is not expected to be turned on into production.
		err := LoadViews(templatesDir, DefaultFuncMap)
		if err != nil {
			return err
		}
	}
	if !tmplInited {
		return ErrTemplatesNil
	}
	w.Header().Set("Content-Type", "text/html; charset=utf-8")

	// write template to buffer to make sure is working.
	var buf bytes.Buffer
	t, ok := templates[name]
	if !ok {
		w.WriteHeader(http.StatusInternalServerError)
		w.Write([]byte("template not found"))
		return ErrTemplateNotFound
	}
	err := t.ExecuteTemplate(&buf, name, v)
	if err != nil {
		return err
	}
	// buffer writing was done without errors. Write to http
	// response.
	_, err = buf.WriteTo(w)
	return err
}

// Modeler interface
type Modeler interface {
	IsValid() error
}
<commit_msg>fix slashes endopoint.<commit_after>// Package srest contains utilyties for sites creation and web services.
/*
	RESTfuler interface:
		One(w http.ResponseWriter, r *http.Request)
		List(w http.ResponseWriter, r *http.Request)
		Create(w http.ResponseWriter, r *http.Request)
		Update(w http.ResponseWriter, r *http.Request)
		Delete(w http.ResponseWriter, r *http.Request)

	Modeler interface:
		IsValid() error
*/
// The MIT License (MIT)
//
// Copyright (c) 2016 Angel Del Castillo
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
package srest

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"html/template"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"os/signal"
	"path"
	"path/filepath"
	"strings"
	"sync"
	"syscall"

	"github.com/bmizerany/pat"
	"github.com/gorilla/schema"
)

var (
	debug        bool
	templatesDir string

	// DefaultFuncMap can be used with LoadViews for common template tasks like:
	//
	// cap: capitalize strings
	// eqs: compare value of two types.
	DefaultFuncMap = deffuncmap()

	// ErrModeler error returned when modeler interface is
	// not implemented.
	ErrModeler = errors.New("srest: modeler interface not found")

	// ErrTemplatesInited error returned when LoadViews
	// function is called twice.
	ErrTemplatesInited = errors.New("srest: templates already inited")

	// ErrTemplatesNil error returned when not template files
	// were loaded.
	ErrTemplatesNil = errors.New("srest: not templates found")

	// ErrTemplateNotFound error returned when template name
	// is not present.
	ErrTemplateNotFound = errors.New("srest: template not found")
)

func deffuncmap() template.FuncMap {
	return template.FuncMap{
		"cap": func(s string) string {
			if len(s) < 1 {
				return s
			}
			return strings.ToUpper(s[:1]) + s[1:]
		},
		// eqs validates x and y are equal no matter type.
		"eqs": func(x, y interface{}) bool {
			return fmt.Sprintf("%v", x) == fmt.Sprintf("%v", y)
		},
	}
}

// Options struct
type Options struct {
	UseTLS bool
	TLSCer string
	TLSKey string
}

var (
	// DefaultConf contains default configuration without TLS.
	DefaultConf = &Options{
		UseTLS: false,
	}
)

// SREST struct.
type SREST struct {
	Mux     *pat.PatternServeMux
	Options *Options
}

// New returns a new server.
func New(options *Options) *SREST {
	if options == nil {
		options = DefaultConf
	}
	m := &SREST{
		Mux:     pat.New(),
		Options: options,
	}
	return m
}

// Get wrapper allows GET endpoints and middlewares. It will
// generate endpoints for `resource` and `resource/` because
// some services requires both endpoints.
func (m *SREST) Get(uri string, hf http.Handler, mws ...func(http.Handler) http.Handler) {
	// FIXME; allow both o remove one?
	m.Mux.Get(path.Clean(uri), chainHandler(hf, mws...))
	m.Mux.Get(path.Clean(uri)+"/", chainHandler(hf, mws...))
}

// Post wrapper useful for add middleware like Use method.
func (m *SREST) Post(uri string, hf http.Handler, mws ...func(http.Handler) http.Handler) {
<<<<<<< HEAD
<<<<<<< HEAD
	// FIXME; make test for clean POST endpoint.
=======
>>>>>>> release/v0.0.2
	uri = filepath.Clean(uri)
	m.Mux.Post(uri, chainHandler(hf, mws...))
=======
	m.Mux.Post(path.Clean(uri), chainHandler(hf, mws...))
>>>>>>> release/v0.0.3
}

// Put wrapper useful for add middleware like Use method.
func (m *SREST) Put(uri string, hf http.Handler, mws ...func(http.Handler) http.Handler) {
	m.Mux.Put(path.Clean(uri), chainHandler(hf, mws...))
}

// Del wrapper useful for add middleware like Use method.
func (m *SREST) Del(uri string, hf http.Handler, mws ...func(http.Handler) http.Handler) {
	m.Mux.Del(path.Clean(uri), chainHandler(hf, mws...))
}

// Use receives a RESTfuler interface and generates endpoints for:
//
// GET /:id
// GET /
// POST /
// PUT /:id
// DELETE /:id
func (m *SREST) Use(uri string, n RESTfuler, mws ...func(http.Handler) http.Handler) {
	m.Get(uri+"/:id", http.HandlerFunc(n.One), mws...)
	m.Get(uri, http.HandlerFunc(n.List), mws...)
	m.Post(uri, http.HandlerFunc(n.Create), mws...)
	m.Put(uri+"/:id", http.HandlerFunc(n.Update), mws...)
	m.Del(uri+"/:id", http.HandlerFunc(n.Delete), mws...)
}

// Run start a server listening with http.ListenAndServe or http.ListenAndServeTLS
// returns a channel bind it to SIGTERM and SIGINT signal
// you will block this way: <-m.Run()
func (m *SREST) Run(port int) chan os.Signal {
	// TODO; change logic to allow server stop without leaking a goroutine and handle graceful shutdown.
	c := make(chan os.Signal)
	signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
	go func() {
		addrs := fmt.Sprintf(":%v", port)
		log.Printf("srest: Run %v", addrs)
		var err error
		if m.Options.UseTLS {
			err = http.ListenAndServeTLS(addrs, m.Options.TLSCer, m.Options.TLSKey, m.Mux)
		} else {
			err = http.ListenAndServe(addrs, m.Mux)
		}
		if err != nil {
			log.Printf("srest: Run : ListenAndServe : err [%s]", err)
		}
	}()
	return c
}

// Debug enables template files reload on every request.
func (m *SREST) Debug(ok bool) {
	debug = ok
}

// Debug enables template files reload on every request.
func Debug(ok bool) {
	debug = ok
}

// Static handler.
//
// Usage:
// Get("/public", Static("/public", "mydir"))
func Static(uri, dir string) http.Handler {
	uri = path.Clean(uri) + "/"
	dir = path.Clean(dir) + "/"
	return http.StripPrefix(uri, http.FileServer(http.Dir(dir)))
}

func chainHandler(fh http.Handler, mws ...func(http.Handler) http.Handler) http.Handler {
	// no middlewares then return handler
	if len(mws) < 1 {
		return fh
	}

	var cs []func(http.Handler) http.Handler
	cs = append(cs, mws...)
	var h http.Handler
	h = fh // this disable linter warning
	for i := range cs {
		h = cs[len(cs)-1-i](h)
	}
	return h
}

// RESTfuler interface
type RESTfuler interface {
	Create(w http.ResponseWriter, r *http.Request)
	One(w http.ResponseWriter, r *http.Request)
	List(w http.ResponseWriter, r *http.Request)
	Update(w http.ResponseWriter, r *http.Request)
	Delete(w http.ResponseWriter, r *http.Request)
}

var (
	// schDecoder default gorilla schema decoder.
	schDecoder = schema.NewDecoder()
)

// Bind implements gorilla schema and runs IsValid method from data.
func Bind(vars url.Values, dst interface{}) error {
	err := schDecoder.Decode(dst, vars)
	if err != nil {
		return err
	}
	// check model is valid
	mo, ok := dst.(Modeler)
	if !ok {
		return ErrModeler
	}
	return mo.IsValid()
}

// JSON writes v to response writer.
func JSON(w http.ResponseWriter, v interface{}) error {
	w.Header().Set("Content-Type", "application/json")
	return json.NewEncoder(w).Encode(v)
}

var (
	// templates collection.
	templates  = map[string]*template.Template{}
	tmplInited bool
	mut        sync.RWMutex
)

// LoadViews read html files on dir tree and parses it
// as templates.
// In order to render templates you need to call Render
// function passing <file.html> or <subdir>/<file.html>
// as name for template.
//
// funcMap will overwrite DefaultFuncMap.
func LoadViews(dir string, funcMap template.FuncMap) error {
	if tmplInited {
		return ErrTemplatesInited
	}

	dir = filepath.Clean(dir)
	templatesDir = dir

	var files []string
	var data []byte
	err := filepath.Walk(dir, func(name string, info os.FileInfo, err error) error {
		// take template name from subdir+filename
		tname := strings.Replace(name, dir+"/", "", -1)
		ext := filepath.Ext(name)
		// ommit files not .html
		if ext != ".html" {
			return nil
		}
		b, err := ioutil.ReadFile(name)
		if err != nil {
			return err
		}
		// append to unique template data
		data = append(data, []byte(fmt.Sprintf(`{{define "%s"}}`, tname))...)
		data = append(data, b...)
		data = append(data, []byte(`{{end}}`)...)
		// wee need this after for template parsing
		files = append(files, tname)
		return nil
	})
	if err != nil {
		return err
	}

	DefaultFuncMap = funcMap
	for _, k := range files {
		// template parsing
		templates[k] = template.Must(template.New(k).Funcs(funcMap).Parse(string(data)))
	}

	tmplInited = true
	return nil
}

// Render writes a template to http response.
// In order to render templates you need to call Render
// function passing <file.html> or <subdir>/<file.html>
// as name for template.
func Render(w http.ResponseWriter, name string, v interface{}) error {
	// for now use a mutex, later implementations can use sync.Pool of templates.
	mut.RLock()
	defer mut.RUnlock()

	if debug {
		// clean templates
		for k := range templates {
			delete(templates, k)
		}
		tmplInited = false
		// load templates again
		// this generates a race condition. TODO; check later if a really trouble
		// on debug mode, this is not expected to be turned on into production.
		err := LoadViews(templatesDir, DefaultFuncMap)
		if err != nil {
			return err
		}
	}
	if !tmplInited {
		return ErrTemplatesNil
	}
	w.Header().Set("Content-Type", "text/html; charset=utf-8")

	// write template to buffer to make sure is working.
	var buf bytes.Buffer
	t, ok := templates[name]
	if !ok {
		w.WriteHeader(http.StatusInternalServerError)
		w.Write([]byte("template not found"))
		return ErrTemplateNotFound
	}
	err := t.ExecuteTemplate(&buf, name, v)
	if err != nil {
		return err
	}
	// buffer writing was done without errors. Write to http
	// response.
	_, err = buf.WriteTo(w)
	return err
}

// Modeler interface
type Modeler interface {
	IsValid() error
}
<|endoftext|>


<commit_before>package boardgame

//Stack is one of the fundamental types in BoardGame. It represents an ordered
//stack of 0 or more Components, all from the same Deck. Each deck has 0 or
//more Stacks based off of it, and together they include all components in
//that deck, with no component residing in more than one stack. Stacks model
//things like a stack of cards, a collection of resource tokens, etc.
type Stack struct {
	//The Game that we're associated with
	Game *Game
	//DeckName is the name of the deck in the game's ComponentChest that this
	//Stack is tied to.
	DeckName string
	//The indexes from the given deck that this stack contains, in order.
	Indexes []int
}

//Len returns the number of items in the stack.
func (s *Stack) Len() int {
	return len(s.Indexes)
}

//ComponentAt fetches the component object representing the n-th object in
//this stack.
func (s *Stack) ComponentAt(index int) *Component {

	if index >= s.Len() || index < 0 {
		return nil
	}

	deck := s.Game.Chest.Deck(s.DeckName)

	if deck == nil {
		return nil
	}

	//We don't need to check that s.Indexes[index] is valid because it was
	//checked when it was set, and Decks are immutable.
	return deck.Components()[s.Indexes[index]]
}

//InsertFront puts the component at index 0 in this stack, moving all other
//items down by one. The Component you insert should not currently be a member
//of any other stacks, to maintain the deck invariant.
func (s *Stack) InsertFront(c *Component) {

	//TODO: this check should actually be done when the component is first put
	//into the deck.
	if c.GameName() != s.Game.Name {
		//We can only add components designed for this game
		return
	}

	if c.Address.Deck != s.DeckName {
		//We can only add items that are in our deck.

		//TODO: communicate an error
		return
	}

	s.Indexes = append([]int{c.Address.Index}, s.Indexes...)
}

/*

//InsertBack puts the component at the last index in this stack. The
//Component you insert should not currently be a member of any other stacks,
//to maintain the deck invariant.
func (s *Stack) InsertBack(c Component) {

}

//RemoveFront removes the component from the first slot in this stack,
//shifting all later components down by 1. You should then insert the
//component in another stack to maintain the deck invariant.
func (s *Stack) RemoveFront() Component {

}

//RemoveBack removes the component from the last slot in this stack. You
//should then insert the component in another stack to maintain the deck
//invariant.
func (s *Stack) RemoveBack() Component {

}

*/
<commit_msg>Removed a check for a thing that's already guaranteed elsewhere.<commit_after>package boardgame

//Stack is one of the fundamental types in BoardGame. It represents an ordered
//stack of 0 or more Components, all from the same Deck. Each deck has 0 or
//more Stacks based off of it, and together they include all components in
//that deck, with no component residing in more than one stack. Stacks model
//things like a stack of cards, a collection of resource tokens, etc.
type Stack struct {
	//The Game that we're associated with
	Game *Game
	//DeckName is the name of the deck in the game's ComponentChest that this
	//Stack is tied to.
	DeckName string
	//The indexes from the given deck that this stack contains, in order.
	Indexes []int
}

//Len returns the number of items in the stack.
func (s *Stack) Len() int {
	return len(s.Indexes)
}

//ComponentAt fetches the component object representing the n-th object in
//this stack.
func (s *Stack) ComponentAt(index int) *Component {

	if index >= s.Len() || index < 0 {
		return nil
	}

	deck := s.Game.Chest.Deck(s.DeckName)

	if deck == nil {
		return nil
	}

	//We don't need to check that s.Indexes[index] is valid because it was
	//checked when it was set, and Decks are immutable.
	return deck.Components()[s.Indexes[index]]
}

//InsertFront puts the component at index 0 in this stack, moving all other
//items down by one. The Component you insert should not currently be a member
//of any other stacks, to maintain the deck invariant.
func (s *Stack) InsertFront(c *Component) {

	//Based on how Decks and Chests are constructed, we know the components in
	//the chest hae the right gamename, so no need to check.

	if c.Address.Deck != s.DeckName {
		//We can only add items that are in our deck.

		//TODO: communicate an error
		return
	}

	s.Indexes = append([]int{c.Address.Index}, s.Indexes...)
}

/*

//InsertBack puts the component at the last index in this stack. The
//Component you insert should not currently be a member of any other stacks,
//to maintain the deck invariant.
func (s *Stack) InsertBack(c Component) {

}

//RemoveFront removes the component from the first slot in this stack,
//shifting all later components down by 1. You should then insert the
//component in another stack to maintain the deck invariant.
func (s *Stack) RemoveFront() Component {

}

//RemoveBack removes the component from the last slot in this stack. You
//should then insert the component in another stack to maintain the deck
//invariant.
func (s *Stack) RemoveBack() Component {

}

*/
<|endoftext|>


<commit_before>// Copyright 2013, David Howden
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package raspicam

import (
	"fmt"
	"strings"
)

const raspiStillCommand = "raspistill"
const raspiStillYUVCommand = "raspiyuv"

// Encoding represents an enumeration of the supported encoding types
type Encoding uint

const (
	EncodingJPEG Encoding = iota
	EncodingBMP
	EncodingGIF
	EncodingPNG
)

var encodings = [...]string{
	"jpg",
	"bmp",
	"gif",
	"png",
}

// String returns the parameter string for the given encoding
func (s Encoding) String() string {
	return encodings[s]
}

// BaseStill represents the common elements between a Still and StillYUV
// as described in their equivalents found in RaspiStill.c and RaspiStillYUV.c
// respectively.
type BaseStill struct {
	Timeout       int // Delay (milliseconds) before image is taken
	Width, Height int // Image dimensions
	Timelapse     int // The number of pictures to take in the given timeout interval
	Camera        Camera
	Preview       Preview
}

// The default BaseStill setup
var defaultBaseStill = BaseStill{Timeout: 5000, Width: 2592, Height: 1944,
	Camera: defaultCamera, Preview: defaultPreview}

// String returns the parameter string for the given BaseStill
func (s *BaseStill) String() string {
	output := "--output -"
	if s.Timeout != defaultStill.Timeout {
		output += fmt.Sprintf(" --timeout %v", s.Timeout)
	}
	if s.Width != defaultStill.Width {
		output += fmt.Sprintf(" --width %v", s.Width)
	}
	if s.Height != defaultStill.Height {
		output += fmt.Sprintf(" --height %v", s.Height)
	}
	output += " " + s.Camera.String()
	output += " " + s.Preview.String()
	return strings.TrimSpace(output)
}

// The default Still setup
var defaultStill = Still{BaseStill: defaultBaseStill, Quality: 85,
	Encoding: EncodingJPEG}

// Still represents the configuration necessary to call raspistill
type Still struct {
	BaseStill
	Quality  int  // Quality (for lossy encoding)
	Raw      bool // Want a raw image?
	Encoding Encoding
}

// String returns the parameter string for the given Still struct
func (s *Still) String() string {
	output := s.BaseStill.String()
	if s.Quality != defaultStill.Quality {
		output += fmt.Sprintf(" --quality %v", s.Quality)
	}
	if s.Raw {
		output += " --raw"
	}
	if s.Encoding != defaultStill.Encoding {
		output += fmt.Sprintf(" --encoding %v", s.Encoding)
	}
	return strings.TrimSpace(output)
}

// cmd returns the raspicam command associated with this struct
func (s *Still) cmd() string {
	return raspiStillCommand
}

// params returns the parameters to be used in the command execution
func (s *Still) params() []string {
	return strings.Fields(s.String())
}

// StillYUV represents the configuration necessary to call raspistillYUV
type StillYUV struct {
	BaseStill
	UseRGB bool // Output RGB data rather than YUV
}

// The default StillYUV setup
var defaultStillYUV = StillYUV{BaseStill: defaultBaseStill}

// String returns the parameter string for the given StillYUV struct
func (s *StillYUV) String() string {
	output := s.BaseStill.String()
	if s.UseRGB {
		output += " --rgb"
	}
	return strings.TrimSpace(output)
}

// cmd returns the raspicam command associated with this struct
func (s *StillYUV) cmd() string {
	return raspiStillYUVCommand
}

// params returns the parameters to be used in the command execution
func (s *StillYUV) params() []string {
	return strings.Fields(s.String())
}

// NewStill returns a *Still with the default values set by the raspistill command
// (see userland/linux/apps/raspicam/RaspiStill.c)
func NewStill() *Still {
	newStill := defaultStill
	return &newStill
}

// NewStill returns a *StillYUV with the default values set by the raspistillYUV command
// (see userland/linux/apps/raspicam/RaspiStillYUV.c)
func NewStillYUV() *StillYUV {
	newStillYUV := defaultStillYUV
	return &newStillYUV
}
<commit_msg>Relocated NewStill to be closer to its friends<commit_after>// Copyright 2013, David Howden
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package raspicam

import (
	"fmt"
	"strings"
)

const raspiStillCommand = "raspistill"
const raspiStillYUVCommand = "raspiyuv"

// Encoding represents an enumeration of the supported encoding types
type Encoding uint

const (
	EncodingJPEG Encoding = iota
	EncodingBMP
	EncodingGIF
	EncodingPNG
)

var encodings = [...]string{
	"jpg",
	"bmp",
	"gif",
	"png",
}

// String returns the parameter string for the given encoding
func (s Encoding) String() string {
	return encodings[s]
}

// BaseStill represents the common elements between a Still and StillYUV
// as described in their equivalents found in RaspiStill.c and RaspiStillYUV.c
// respectively.
type BaseStill struct {
	Timeout       int // Delay (milliseconds) before image is taken
	Width, Height int // Image dimensions
	Timelapse     int // The number of pictures to take in the given timeout interval
	Camera        Camera
	Preview       Preview
}

// The default BaseStill setup
var defaultBaseStill = BaseStill{Timeout: 5000, Width: 2592, Height: 1944,
	Camera: defaultCamera, Preview: defaultPreview}

// String returns the parameter string for the given BaseStill
func (s *BaseStill) String() string {
	output := "--output -"
	if s.Timeout != defaultStill.Timeout {
		output += fmt.Sprintf(" --timeout %v", s.Timeout)
	}
	if s.Width != defaultStill.Width {
		output += fmt.Sprintf(" --width %v", s.Width)
	}
	if s.Height != defaultStill.Height {
		output += fmt.Sprintf(" --height %v", s.Height)
	}
	output += " " + s.Camera.String()
	output += " " + s.Preview.String()
	return strings.TrimSpace(output)
}

// The default Still setup
var defaultStill = Still{BaseStill: defaultBaseStill, Quality: 85,
	Encoding: EncodingJPEG}

// Still represents the configuration necessary to call raspistill
type Still struct {
	BaseStill
	Quality  int  // Quality (for lossy encoding)
	Raw      bool // Want a raw image?
	Encoding Encoding
}

// String returns the parameter string for the given Still struct
func (s *Still) String() string {
	output := s.BaseStill.String()
	if s.Quality != defaultStill.Quality {
		output += fmt.Sprintf(" --quality %v", s.Quality)
	}
	if s.Raw {
		output += " --raw"
	}
	if s.Encoding != defaultStill.Encoding {
		output += fmt.Sprintf(" --encoding %v", s.Encoding)
	}
	return strings.TrimSpace(output)
}

// cmd returns the raspicam command associated with this struct
func (s *Still) cmd() string {
	return raspiStillCommand
}

// params returns the parameters to be used in the command execution
func (s *Still) params() []string {
	return strings.Fields(s.String())
}

// NewStill returns a *Still with the default values set by the raspistill command
// (see userland/linux/apps/raspicam/RaspiStill.c)
func NewStill() *Still {
	newStill := defaultStill
	return &newStill
}

// StillYUV represents the configuration necessary to call raspistillYUV
type StillYUV struct {
	BaseStill
	UseRGB bool // Output RGB data rather than YUV
}

// The default StillYUV setup
var defaultStillYUV = StillYUV{BaseStill: defaultBaseStill}

// String returns the parameter string for the given StillYUV struct
func (s *StillYUV) String() string {
	output := s.BaseStill.String()
	if s.UseRGB {
		output += " --rgb"
	}
	return strings.TrimSpace(output)
}

// cmd returns the raspicam command associated with this struct
func (s *StillYUV) cmd() string {
	return raspiStillYUVCommand
}

// params returns the parameters to be used in the command execution
func (s *StillYUV) params() []string {
	return strings.Fields(s.String())
}

// NewStill returns a *StillYUV with the default values set by the raspistillYUV command
// (see userland/linux/apps/raspicam/RaspiStillYUV.c)
func NewStillYUV() *StillYUV {
	newStillYUV := defaultStillYUV
	return &newStillYUV
}
<|endoftext|>


<commit_before>// Package store is a dead simple configuration manager for Go applications.
package store

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"reflect"
	"runtime"

	"github.com/BurntSushi/toml"
	"github.com/go-yaml/yaml"
)

// MarshalFunc is any marshaler.
type MarshalFunc func(v interface{}) ([]byte, error)

// UnmarshalFunc is any unmarshaler.
type UnmarshalFunc func(data []byte, v interface{}) error

var (
	applicationName = ""
	formats         = map[string]format{}
)

type format struct {
	m  MarshalFunc
	um UnmarshalFunc
}

func init() {
	formats["json"] = format{m: json.Marshal, um: json.Unmarshal}
	formats["yaml"] = format{m: yaml.Marshal, um: yaml.Unmarshal}
	formats["yml"] = format{m: yaml.Marshal, um: yaml.Unmarshal}

	formats["toml"] = format{
		m: func(v interface{}) ([]byte, error) {
			b := bytes.Buffer{}
			err := toml.NewEncoder(&b).Encode(v)
			return b.Bytes(), err
		},
		um: toml.Unmarshal,
	}
}

// Init sets up a unique application name that will be used for name of the
// configuration directory on the file system. By default, Store puts all the
// config data to to $XDG_CONFIG_HOME or $HOME on Linux systems
// and to %APPDATA% on Windows.
//
// Beware: Store will panic on any sensitive calls unless you run Init inb4.
func Init(application string) {
	applicationName = application
}

// Register is the way you register configuration formats, by mapping some
// file name extension to corresponding marshal and unmarshal functions.
// Once registered, the format given would be compatible with Load and Save.
func Register(extension string, m MarshalFunc, um UnmarshalFunc) {
	formats[extension] = format{m, um}
}

// Load reads a configuration from `path` and puts it into `v` pointer. Store
// supports either JSON, TOML or YAML and will deduce the file format out of
// the filename (.json/.toml/.yaml). For other formats of custom extensions
// please you LoadWith.
//
// Path is a full filename, including the file extension, e.g. "foobar.json".
// If `path` doesn't exist, Load will create one and emptify `v` pointer by
// replacing it with a newly created object, derived from type of `v`.
//
// Load panics on unknown configuration formats.
func Load(path string, v interface{}) error {
	if applicationName == "" {
		panic("store: application name not defined")
	}

	if format, ok := formats[extension(path)]; ok {
		return LoadWith(path, v, format.um)
	}

	panic("store: unknown configuration format")
}

// Save puts a configuration from `v` pointer into a file `path`. Store
// supports either JSON, TOML or YAML and will deduce the file format out of
// the filename (.json/.toml/.yaml). For other formats of custom extensions
// please you LoadWith.
//
// Path is a full filename, including the file extension, e.g. "foobar.json".
//
// Save panics on unknown configuration formats.
func Save(path string, v interface{}) error {
	if applicationName == "" {
		panic("store: application name not defined")
	}

	if format, ok := formats[extension(path)]; ok {
		return SaveWith(path, v, format.m)
	}

	panic("store: unknown configuration format")
}

// LoadWith loads the configuration using any unmarshaler at all.
func LoadWith(path string, v interface{}, um UnmarshalFunc) error {
	if applicationName == "" {
		panic("store: application name not defined")
	}

	globalPath := buildPlatformPath(path)

	data, err := ioutil.ReadFile(globalPath)

	if err != nil {
		// There is a chance that file we are looking for
		// just doesn't exist. In this case we are supposed
		// to create an empty configuration file, based on v.
		empty := reflect.New(reflect.TypeOf(v))
		if innerErr := Save(path, &empty); innerErr != nil {
			// Smth going on with the file system... returning error.
			return err
		}

		v = empty

		return nil
	}

	if err := um(data, v); err != nil {
		return fmt.Errorf("store: failed to unmarshal %s: %v", path, err)
	}

	return nil
}

// SaveWith saves the configuration using any marshaler at all.
func SaveWith(path string, v interface{}, m MarshalFunc) error {
	if applicationName == "" {
		panic("store: application name not defined")
	}

	var b bytes.Buffer

	if data, err := m(v); err == nil {
		b.Write(data)
	} else {
		return fmt.Errorf("store: failed to marshal %s: %v", path, err)
	}

	b.WriteRune('\n')

	globalPath := buildPlatformPath(path)
	if err := os.MkdirAll(filepath.Dir(globalPath), os.ModePerm); err != nil {
		return err
	}

	if err := ioutil.WriteFile(globalPath, b.Bytes(), os.ModePerm); err != nil {
		return err
	}

	return nil
}

func extension(path string) string {
	for i := len(path) - 1; i >= 0; i-- {
		if path[i] == '.' {
			return path[i+1:]
		}
	}

	return ""
}

// buildPlatformPath builds a platform-dependent path for relative path given.
func buildPlatformPath(path string) string {
	if runtime.GOOS == "windows" {
		return fmt.Sprintf("%s\\%s\\%s", os.Getenv("APPDATA"),
			applicationName,
			path)
	}

	var unixConfigDir string
	if xdg := os.Getenv("XDG_CONFIG_HOME"); xdg != "" {
		unixConfigDir = xdg
	} else {
		unixConfigDir = os.Getenv("HOME") + "/.config"
	}

	return fmt.Sprintf("%s/%s/%s", unixConfigDir,
		applicationName,
		path)
}

// SetApplicationName is DEPRECATED (use Init instead).
func SetApplicationName(handle string) {
	applicationName = handle
}
<commit_msg>changed the yaml dependency<commit_after>// Package store is a dead simple configuration manager for Go applications.
package store

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"reflect"
	"runtime"

	"github.com/BurntSushi/toml"
	"gopkg.in/yaml.v2"
)

// MarshalFunc is any marshaler.
type MarshalFunc func(v interface{}) ([]byte, error)

// UnmarshalFunc is any unmarshaler.
type UnmarshalFunc func(data []byte, v interface{}) error

var (
	applicationName = ""
	formats         = map[string]format{}
)

type format struct {
	m  MarshalFunc
	um UnmarshalFunc
}

func init() {
	formats["json"] = format{m: json.Marshal, um: json.Unmarshal}
	formats["yaml"] = format{m: yaml.Marshal, um: yaml.Unmarshal}
	formats["yml"] = format{m: yaml.Marshal, um: yaml.Unmarshal}

	formats["toml"] = format{
		m: func(v interface{}) ([]byte, error) {
			b := bytes.Buffer{}
			err := toml.NewEncoder(&b).Encode(v)
			return b.Bytes(), err
		},
		um: toml.Unmarshal,
	}
}

// Init sets up a unique application name that will be used for name of the
// configuration directory on the file system. By default, Store puts all the
// config data to to $XDG_CONFIG_HOME or $HOME on Linux systems
// and to %APPDATA% on Windows.
//
// Beware: Store will panic on any sensitive calls unless you run Init inb4.
func Init(application string) {
	applicationName = application
}

// Register is the way you register configuration formats, by mapping some
// file name extension to corresponding marshal and unmarshal functions.
// Once registered, the format given would be compatible with Load and Save.
func Register(extension string, m MarshalFunc, um UnmarshalFunc) {
	formats[extension] = format{m, um}
}

// Load reads a configuration from `path` and puts it into `v` pointer. Store
// supports either JSON, TOML or YAML and will deduce the file format out of
// the filename (.json/.toml/.yaml). For other formats of custom extensions
// please you LoadWith.
//
// Path is a full filename, including the file extension, e.g. "foobar.json".
// If `path` doesn't exist, Load will create one and emptify `v` pointer by
// replacing it with a newly created object, derived from type of `v`.
//
// Load panics on unknown configuration formats.
func Load(path string, v interface{}) error {
	if applicationName == "" {
		panic("store: application name not defined")
	}

	if format, ok := formats[extension(path)]; ok {
		return LoadWith(path, v, format.um)
	}

	panic("store: unknown configuration format")
}

// Save puts a configuration from `v` pointer into a file `path`. Store
// supports either JSON, TOML or YAML and will deduce the file format out of
// the filename (.json/.toml/.yaml). For other formats of custom extensions
// please you LoadWith.
//
// Path is a full filename, including the file extension, e.g. "foobar.json".
//
// Save panics on unknown configuration formats.
func Save(path string, v interface{}) error {
	if applicationName == "" {
		panic("store: application name not defined")
	}

	if format, ok := formats[extension(path)]; ok {
		return SaveWith(path, v, format.m)
	}

	panic("store: unknown configuration format")
}

// LoadWith loads the configuration using any unmarshaler at all.
func LoadWith(path string, v interface{}, um UnmarshalFunc) error {
	if applicationName == "" {
		panic("store: application name not defined")
	}

	globalPath := buildPlatformPath(path)

	data, err := ioutil.ReadFile(globalPath)

	if err != nil {
		// There is a chance that file we are looking for
		// just doesn't exist. In this case we are supposed
		// to create an empty configuration file, based on v.
		empty := reflect.New(reflect.TypeOf(v))
		if innerErr := Save(path, &empty); innerErr != nil {
			// Smth going on with the file system... returning error.
			return err
		}

		v = empty

		return nil
	}

	if err := um(data, v); err != nil {
		return fmt.Errorf("store: failed to unmarshal %s: %v", path, err)
	}

	return nil
}

// SaveWith saves the configuration using any marshaler at all.
func SaveWith(path string, v interface{}, m MarshalFunc) error {
	if applicationName == "" {
		panic("store: application name not defined")
	}

	var b bytes.Buffer

	if data, err := m(v); err == nil {
		b.Write(data)
	} else {
		return fmt.Errorf("store: failed to marshal %s: %v", path, err)
	}

	b.WriteRune('\n')

	globalPath := buildPlatformPath(path)
	if err := os.MkdirAll(filepath.Dir(globalPath), os.ModePerm); err != nil {
		return err
	}

	if err := ioutil.WriteFile(globalPath, b.Bytes(), os.ModePerm); err != nil {
		return err
	}

	return nil
}

func extension(path string) string {
	for i := len(path) - 1; i >= 0; i-- {
		if path[i] == '.' {
			return path[i+1:]
		}
	}

	return ""
}

// buildPlatformPath builds a platform-dependent path for relative path given.
func buildPlatformPath(path string) string {
	if runtime.GOOS == "windows" {
		return fmt.Sprintf("%s\\%s\\%s", os.Getenv("APPDATA"),
			applicationName,
			path)
	}

	var unixConfigDir string
	if xdg := os.Getenv("XDG_CONFIG_HOME"); xdg != "" {
		unixConfigDir = xdg
	} else {
		unixConfigDir = os.Getenv("HOME") + "/.config"
	}

	return fmt.Sprintf("%s/%s/%s", unixConfigDir,
		applicationName,
		path)
}

// SetApplicationName is DEPRECATED (use Init instead).
func SetApplicationName(handle string) {
	applicationName = handle
}
<|endoftext|>


<commit_before>package libnetwork

import (
	"encoding/json"
	"fmt"

	log "github.com/Sirupsen/logrus"
	"github.com/docker/libkv/store"
	"github.com/docker/libnetwork/datastore"
	"github.com/docker/libnetwork/types"
)

func (c *controller) validateDatastoreConfig() bool {
	if c.cfg == nil || c.cfg.Datastore.Client.Provider == "" || c.cfg.Datastore.Client.Address == "" {
		return false
	}
	return true
}

func (c *controller) initDataStore() error {
	c.Lock()
	cfg := c.cfg
	c.Unlock()
	if !c.validateDatastoreConfig() {
		return fmt.Errorf("datastore initialization requires a valid configuration")
	}

	store, err := datastore.NewDataStore(&cfg.Datastore)
	if err != nil {
		return err
	}
	c.Lock()
	c.store = store
	c.Unlock()

	nws, err := c.getNetworksFromStore()
	if err == nil {
		c.processNetworkUpdate(nws, nil)
	} else if err != datastore.ErrKeyNotFound {
		log.Warnf("failed to read networks from datastore during init : %v", err)
	}
	return c.watchNetworks()
}

func (c *controller) getNetworksFromStore() ([]*store.KVPair, error) {
	c.Lock()
	cs := c.store
	c.Unlock()
	return cs.KVStore().List(datastore.Key(datastore.NetworkKeyPrefix))
}

func (c *controller) newNetworkFromStore(n *network) error {
	n.Lock()
	n.ctrlr = c
	n.endpoints = endpointTable{}
	n.Unlock()

	return c.addNetwork(n)
}

func (c *controller) updateNetworkToStore(n *network) error {
	global, err := n.isGlobalScoped()
	if err != nil || !global {
		return err
	}
	c.Lock()
	cs := c.store
	c.Unlock()
	if cs == nil {
		log.Debugf("datastore not initialized. Network %s is not added to the store", n.Name())
		return nil
	}

	return cs.PutObjectAtomic(n)
}

func (c *controller) deleteNetworkFromStore(n *network) error {
	global, err := n.isGlobalScoped()
	if err != nil || !global {
		return err
	}
	c.Lock()
	cs := c.store
	c.Unlock()
	if cs == nil {
		log.Debugf("datastore not initialized. Network %s is not deleted from datastore", n.Name())
		return nil
	}

	if err := cs.DeleteObjectAtomic(n); err != nil {
		return err
	}

	return nil
}

func (c *controller) getNetworkFromStore(nid types.UUID) (*network, error) {
	n := network{id: nid}
	if err := c.store.GetObject(datastore.Key(n.Key()...), &n); err != nil {
		return nil, err
	}
	return &n, nil
}

func (c *controller) newEndpointFromStore(key string, ep *endpoint) error {
	ep.Lock()
	n := ep.network
	id := ep.id
	ep.Unlock()

	_, err := n.EndpointByID(string(id))
	if err != nil {
		if _, ok := err.(ErrNoSuchEndpoint); ok {
			return n.addEndpoint(ep)
		}
	}
	return err
}

func (c *controller) updateEndpointToStore(ep *endpoint) error {
	ep.Lock()
	n := ep.network
	name := ep.name
	ep.Unlock()
	global, err := n.isGlobalScoped()
	if err != nil || !global {
		return err
	}
	c.Lock()
	cs := c.store
	c.Unlock()
	if cs == nil {
		log.Debugf("datastore not initialized. endpoint %s is not added to the store", name)
		return nil
	}

	return cs.PutObjectAtomic(ep)
}

func (c *controller) getEndpointFromStore(eid types.UUID) (*endpoint, error) {
	ep := endpoint{id: eid}
	if err := c.store.GetObject(datastore.Key(ep.Key()...), &ep); err != nil {
		return nil, err
	}
	return &ep, nil
}

func (c *controller) deleteEndpointFromStore(ep *endpoint) error {
	ep.Lock()
	n := ep.network
	ep.Unlock()
	global, err := n.isGlobalScoped()
	if err != nil || !global {
		return err
	}

	c.Lock()
	cs := c.store
	c.Unlock()
	if cs == nil {
		log.Debugf("datastore not initialized. endpoint %s is not deleted from datastore", ep.Name())
		return nil
	}

	if err := cs.DeleteObjectAtomic(ep); err != nil {
		return err
	}

	return nil
}

func (c *controller) watchNetworks() error {
	if !c.validateDatastoreConfig() {
		return nil
	}

	c.Lock()
	cs := c.store
	c.Unlock()

	nwPairs, err := cs.KVStore().WatchTree(datastore.Key(datastore.NetworkKeyPrefix), nil)
	if err != nil {
		return err
	}
	go func() {
		for {
			select {
			case nws := <-nwPairs:
				c.Lock()
				tmpview := networkTable{}
				lview := c.networks
				c.Unlock()
				for k, v := range lview {
					tmpview[k] = v
				}
				c.processNetworkUpdate(nws, &tmpview)
				// Delete processing
				for k := range tmpview {
					c.Lock()
					existing, ok := c.networks[k]
					c.Unlock()
					if !ok {
						continue
					}
					tmp := network{}
					if err := c.store.GetObject(datastore.Key(existing.Key()...), &tmp); err != datastore.ErrKeyNotFound {
						continue
					}
					if err := existing.deleteNetwork(); err != nil {
						log.Debugf("Delete failed %s: %s", existing.name, err)
					}
				}
			}
		}
	}()
	return nil
}

func (n *network) watchEndpoints() error {
	if !n.ctrlr.validateDatastoreConfig() {
		return nil
	}

	n.Lock()
	cs := n.ctrlr.store
	tmp := endpoint{network: n}
	n.stopWatchCh = make(chan struct{})
	stopCh := n.stopWatchCh
	n.Unlock()

	epPairs, err := cs.KVStore().WatchTree(datastore.Key(tmp.KeyPrefix()...), stopCh)
	if err != nil {
		return err
	}
	go func() {
		for {
			select {
			case <-stopCh:
				return
			case eps := <-epPairs:
				n.Lock()
				tmpview := endpointTable{}
				lview := n.endpoints
				n.Unlock()
				for k, v := range lview {
					tmpview[k] = v
				}
				for _, epe := range eps {
					var ep endpoint
					err := json.Unmarshal(epe.Value, &ep)
					if err != nil {
						log.Error(err)
						continue
					}
					delete(tmpview, ep.id)
					ep.dbIndex = epe.LastIndex
					ep.network = n
					if n.ctrlr.processEndpointUpdate(&ep) {
						err = n.ctrlr.newEndpointFromStore(epe.Key, &ep)
						if err != nil {
							log.Error(err)
						}
					}
				}
				// Delete processing
				for k := range tmpview {
					n.Lock()
					existing, ok := n.endpoints[k]
					n.Unlock()
					if !ok {
						continue
					}
					tmp := endpoint{}
					if err := cs.GetObject(datastore.Key(existing.Key()...), &tmp); err != datastore.ErrKeyNotFound {
						continue
					}
					if err := existing.deleteEndpoint(); err != nil {
						log.Debugf("Delete failed %s: %s", existing.name, err)
					}
				}
			}
		}
	}()
	return nil
}

func (n *network) stopWatch() {
	n.Lock()
	if n.stopWatchCh != nil {
		close(n.stopWatchCh)
		n.stopWatchCh = nil
	}
	n.Unlock()
}

func (c *controller) processNetworkUpdate(nws []*store.KVPair, prune *networkTable) {
	for _, kve := range nws {
		var n network
		err := json.Unmarshal(kve.Value, &n)
		if err != nil {
			log.Error(err)
			continue
		}
		if prune != nil {
			delete(*prune, n.id)
		}
		n.dbIndex = kve.LastIndex
		c.Lock()
		existing, ok := c.networks[n.id]
		c.Unlock()
		if ok {
			existing.Lock()
			// Skip existing network update
			if existing.dbIndex != n.dbIndex {
				existing.dbIndex = n.dbIndex
				existing.endpointCnt = n.endpointCnt
			}
			existing.Unlock()
			continue
		}

		if err = c.newNetworkFromStore(&n); err != nil {
			log.Error(err)
		}
	}
}

func (c *controller) processEndpointUpdate(ep *endpoint) bool {
	nw := ep.network
	if nw == nil {
		return true
	}
	nw.Lock()
	id := nw.id
	nw.Unlock()

	c.Lock()
	n, ok := c.networks[id]
	c.Unlock()
	if !ok {
		return true
	}
	existing, _ := n.EndpointByID(string(ep.id))
	if existing == nil {
		return true
	}

	ee := existing.(*endpoint)
	ee.Lock()
	if ee.dbIndex != ep.dbIndex {
		ee.dbIndex = ep.dbIndex
		if ee.container != nil && ep.container != nil {
			// we care only about the container id
			ee.container.id = ep.container.id
		} else {
			// we still care only about the container id, but this is a short-cut to communicate join or leave operation
			ee.container = ep.container
		}
	}
	ee.Unlock()

	return false
}
<commit_msg>Ignoring locally scoped endpoints/networks from distributed delete<commit_after>package libnetwork

import (
	"encoding/json"
	"fmt"

	log "github.com/Sirupsen/logrus"
	"github.com/docker/libkv/store"
	"github.com/docker/libnetwork/datastore"
	"github.com/docker/libnetwork/types"
)

func (c *controller) validateDatastoreConfig() bool {
	if c.cfg == nil || c.cfg.Datastore.Client.Provider == "" || c.cfg.Datastore.Client.Address == "" {
		return false
	}
	return true
}

func (c *controller) initDataStore() error {
	c.Lock()
	cfg := c.cfg
	c.Unlock()
	if !c.validateDatastoreConfig() {
		return fmt.Errorf("datastore initialization requires a valid configuration")
	}

	store, err := datastore.NewDataStore(&cfg.Datastore)
	if err != nil {
		return err
	}
	c.Lock()
	c.store = store
	c.Unlock()

	nws, err := c.getNetworksFromStore()
	if err == nil {
		c.processNetworkUpdate(nws, nil)
	} else if err != datastore.ErrKeyNotFound {
		log.Warnf("failed to read networks from datastore during init : %v", err)
	}
	return c.watchNetworks()
}

func (c *controller) getNetworksFromStore() ([]*store.KVPair, error) {
	c.Lock()
	cs := c.store
	c.Unlock()
	return cs.KVStore().List(datastore.Key(datastore.NetworkKeyPrefix))
}

func (c *controller) newNetworkFromStore(n *network) error {
	n.Lock()
	n.ctrlr = c
	n.endpoints = endpointTable{}
	n.Unlock()

	return c.addNetwork(n)
}

func (c *controller) updateNetworkToStore(n *network) error {
	global, err := n.isGlobalScoped()
	if err != nil || !global {
		return err
	}
	c.Lock()
	cs := c.store
	c.Unlock()
	if cs == nil {
		log.Debugf("datastore not initialized. Network %s is not added to the store", n.Name())
		return nil
	}

	return cs.PutObjectAtomic(n)
}

func (c *controller) deleteNetworkFromStore(n *network) error {
	global, err := n.isGlobalScoped()
	if err != nil || !global {
		return err
	}
	c.Lock()
	cs := c.store
	c.Unlock()
	if cs == nil {
		log.Debugf("datastore not initialized. Network %s is not deleted from datastore", n.Name())
		return nil
	}

	if err := cs.DeleteObjectAtomic(n); err != nil {
		return err
	}

	return nil
}

func (c *controller) getNetworkFromStore(nid types.UUID) (*network, error) {
	n := network{id: nid}
	if err := c.store.GetObject(datastore.Key(n.Key()...), &n); err != nil {
		return nil, err
	}
	return &n, nil
}

func (c *controller) newEndpointFromStore(key string, ep *endpoint) error {
	ep.Lock()
	n := ep.network
	id := ep.id
	ep.Unlock()

	_, err := n.EndpointByID(string(id))
	if err != nil {
		if _, ok := err.(ErrNoSuchEndpoint); ok {
			return n.addEndpoint(ep)
		}
	}
	return err
}

func (c *controller) updateEndpointToStore(ep *endpoint) error {
	ep.Lock()
	n := ep.network
	name := ep.name
	ep.Unlock()
	global, err := n.isGlobalScoped()
	if err != nil || !global {
		return err
	}
	c.Lock()
	cs := c.store
	c.Unlock()
	if cs == nil {
		log.Debugf("datastore not initialized. endpoint %s is not added to the store", name)
		return nil
	}

	return cs.PutObjectAtomic(ep)
}

func (c *controller) getEndpointFromStore(eid types.UUID) (*endpoint, error) {
	ep := endpoint{id: eid}
	if err := c.store.GetObject(datastore.Key(ep.Key()...), &ep); err != nil {
		return nil, err
	}
	return &ep, nil
}

func (c *controller) deleteEndpointFromStore(ep *endpoint) error {
	ep.Lock()
	n := ep.network
	ep.Unlock()
	global, err := n.isGlobalScoped()
	if err != nil || !global {
		return err
	}

	c.Lock()
	cs := c.store
	c.Unlock()
	if cs == nil {
		log.Debugf("datastore not initialized. endpoint %s is not deleted from datastore", ep.Name())
		return nil
	}

	if err := cs.DeleteObjectAtomic(ep); err != nil {
		return err
	}

	return nil
}

func (c *controller) watchNetworks() error {
	if !c.validateDatastoreConfig() {
		return nil
	}

	c.Lock()
	cs := c.store
	c.Unlock()

	nwPairs, err := cs.KVStore().WatchTree(datastore.Key(datastore.NetworkKeyPrefix), nil)
	if err != nil {
		return err
	}
	go func() {
		for {
			select {
			case nws := <-nwPairs:
				c.Lock()
				tmpview := networkTable{}
				lview := c.networks
				c.Unlock()
				for k, v := range lview {
					global, _ := v.isGlobalScoped()
					if global {
						tmpview[k] = v
					}
				}
				c.processNetworkUpdate(nws, &tmpview)
				// Delete processing
				for k := range tmpview {
					c.Lock()
					existing, ok := c.networks[k]
					c.Unlock()
					if !ok {
						continue
					}
					tmp := network{}
					if err := c.store.GetObject(datastore.Key(existing.Key()...), &tmp); err != datastore.ErrKeyNotFound {
						continue
					}
					if err := existing.deleteNetwork(); err != nil {
						log.Debugf("Delete failed %s: %s", existing.name, err)
					}
				}
			}
		}
	}()
	return nil
}

func (n *network) watchEndpoints() error {
	if !n.ctrlr.validateDatastoreConfig() {
		return nil
	}

	n.Lock()
	cs := n.ctrlr.store
	tmp := endpoint{network: n}
	n.stopWatchCh = make(chan struct{})
	stopCh := n.stopWatchCh
	n.Unlock()

	epPairs, err := cs.KVStore().WatchTree(datastore.Key(tmp.KeyPrefix()...), stopCh)
	if err != nil {
		return err
	}
	go func() {
		for {
			select {
			case <-stopCh:
				return
			case eps := <-epPairs:
				n.Lock()
				tmpview := endpointTable{}
				lview := n.endpoints
				n.Unlock()
				for k, v := range lview {
					global, _ := v.network.isGlobalScoped()
					if global {
						tmpview[k] = v
					}
				}
				for _, epe := range eps {
					var ep endpoint
					err := json.Unmarshal(epe.Value, &ep)
					if err != nil {
						log.Error(err)
						continue
					}
					delete(tmpview, ep.id)
					ep.dbIndex = epe.LastIndex
					ep.network = n
					if n.ctrlr.processEndpointUpdate(&ep) {
						err = n.ctrlr.newEndpointFromStore(epe.Key, &ep)
						if err != nil {
							log.Error(err)
						}
					}
				}
				// Delete processing
				for k := range tmpview {
					n.Lock()
					existing, ok := n.endpoints[k]
					n.Unlock()
					if !ok {
						continue
					}
					tmp := endpoint{}
					if err := cs.GetObject(datastore.Key(existing.Key()...), &tmp); err != datastore.ErrKeyNotFound {
						continue
					}
					if err := existing.deleteEndpoint(); err != nil {
						log.Debugf("Delete failed %s: %s", existing.name, err)
					}
				}
			}
		}
	}()
	return nil
}

func (n *network) stopWatch() {
	n.Lock()
	if n.stopWatchCh != nil {
		close(n.stopWatchCh)
		n.stopWatchCh = nil
	}
	n.Unlock()
}

func (c *controller) processNetworkUpdate(nws []*store.KVPair, prune *networkTable) {
	for _, kve := range nws {
		var n network
		err := json.Unmarshal(kve.Value, &n)
		if err != nil {
			log.Error(err)
			continue
		}
		if prune != nil {
			delete(*prune, n.id)
		}
		n.dbIndex = kve.LastIndex
		c.Lock()
		existing, ok := c.networks[n.id]
		c.Unlock()
		if ok {
			existing.Lock()
			// Skip existing network update
			if existing.dbIndex != n.dbIndex {
				existing.dbIndex = n.dbIndex
				existing.endpointCnt = n.endpointCnt
			}
			existing.Unlock()
			continue
		}

		if err = c.newNetworkFromStore(&n); err != nil {
			log.Error(err)
		}
	}
}

func (c *controller) processEndpointUpdate(ep *endpoint) bool {
	nw := ep.network
	if nw == nil {
		return true
	}
	nw.Lock()
	id := nw.id
	nw.Unlock()

	c.Lock()
	n, ok := c.networks[id]
	c.Unlock()
	if !ok {
		return true
	}
	existing, _ := n.EndpointByID(string(ep.id))
	if existing == nil {
		return true
	}

	ee := existing.(*endpoint)
	ee.Lock()
	if ee.dbIndex != ep.dbIndex {
		ee.dbIndex = ep.dbIndex
		if ee.container != nil && ep.container != nil {
			// we care only about the container id
			ee.container.id = ep.container.id
		} else {
			// we still care only about the container id, but this is a short-cut to communicate join or leave operation
			ee.container = ep.container
		}
	}
	ee.Unlock()

	return false
}
<|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 arbitrator

import (
	"fmt"
	"testing"
	"time"

	apiv1 "github.com/kubernetes-incubator/kube-arbitrator/pkg/apis/v1"
	"github.com/kubernetes-incubator/kube-arbitrator/pkg/client"
	"github.com/kubernetes-incubator/kube-arbitrator/pkg/controller"
	"github.com/kubernetes-incubator/kube-arbitrator/pkg/policy/proportion"
	"github.com/kubernetes-incubator/kube-arbitrator/pkg/schedulercache"
	"github.com/kubernetes-incubator/kube-arbitrator/test/integration/framework"

	"k8s.io/api/core/v1"
	apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	clientset "k8s.io/client-go/kubernetes"
	restclient "k8s.io/client-go/rest"
)

// prepareNamespace prepare two namespaces "ns01" and "ns02"
func prepareNamespace(cs *clientset.Clientset) error {
	ns01 := &v1.Namespace{
		ObjectMeta: metav1.ObjectMeta{
			Name: "ns01",
		},
	}
	ns02 := &v1.Namespace{
		ObjectMeta: metav1.ObjectMeta{
			Name: "ns02",
		},
	}

	_, err := cs.CoreV1().Namespaces().Create(ns01)
	if err != nil {
		return fmt.Errorf("fail to create namespace ns01, %#v", err)
	}
	_, err = cs.CoreV1().Namespaces().Create(ns02)
	if err != nil {
		return fmt.Errorf("fail to create namespace ns02, %#v", err)
	}

	return nil
}

// prepareNode prepare one node "node01" which contain 15 cpus and 15Gi memory
func prepareNode(cs *clientset.Clientset) error {
	node := &v1.Node{
		ObjectMeta: metav1.ObjectMeta{
			Name:         "node01",
			GenerateName: "node01",
		},
		Spec: v1.NodeSpec{
			ExternalID: "foo",
		},
		Status: v1.NodeStatus{
			Capacity: v1.ResourceList{
				v1.ResourceCPU:    resource.MustParse("15"),
				v1.ResourceMemory: resource.MustParse("15Gi"),
			},
			Phase: v1.NodeRunning,
			Conditions: []v1.NodeCondition{
				{Type: v1.NodeReady, Status: v1.ConditionTrue},
			},
		},
	}

	_, err := cs.CoreV1().Nodes().Create(node)
	if err != nil {
		return fmt.Errorf("fail to create node node01, %#v", err)
	}

	return nil
}

// prepareResourceQuota prepare two resource quotas "rq01" and "rq02"
// "rq01" is under namespace "ns01", "rq02" is under namespace "ns02"
// "rq01" and "rq02" will not limit cpu and memory usage at first
func prepareResourceQuota(cs *clientset.Clientset) error {
	rq01 := &v1.ResourceQuota{
		ObjectMeta: metav1.ObjectMeta{
			Name:      "rq01",
			Namespace: "ns01",
		},
		Spec: v1.ResourceQuotaSpec{
			Hard: v1.ResourceList{
				v1.ResourcePods: resource.MustParse("1000"),
			},
		},
	}
	rq02 := &v1.ResourceQuota{
		ObjectMeta: metav1.ObjectMeta{
			Name:      "rq02",
			Namespace: "ns02",
		},
		Spec: v1.ResourceQuotaSpec{
			Hard: v1.ResourceList{
				v1.ResourcePods: resource.MustParse("1000"),
			},
		},
	}

	_, err := cs.CoreV1().ResourceQuotas(rq01.Namespace).Create(rq01)
	if err != nil {
		return fmt.Errorf("fail to create quota rq01, %#v", err)
	}
	_, err = cs.CoreV1().ResourceQuotas(rq02.Namespace).Create(rq02)
	if err != nil {
		return fmt.Errorf("fail to create quota rq02, %#v", err)
	}

	return nil
}

// prepareCRD prepare customer resource definition "ResourceQuotaAllocator"
// create two ResourceQuotaAllocator, "allocator01" and "allocator02"
// "allocator01" is under namespace "ns01" and has attribute "weight=1"
// "allocator02" is under namespace "ns02" and has attribute "weight=2"
func prepareCRD(config *restclient.Config) error {
	extensionscs, err := apiextensionsclient.NewForConfig(config)
	if err != nil {
		return fmt.Errorf("fail to create crd config, %#v", err)
	}

	_, err = client.CreateResourceQuotaAllocatorCRD(extensionscs)
	if err != nil && !apierrors.IsAlreadyExists(err) {
		return fmt.Errorf("fail to create crd, %#v", err)
	}

	crdClient, _, err := client.NewClient(config)
	if err != nil {
		return fmt.Errorf("fail to create crd client, %#v", err)
	}

	crd01 := &apiv1.Queue{
		ObjectMeta: metav1.ObjectMeta{
			Name:      "allocator01",
			Namespace: "ns01",
		},
		Spec: apiv1.QueueSpec{
			Weight: 1,
		},
	}
	crd02 := &apiv1.Queue{
		ObjectMeta: metav1.ObjectMeta{
			Name:      "allocator02",
			Namespace: "ns02",
		},
		Spec: apiv1.QueueSpec{
			Weight: 2,
		},
	}

	var result apiv1.Queue
	err = crdClient.Post().
		Resource(apiv1.QueuePlural).
		Namespace(crd01.Namespace).
		Body(crd01).
		Do().Into(&result)
	if err != nil {
		return fmt.Errorf("fail to create crd crd01, %#v", err)
	}
	err = crdClient.Post().
		Resource(apiv1.QueuePlural).
		Namespace(crd02.Namespace).
		Body(crd02).
		Do().Into(&result)
	if err != nil {
		return fmt.Errorf("fail to create crd crd02, %#v", err)
	}

	return nil
}

func TestArbitrator(t *testing.T) {
	config, tearDown := framework.StartTestServerOrDie(t)
	defer tearDown()

	cs := clientset.NewForConfigOrDie(config)
	defer cs.CoreV1().Nodes().DeleteCollection(nil, metav1.ListOptions{})

	err := prepareNamespace(cs)
	if err != nil {
		t.Fatalf("fail to prepare namespaces, %#v", err)
	}

	err = prepareNode(cs)
	if err != nil {
		t.Fatalf("fail to prepare node, %#v", err)
	}

	err = prepareResourceQuota(cs)
	if err != nil {
		t.Fatalf("fail to prepare resource quota, %#v", err)
	}

	err = prepareCRD(config)
	if err != nil {
		t.Fatalf("fail to prepare CRD, %#v", err)
	}

	neverStop := make(chan struct{})
	defer close(neverStop)
	cache := schedulercache.New(config)
	go cache.Run(neverStop)
	c := controller.NewResourceQuotaAllocatorController(config, cache, proportion.New())
	go c.Run()

	// sleep to wait scheduler finish
	time.Sleep(10 * time.Second)

	// verify scheduler result
	rq01, _ := cs.CoreV1().ResourceQuotas("ns01").Get("rq01", metav1.GetOptions{})
	cpu01 := rq01.Spec.Hard["limits.cpu"]
	if v, _ := (&cpu01).AsInt64(); v != int64(5) {
		t.Fatalf("after scheduler, cpu is not 5 for rq01, %#v", rq01)
	}
	rq02, _ := cs.CoreV1().ResourceQuotas("ns02").Get("rq02", metav1.GetOptions{})
	cpu02 := rq02.Spec.Hard["limits.cpu"]
	if v, _ := (&cpu02).AsInt64(); v != int64(10) {
		t.Fatalf("after scheduler, cpu is not 10 for rq02, %#v", rq02)
	}
}
<commit_msg>change resourcequotaallocator to queue for integration test case<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 arbitrator

import (
	"fmt"
	"testing"
	"time"

	apiv1 "github.com/kubernetes-incubator/kube-arbitrator/pkg/apis/v1"
	"github.com/kubernetes-incubator/kube-arbitrator/pkg/client"
	"github.com/kubernetes-incubator/kube-arbitrator/pkg/controller"
	"github.com/kubernetes-incubator/kube-arbitrator/pkg/policy/proportion"
	"github.com/kubernetes-incubator/kube-arbitrator/pkg/schedulercache"
	"github.com/kubernetes-incubator/kube-arbitrator/test/integration/framework"

	"k8s.io/api/core/v1"
	apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	clientset "k8s.io/client-go/kubernetes"
	restclient "k8s.io/client-go/rest"
)

// prepareNamespace prepare two namespaces "ns01" and "ns02"
func prepareNamespace(cs *clientset.Clientset) error {
	ns01 := &v1.Namespace{
		ObjectMeta: metav1.ObjectMeta{
			Name: "ns01",
		},
	}
	ns02 := &v1.Namespace{
		ObjectMeta: metav1.ObjectMeta{
			Name: "ns02",
		},
	}

	_, err := cs.CoreV1().Namespaces().Create(ns01)
	if err != nil {
		return fmt.Errorf("fail to create namespace ns01, %#v", err)
	}
	_, err = cs.CoreV1().Namespaces().Create(ns02)
	if err != nil {
		return fmt.Errorf("fail to create namespace ns02, %#v", err)
	}

	return nil
}

// prepareNode prepare one node "node01" which contain 15 cpus and 15Gi memory
func prepareNode(cs *clientset.Clientset) error {
	node := &v1.Node{
		ObjectMeta: metav1.ObjectMeta{
			Name:         "node01",
			GenerateName: "node01",
		},
		Spec: v1.NodeSpec{
			ExternalID: "foo",
		},
		Status: v1.NodeStatus{
			Capacity: v1.ResourceList{
				v1.ResourceCPU:    resource.MustParse("15"),
				v1.ResourceMemory: resource.MustParse("15Gi"),
			},
			Phase: v1.NodeRunning,
			Conditions: []v1.NodeCondition{
				{Type: v1.NodeReady, Status: v1.ConditionTrue},
			},
		},
	}

	_, err := cs.CoreV1().Nodes().Create(node)
	if err != nil {
		return fmt.Errorf("fail to create node node01, %#v", err)
	}

	return nil
}

// prepareResourceQuota prepare two resource quotas "rq01" and "rq02"
// "rq01" is under namespace "ns01", "rq02" is under namespace "ns02"
// "rq01" and "rq02" will not limit cpu and memory usage at first
func prepareResourceQuota(cs *clientset.Clientset) error {
	rq01 := &v1.ResourceQuota{
		ObjectMeta: metav1.ObjectMeta{
			Name:      "rq01",
			Namespace: "ns01",
		},
		Spec: v1.ResourceQuotaSpec{
			Hard: v1.ResourceList{
				v1.ResourcePods: resource.MustParse("1000"),
			},
		},
	}
	rq02 := &v1.ResourceQuota{
		ObjectMeta: metav1.ObjectMeta{
			Name:      "rq02",
			Namespace: "ns02",
		},
		Spec: v1.ResourceQuotaSpec{
			Hard: v1.ResourceList{
				v1.ResourcePods: resource.MustParse("1000"),
			},
		},
	}

	_, err := cs.CoreV1().ResourceQuotas(rq01.Namespace).Create(rq01)
	if err != nil {
		return fmt.Errorf("fail to create quota rq01, %#v", err)
	}
	_, err = cs.CoreV1().ResourceQuotas(rq02.Namespace).Create(rq02)
	if err != nil {
		return fmt.Errorf("fail to create quota rq02, %#v", err)
	}

	return nil
}

// prepareCRD prepare customer resource definition "ResourceQuotaAllocator"
// create two ResourceQuotaAllocator, "queue01" and "queue02"
// "queue01" is under namespace "ns01" and has attribute "weight=1"
// "queue02" is under namespace "ns02" and has attribute "weight=2"
func prepareCRD(config *restclient.Config) error {
	extensionscs, err := apiextensionsclient.NewForConfig(config)
	if err != nil {
		return fmt.Errorf("fail to create crd config, %#v", err)
	}

	_, err = client.CreateQueueCRD(extensionscs)
	if err != nil && !apierrors.IsAlreadyExists(err) {
		return fmt.Errorf("fail to create crd, %#v", err)
	}

	crdClient, _, err := client.NewClient(config)
	if err != nil {
		return fmt.Errorf("fail to create crd client, %#v", err)
	}

	crd01 := &apiv1.Queue{
		ObjectMeta: metav1.ObjectMeta{
			Name:      "queue01",
			Namespace: "ns01",
		},
		Spec: apiv1.QueueSpec{
			Weight: 1,
		},
	}
	crd02 := &apiv1.Queue{
		ObjectMeta: metav1.ObjectMeta{
			Name:      "queue02",
			Namespace: "ns02",
		},
		Spec: apiv1.QueueSpec{
			Weight: 2,
		},
	}

	var result apiv1.Queue
	err = crdClient.Post().
		Resource(apiv1.QueuePlural).
		Namespace(crd01.Namespace).
		Body(crd01).
		Do().Into(&result)
	if err != nil {
		return fmt.Errorf("fail to create crd crd01, %#v", err)
	}
	err = crdClient.Post().
		Resource(apiv1.QueuePlural).
		Namespace(crd02.Namespace).
		Body(crd02).
		Do().Into(&result)
	if err != nil {
		return fmt.Errorf("fail to create crd crd02, %#v", err)
	}

	return nil
}

func TestArbitrator(t *testing.T) {
	config, tearDown := framework.StartTestServerOrDie(t)
	defer tearDown()

	cs := clientset.NewForConfigOrDie(config)
	defer cs.CoreV1().Nodes().DeleteCollection(nil, metav1.ListOptions{})

	err := prepareNamespace(cs)
	if err != nil {
		t.Fatalf("fail to prepare namespaces, %#v", err)
	}

	err = prepareNode(cs)
	if err != nil {
		t.Fatalf("fail to prepare node, %#v", err)
	}

	err = prepareResourceQuota(cs)
	if err != nil {
		t.Fatalf("fail to prepare resource quota, %#v", err)
	}

	err = prepareCRD(config)
	if err != nil {
		t.Fatalf("fail to prepare CRD, %#v", err)
	}

	neverStop := make(chan struct{})
	defer close(neverStop)
	cache := schedulercache.New(config)
	go cache.Run(neverStop)
	c := controller.NewQueueController(config, cache, proportion.New())
	go c.Run()

	// sleep to wait scheduler finish
	time.Sleep(10 * time.Second)

	// verify scheduler result
	rq01, _ := cs.CoreV1().ResourceQuotas("ns01").Get("rq01", metav1.GetOptions{})
	cpu01 := rq01.Spec.Hard["limits.cpu"]
	if v, _ := (&cpu01).AsInt64(); v != int64(5) {
		t.Fatalf("after scheduler, cpu is not 5 for rq01, %#v", rq01)
	}
	rq02, _ := cs.CoreV1().ResourceQuotas("ns02").Get("rq02", metav1.GetOptions{})
	cpu02 := rq02.Spec.Hard["limits.cpu"]
	if v, _ := (&cpu02).AsInt64(); v != int64(10) {
		t.Fatalf("after scheduler, cpu is not 10 for rq02, %#v", rq02)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
)

type keeper struct {
	client *http.Client
	uri    string
}

func newKeeper(host, snapshot, source string) *keeper {
	return &keeper{
		client: &http.Client{},
		uri:    fmt.Sprintf("http://%s/%s/%s", host, snapshot, source),
	}
}

func (k *keeper) store(header []string, values []float64) {
	sample := map[string]float64{}

	for i, metric := range header {
		sample[metric] = values[i]
	}
	b, err := json.Marshal(sample)
	if err != nil {
		log.Printf("%v", err)
	}
	j := bytes.NewReader(b)

	req, err := http.NewRequest("POST", k.uri, j)
	if err != nil {
		log.Printf("%v", err)
	}

	resp, err := k.client.Do(req)
	if err != nil {
		log.Printf("%v", err)
	}
	defer resp.Body.Close()
	ioutil.ReadAll(resp.Body)
}
<commit_msg>Don't crash when perfkeeper is down<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
)

type keeper struct {
	client *http.Client
	uri    string
}

func newKeeper(host, snapshot, source string) *keeper {
	return &keeper{
		client: &http.Client{},
		uri:    fmt.Sprintf("http://%s/%s/%s", host, snapshot, source),
	}
}

func (k *keeper) store(header []string, values []float64) {
	sample := map[string]float64{}

	for i, metric := range header {
		sample[metric] = values[i]
	}
	b, err := json.Marshal(sample)
	if err != nil {
		log.Printf("%v", err)
		return
	}
	j := bytes.NewReader(b)

	req, err := http.NewRequest("POST", k.uri, j)
	if err != nil {
		log.Printf("%v", err)
		return
	}

	resp, err := k.client.Do(req)
	if err != nil {
		log.Printf("%v", err)
		return
	}
	defer resp.Body.Close()
	ioutil.ReadAll(resp.Body)
}
<|endoftext|>