<commit_before>package elasticsearch

import (
	"encoding/json"
)

// This file contains structures that represent all of the various JSON-
// marshalable queries and sub-queries that are part of the ElasticSearch
// grammar. These structures are one-way: they're only meant to be Marshaled.

type SubQuery interface{}

var nilSubQuery SubQuery

//
//
//

// Wrapper gives a dynamic name to a SubQuery. For example, Name="foo"
// Wrapped=`{"bar": 123}` marshals to `{"foo": {"bar": 123}}`.
//
// You *can* use this directly in your business-logic code, but if you do, it's
// probably a sign you should file an issue (or make a pull request) to give
// your specific use-case proper, first class support, via a FooQuery[Params]
// type-set.
type Wrapper struct {
	Name    string
	Wrapped SubQuery
}

func (w *Wrapper) MarshalJSON() ([]byte, error) {
	return json.Marshal(map[string]SubQuery{
		w.Name: w.Wrapped,
	})
}

//
//
//

func QueryWrapper(q SubQuery) SubQuery {
	return &Wrapper{
		Name:    "query",
		Wrapped: q,
	}
}

//
//
//

// GenericQueryParams marshal to a valid query object for a large number of
// query types. You generally use them applied to a particular field, ie. scope;
// see FieldedGenericQuery.
type GenericQueryParams struct {
	Query              string  `json:"query,omitempty"`
	Analyzer           string  `json:"analyzer,omitempty"`
	Type               string  `json:"type,omitempty"`
	MaxExpansions      string  `json:"max_expansions,omitempty"`
	Boost              float32 `json:"boost,omitempty"`
	Operator           string  `json:"operator,omitempty"`
	MinimumShouldMatch string  `json:"minimum_should_match,omitempty"`
	CutoffFrequency    float32 `json:"cutoff_frequency,omitempty"`
}

// FieldedGenericQuery returns a SubQuery representing the passed QueryParams
// applied to the given scope, ie. field. The returned SubQuery can be used as
// the Query in a MatchQuery, for example.
func FieldedGenericQuery(field string, p GenericQueryParams) SubQuery {
	return &Wrapper{
		Name:    field,
		Wrapped: p,
	}
}

//
//
//

// http://www.elasticsearch.org/guide/reference/query-dsl/match-query.html
type MatchQueryParams struct {
	Query SubQuery `json:"match"`
}

func MatchQuery(p MatchQueryParams) SubQuery {
	return p
}

//
//
//

// http://www.elasticsearch.org/guide/reference/query-dsl/term-query.html
// Typically `Query` would be &Wrapper{Name: "fieldname", Wrapped: "value"}.
type TermQueryParams struct {
	Query SubQuery `json:"term"`
}

func TermQuery(p TermQueryParams) SubQuery {
	return p
}

//
//
//

// http://www.elasticsearch.org/guide/reference/query-dsl/terms-query.html
// "a simpler syntax query for using a `bool` query with several `term` queries
// in the `should` clauses."
type TermsQueryParams struct {
	Query SubQuery `json:"terms"` // often `{ "field": ["value1", "value2"] }`
}

func TermsQuery(p TermsQueryParams) SubQuery {
	return p
}

//
//
//

// http://www.elasticsearch.org/guide/reference/query-dsl/dis-max-query.html
type DisMaxQueryParams struct {
	Queries    []SubQuery `json:"queries"`
	Boost      float32    `json:"boost,omitempty"`
	TieBreaker float32    `json:"tie_breaker,omitempty"`
}

func DisMaxQuery(p DisMaxQueryParams) SubQuery {
	return &Wrapper{
		Name:    "dis_max",
		Wrapped: p,
	}
}

//
//
//

// http://www.elasticsearch.org/guide/reference/query-dsl/bool-query.html
type BoolQueryParams struct {
	Must                     SubQuery `json:"must,omitempty"` // can be slice!
	Should                   SubQuery `json:"should,omitempty"`
	MustNot                  SubQuery `json:"must_not,omitempty"`
	MinimumNumberShouldMatch int      `json:"minimum_number_should_match,omitempty"`
	Boost                    float32  `json:"boost,omitempty"`
}

func BoolQuery(p BoolQueryParams) SubQuery {
	return &Wrapper{
		Name:    "bool",
		Wrapped: p,
	}
}

//
//
//

// http://www.elasticsearch.org/guide/reference/query-dsl/custom-score-query.html
type CustomScoreQueryParams struct {
	Script string                 `json:"script"`
	Lang   string                 `json:"lang"`
	Params map[string]interface{} `json:"params"`
	Query  SubQuery               `json:"query"`
}

func CustomScoreQuery(p CustomScoreQueryParams) SubQuery {
	return &Wrapper{
		Name:    "custom_score",
		Wrapped: p,
	}
}

//
//
//

type ConstantScoreQueryParams struct {
	Query  SubQuery       `json:"query,omitempty"`
	Filter FilterSubQuery `json:"filter,omitempty"`
	Boost  float32        `json:"boost,omitempty"`
}

func ConstantScoreQuery(p ConstantScoreQueryParams) SubQuery {
	return &Wrapper{
		Name:    "constant_score",
		Wrapped: p,
	}
}

//
//
//

func MatchAllQuery() SubQuery {
	return &Wrapper{
		Name:    "match_all",
		Wrapped: map[string]interface{}{}, // render to '{}'
	}
}

//
//
//

// Haven't quite figured out how to best represent this.
// TODO break these up into embeddable query-parts?
type OffsetLimitFacetsFilterQueryParams struct {
	Offset int            `json:"from"`
	Limit  int            `json:"size"`
	Facets FacetSubQuery  `json:"facets,omitempty"`
	Filter FilterSubQuery `json:"filter,omitempty"`
	Query  SubQuery       `json:"query"`
}

//
//
//
// =============================================================================
// HERE BE FILTERS
// =============================================================================
//
//
//

type FilterSubQuery SubQuery

func MakeFilter(filter SubQuery) FilterSubQuery {
	return FilterSubQuery(filter)
}

func MakeFilters(filters []SubQuery) []FilterSubQuery {
	a := []FilterSubQuery{}
	for _, filter := range filters {
		a = append(a, MakeFilter(filter))
	}
	return a
}

type BooleanFiltersParams struct {
	AndFilters []FilterSubQuery
	OrFilters  []FilterSubQuery
}

func BooleanFilters(p BooleanFiltersParams) SubQuery {
	switch nAnd, nOr := len(p.AndFilters), len(p.OrFilters); true {
	case nAnd <= 0 && nOr <= 0:
		return map[string]interface{}{} // render to '{}'

	case nAnd > 0 && nOr <= 0:
		return &Wrapper{
			Name:    "and",
			Wrapped: p.AndFilters,
		}

	case nAnd <= 0 && nOr > 0:
		return &Wrapper{
			Name:    "or",
			Wrapped: p.OrFilters,
		}

	case nAnd > 0 && nOr > 0:
		combinedFilters := append(p.AndFilters, &Wrapper{
			Name:    "or",
			Wrapped: p.OrFilters,
		})
		return &Wrapper{
			Name:    "and",
			Wrapped: combinedFilters,
		}
	}
	panic("unreachable")
}

//
//
//

type QueryFilterParams struct {
	Query SubQuery `json:"query"`
}

func QueryFilter(p QueryFilterParams) FilterSubQuery {
	return p // no need for another layer of indirection; just like a typecast
}

//
//
//

type TermFilterParams struct {
	Field string
	Value string // for multiple values, use TermsFilter
}

func TermFilter(p TermFilterParams) FilterSubQuery {
	return &Wrapper{
		Name: "term",
		Wrapped: &Wrapper{
			Name:    p.Field,
			Wrapped: p.Value,
		},
	}
}

type TermsFilterParams struct {
	Field     string
	Values    []string
	Execution string
}

func TermsFilter(p TermsFilterParams) FilterSubQuery {
	terms := map[string]interface{}{
		p.Field: p.Values,
	}
	if p.Execution != "" {
		terms["execution"] = p.Execution
	}
	return map[string]interface{}{
		"terms": terms,
	}
}

//
//
//

// http://www.elasticsearch.org/guide/reference/query-dsl/type-filter.html
type FieldedFilterParams struct {
	Value string `json:"value"`
}

// TODO I guess remove all Fielded* functions except FieldedGenericQuery?
// TODO and rename FieldedGenericQuery to like FieldedSubObject, maybe?
func FieldedFilter(fieldName string, p FieldedFilterParams) FilterSubQuery {
	return &Wrapper{
		Name:    fieldName,
		Wrapped: p,
	}
}

//
//
//

type RangeSubQuery SubQuery

// http://www.elasticsearch.org/guide/reference/query-dsl/range-filter.html
type RangeFilterParams struct {
	From         string `json:"from,omitempty"`
	To           string `json:"to,omitempty"`
	IncludeLower bool   `json:"include_lower"`
	IncludeUpper bool   `json:"include_upper"`
}

func FieldedRangeSubQuery(field string, p RangeFilterParams) RangeSubQuery {
	return &Wrapper{
		Name:    field,
		Wrapped: p,
	}
}

func RangeFilter(q RangeSubQuery) FilterSubQuery {
	return &Wrapper{
		Name:    "range",
		Wrapped: q,
	}
}

//
//
//
// =============================================================================
// HERE BE FACETS
// =============================================================================
//
//
//

type FacetSubQuery SubQuery

// http://www.elasticsearch.org/guide/reference/api/search/facets/terms-facet.html
type TermsFacetParams struct {
	Field string `json:"field"`
	Size  int    `json:"size"`
}

func TermsFacet(p TermsFacetParams) FacetSubQuery {
	return &Wrapper{
		Name:    "terms",
		Wrapped: p,
	}
}

// TODO other types of facets

// NamedFacet wraps any FooFacet SubQuery so that it can be used
// wherever a facet is called for.
func NamedFacet(name string, q FacetSubQuery) FacetSubQuery {
	return &Wrapper{
		Name:    name,
		Wrapped: q,
	}
}
<commit_msg>ES 1.x: replace custom_score with script_score inside function_score<commit_after>package elasticsearch

import (
	"encoding/json"
)

// This file contains structures that represent all of the various JSON-
// marshalable queries and sub-queries that are part of the ElasticSearch
// grammar. These structures are one-way: they're only meant to be Marshaled.

type SubQuery interface{}

var nilSubQuery SubQuery

//
//
//

// Wrapper gives a dynamic name to a SubQuery. For example, Name="foo"
// Wrapped=`{"bar": 123}` marshals to `{"foo": {"bar": 123}}`.
//
// You *can* use this directly in your business-logic code, but if you do, it's
// probably a sign you should file an issue (or make a pull request) to give
// your specific use-case proper, first class support, via a FooQuery[Params]
// type-set.
type Wrapper struct {
	Name    string
	Wrapped SubQuery
}

func (w *Wrapper) MarshalJSON() ([]byte, error) {
	return json.Marshal(map[string]SubQuery{
		w.Name: w.Wrapped,
	})
}

//
//
//

func QueryWrapper(q SubQuery) SubQuery {
	return &Wrapper{
		Name:    "query",
		Wrapped: q,
	}
}

//
//
//

// GenericQueryParams marshal to a valid query object for a large number of
// query types. You generally use them applied to a particular field, ie. scope;
// see FieldedGenericQuery.
type GenericQueryParams struct {
	Query              string  `json:"query,omitempty"`
	Analyzer           string  `json:"analyzer,omitempty"`
	Type               string  `json:"type,omitempty"`
	MaxExpansions      string  `json:"max_expansions,omitempty"`
	Boost              float32 `json:"boost,omitempty"`
	Operator           string  `json:"operator,omitempty"`
	MinimumShouldMatch string  `json:"minimum_should_match,omitempty"`
	CutoffFrequency    float32 `json:"cutoff_frequency,omitempty"`
}

// FieldedGenericQuery returns a SubQuery representing the passed QueryParams
// applied to the given scope, ie. field. The returned SubQuery can be used as
// the Query in a MatchQuery, for example.
func FieldedGenericQuery(field string, p GenericQueryParams) SubQuery {
	return &Wrapper{
		Name:    field,
		Wrapped: p,
	}
}

//
//
//

// http://www.elasticsearch.org/guide/reference/query-dsl/match-query.html
type MatchQueryParams struct {
	Query SubQuery `json:"match"`
}

func MatchQuery(p MatchQueryParams) SubQuery {
	return p
}

//
//
//

// http://www.elasticsearch.org/guide/reference/query-dsl/term-query.html
// Typically `Query` would be &Wrapper{Name: "fieldname", Wrapped: "value"}.
type TermQueryParams struct {
	Query SubQuery `json:"term"`
}

func TermQuery(p TermQueryParams) SubQuery {
	return p
}

//
//
//

// http://www.elasticsearch.org/guide/reference/query-dsl/terms-query.html
// "a simpler syntax query for using a `bool` query with several `term` queries
// in the `should` clauses."
type TermsQueryParams struct {
	Query SubQuery `json:"terms"` // often `{ "field": ["value1", "value2"] }`
}

func TermsQuery(p TermsQueryParams) SubQuery {
	return p
}

//
//
//

// http://www.elasticsearch.org/guide/reference/query-dsl/dis-max-query.html
type DisMaxQueryParams struct {
	Queries    []SubQuery `json:"queries"`
	Boost      float32    `json:"boost,omitempty"`
	TieBreaker float32    `json:"tie_breaker,omitempty"`
}

func DisMaxQuery(p DisMaxQueryParams) SubQuery {
	return &Wrapper{
		Name:    "dis_max",
		Wrapped: p,
	}
}

//
//
//

// http://www.elasticsearch.org/guide/reference/query-dsl/bool-query.html
type BoolQueryParams struct {
	Must                     SubQuery `json:"must,omitempty"` // can be slice!
	Should                   SubQuery `json:"should,omitempty"`
	MustNot                  SubQuery `json:"must_not,omitempty"`
	MinimumNumberShouldMatch int      `json:"minimum_number_should_match,omitempty"`
	Boost                    float32  `json:"boost,omitempty"`
}

func BoolQuery(p BoolQueryParams) SubQuery {
	return &Wrapper{
		Name:    "bool",
		Wrapped: p,
	}
}

//
//
//

// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html
type ScriptScoreQueryParams struct {
	Lang      string
	Script    string
	Params    map[string]interface{}
	Query     SubQuery
	BoostMode string
}

func ScriptScoreQuery(p ScriptScoreQueryParams) SubQuery {
	return &Wrapper{
		Name: "function_score",
		Wrapped: map[string]interface{}{
			"script_score": map[string]interface{}{
				"lang":   p.Lang,
				"script": p.Script,
				"params": p.Params,
			},
			"query":      p.Query,
			"boost_mode": p.BoostMode,
		},
	}
}

//
//
//

type ConstantScoreQueryParams struct {
	Query  SubQuery       `json:"query,omitempty"`
	Filter FilterSubQuery `json:"filter,omitempty"`
	Boost  float32        `json:"boost,omitempty"`
}

func ConstantScoreQuery(p ConstantScoreQueryParams) SubQuery {
	return &Wrapper{
		Name:    "constant_score",
		Wrapped: p,
	}
}

//
//
//

func MatchAllQuery() SubQuery {
	return &Wrapper{
		Name:    "match_all",
		Wrapped: map[string]interface{}{}, // render to '{}'
	}
}

//
//
//

// Haven't quite figured out how to best represent this.
// TODO break these up into embeddable query-parts?
type OffsetLimitFacetsFilterQueryParams struct {
	Offset int            `json:"from"`
	Limit  int            `json:"size"`
	Facets FacetSubQuery  `json:"facets,omitempty"`
	Filter FilterSubQuery `json:"filter,omitempty"`
	Query  SubQuery       `json:"query"`
}

//
//
//
// =============================================================================
// HERE BE FILTERS
// =============================================================================
//
//
//

type FilterSubQuery SubQuery

func MakeFilter(filter SubQuery) FilterSubQuery {
	return FilterSubQuery(filter)
}

func MakeFilters(filters []SubQuery) []FilterSubQuery {
	a := []FilterSubQuery{}
	for _, filter := range filters {
		a = append(a, MakeFilter(filter))
	}
	return a
}

type BooleanFiltersParams struct {
	AndFilters []FilterSubQuery
	OrFilters  []FilterSubQuery
}

func BooleanFilters(p BooleanFiltersParams) SubQuery {
	switch nAnd, nOr := len(p.AndFilters), len(p.OrFilters); true {
	case nAnd <= 0 && nOr <= 0:
		return map[string]interface{}{} // render to '{}'

	case nAnd > 0 && nOr <= 0:
		return &Wrapper{
			Name:    "and",
			Wrapped: p.AndFilters,
		}

	case nAnd <= 0 && nOr > 0:
		return &Wrapper{
			Name:    "or",
			Wrapped: p.OrFilters,
		}

	case nAnd > 0 && nOr > 0:
		combinedFilters := append(p.AndFilters, &Wrapper{
			Name:    "or",
			Wrapped: p.OrFilters,
		})
		return &Wrapper{
			Name:    "and",
			Wrapped: combinedFilters,
		}
	}
	panic("unreachable")
}

//
//
//

type QueryFilterParams struct {
	Query SubQuery `json:"query"`
}

func QueryFilter(p QueryFilterParams) FilterSubQuery {
	return p // no need for another layer of indirection; just like a typecast
}

//
//
//

type TermFilterParams struct {
	Field string
	Value string // for multiple values, use TermsFilter
}

func TermFilter(p TermFilterParams) FilterSubQuery {
	return &Wrapper{
		Name: "term",
		Wrapped: &Wrapper{
			Name:    p.Field,
			Wrapped: p.Value,
		},
	}
}

type TermsFilterParams struct {
	Field     string
	Values    []string
	Execution string
}

func TermsFilter(p TermsFilterParams) FilterSubQuery {
	terms := map[string]interface{}{
		p.Field: p.Values,
	}
	if p.Execution != "" {
		terms["execution"] = p.Execution
	}
	return map[string]interface{}{
		"terms": terms,
	}
}

//
//
//

// http://www.elasticsearch.org/guide/reference/query-dsl/type-filter.html
type FieldedFilterParams struct {
	Value string `json:"value"`
}

// TODO I guess remove all Fielded* functions except FieldedGenericQuery?
// TODO and rename FieldedGenericQuery to like FieldedSubObject, maybe?
func FieldedFilter(fieldName string, p FieldedFilterParams) FilterSubQuery {
	return &Wrapper{
		Name:    fieldName,
		Wrapped: p,
	}
}

//
//
//

type RangeSubQuery SubQuery

// http://www.elasticsearch.org/guide/reference/query-dsl/range-filter.html
type RangeFilterParams struct {
	From         string `json:"from,omitempty"`
	To           string `json:"to,omitempty"`
	IncludeLower bool   `json:"include_lower"`
	IncludeUpper bool   `json:"include_upper"`
}

func FieldedRangeSubQuery(field string, p RangeFilterParams) RangeSubQuery {
	return &Wrapper{
		Name:    field,
		Wrapped: p,
	}
}

func RangeFilter(q RangeSubQuery) FilterSubQuery {
	return &Wrapper{
		Name:    "range",
		Wrapped: q,
	}
}

//
//
//
// =============================================================================
// HERE BE FACETS
// =============================================================================
//
//
//

type FacetSubQuery SubQuery

// http://www.elasticsearch.org/guide/reference/api/search/facets/terms-facet.html
type TermsFacetParams struct {
	Field string `json:"field"`
	Size  int    `json:"size"`
}

func TermsFacet(p TermsFacetParams) FacetSubQuery {
	return &Wrapper{
		Name:    "terms",
		Wrapped: p,
	}
}

// TODO other types of facets

// NamedFacet wraps any FooFacet SubQuery so that it can be used
// wherever a facet is called for.
func NamedFacet(name string, q FacetSubQuery) FacetSubQuery {
	return &Wrapper{
		Name:    name,
		Wrapped: q,
	}
}
<|endoftext|>


<commit_before>package stockfighter

import (
	"fmt"
	"time"
)

type OrderType int

const (
	Limit OrderType = iota
	Market
	FillOrKill
	ImmediateOrCancel
)

type Game struct {
	Account              string
	InstanceId           uint64
	Instructions         map[string]string
	SecondsPerTradingDay uint64
	Tickers              []string
	Venues               []string
}

type GameState struct {
	Details struct {
		EndOfTheWorldDay uint64
		TradingDay       uint64
	}
	Flash struct {
		Info string
	}
	Done  bool
	Id    uint64
	State string
}

type Symbol struct {
	Symbol string
	Name   string
}

type Order struct {
	Account   string    `json:"account"`
	Venue     string    `json:"venue"`
	Stock     string    `json:"stock"`
	Price     uint64    `json:"price"`
	Quantity  uint64    `json:"qty"`
	Direction string    `json:"direction"`
	OrderType OrderType `json:"orderType"`
}

type StandingOrder struct {
	Price    uint64
	Quantity uint64 `json:"qty"`
	IsBuy    bool
}

type OrderBook struct {
	Venue     string
	Symbol    string
	Asks      []StandingOrder
	Bids      []StandingOrder
	TimeStamp time.Time `json:"ts"`
}

type Fill struct {
	Price     uint64
	Quantity  uint64    `json:"qty"`
	TimeStamp time.Time `json:"ts"`
}

type OrderState struct {
	Venue            string
	Symbol           string
	Price            uint64
	OriginalQuantity uint64 `json:"originalQty"`
	Quantity         uint64 `json:"qty"`
	Direction        string
	Type             OrderType
	Id               uint64
	Account          string
	Timestamp        time.Time `json:"ts"`
	Fills            []Fill
	TotalFilled      uint64
	Open             bool
}

type Quote struct {
	Venue     string
	Symbol    string
	Bid       uint64
	BidSize   uint64
	BidDepth  uint64
	Ask       uint64
	AskSize   uint64
	AskDepth  uint64
	Last      uint64
	LastSize  uint64
	LastTrade time.Time
	QuoteTime time.Time
}

type Execution struct {
	Account          string
	Venue            string
	Symbol           string
	Order            OrderState
	StandingId       uint64
	Price            uint64
	Filled           uint64
	FilledAt         time.Time
	StandingComplete bool
	IncomingComplete bool
}

var orderTypes = [...]string{
	Limit:             "limit",
	Market:            "market",
	FillOrKill:        "fill-or-kill",
	ImmediateOrCancel: "immediate-or-cancel",
}

func (o OrderType) MarshalText() ([]byte, error) {
	return []byte(orderTypes[o]), nil
}

func (o OrderType) String() string {
	return orderTypes[o]
}

var orderTypeMap = map[string]OrderType{
	"limit":               Limit,
	"market":              Market,
	"fill-or-kill":        FillOrKill,
	"immediate-or-cancel": ImmediateOrCancel,
}

func (o *OrderType) UnmarshalText(text []byte) error {
	typ, ok := orderTypeMap[string(text)]
	if ok {
		*o = typ
		return nil
	}
	return fmt.Errorf("Unknown order type: %s", text)
}
<commit_msg>Add missing IncomingId field to Execution<commit_after>package stockfighter

import (
	"fmt"
	"time"
)

type OrderType int

const (
	Limit OrderType = iota
	Market
	FillOrKill
	ImmediateOrCancel
)

type Game struct {
	Account              string
	InstanceId           uint64
	Instructions         map[string]string
	SecondsPerTradingDay uint64
	Tickers              []string
	Venues               []string
}

type GameState struct {
	Details struct {
		EndOfTheWorldDay uint64
		TradingDay       uint64
	}
	Flash struct {
		Info string
	}
	Done  bool
	Id    uint64
	State string
}

type Symbol struct {
	Symbol string
	Name   string
}

type Order struct {
	Account   string    `json:"account"`
	Venue     string    `json:"venue"`
	Stock     string    `json:"stock"`
	Price     uint64    `json:"price"`
	Quantity  uint64    `json:"qty"`
	Direction string    `json:"direction"`
	OrderType OrderType `json:"orderType"`
}

type StandingOrder struct {
	Price    uint64
	Quantity uint64 `json:"qty"`
	IsBuy    bool
}

type OrderBook struct {
	Venue     string
	Symbol    string
	Asks      []StandingOrder
	Bids      []StandingOrder
	TimeStamp time.Time `json:"ts"`
}

type Fill struct {
	Price     uint64
	Quantity  uint64    `json:"qty"`
	TimeStamp time.Time `json:"ts"`
}

type OrderState struct {
	Venue            string
	Symbol           string
	Price            uint64
	OriginalQuantity uint64 `json:"originalQty"`
	Quantity         uint64 `json:"qty"`
	Direction        string
	Type             OrderType
	Id               uint64
	Account          string
	Timestamp        time.Time `json:"ts"`
	Fills            []Fill
	TotalFilled      uint64
	Open             bool
}

type Quote struct {
	Venue     string
	Symbol    string
	Bid       uint64
	BidSize   uint64
	BidDepth  uint64
	Ask       uint64
	AskSize   uint64
	AskDepth  uint64
	Last      uint64
	LastSize  uint64
	LastTrade time.Time
	QuoteTime time.Time
}

type Execution struct {
	Account          string
	Venue            string
	Symbol           string
	Order            OrderState
	StandingId       uint64
	IncomingId       uint64
	Price            uint64
	Filled           uint64
	FilledAt         time.Time
	StandingComplete bool
	IncomingComplete bool
}

var orderTypes = [...]string{
	Limit:             "limit",
	Market:            "market",
	FillOrKill:        "fill-or-kill",
	ImmediateOrCancel: "immediate-or-cancel",
}

func (o OrderType) MarshalText() ([]byte, error) {
	return []byte(orderTypes[o]), nil
}

func (o OrderType) String() string {
	return orderTypes[o]
}

var orderTypeMap = map[string]OrderType{
	"limit":               Limit,
	"market":              Market,
	"fill-or-kill":        FillOrKill,
	"immediate-or-cancel": ImmediateOrCancel,
}

func (o *OrderType) UnmarshalText(text []byte) error {
	typ, ok := orderTypeMap[string(text)]
	if ok {
		*o = typ
		return nil
	}
	return fmt.Errorf("Unknown order type: %s", text)
}
<|endoftext|>


<commit_before>package build

import (
	"bytes"
	"flag"
	"fmt"
	cmdcommon "github.com/mitchellh/packer/common/command"
	"github.com/mitchellh/packer/packer"
	"log"
	"os"
	"os/signal"
	"strconv"
	"strings"
	"sync"
)

type Command byte

func (Command) Help() string {
	return strings.TrimSpace(helpText)
}

func (c Command) Run(env packer.Environment, args []string) int {
	var cfgDebug bool
	var cfgForce bool
	buildOptions := new(cmdcommon.BuildOptions)

	cmdFlags := flag.NewFlagSet("build", flag.ContinueOnError)
	cmdFlags.Usage = func() { env.Ui().Say(c.Help()) }
	cmdFlags.BoolVar(&cfgDebug, "debug", false, "debug mode for builds")
	cmdFlags.BoolVar(&cfgForce, "force", false, "force a build if artifacts exist")
	cmdcommon.BuildOptionFlags(cmdFlags, buildOptions)
	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	args = cmdFlags.Args()
	if len(args) != 1 {
		cmdFlags.Usage()
		return 1
	}

	if err := buildOptions.Validate(); err != nil {
		env.Ui().Error(err.Error())
		env.Ui().Error("")
		env.Ui().Error(c.Help())
		return 1
	}

	userVars, err := buildOptions.AllUserVars()
	if err != nil {
		env.Ui().Error(fmt.Sprintf("Error compiling user variables: %s", err))
		env.Ui().Error("")
		env.Ui().Error(c.Help())
		return 1
	}

	// Read the file into a byte array so that we can parse the template
	log.Printf("Reading template: %s", args[0])
	tpl, err := packer.ParseTemplateFile(args[0])
	if err != nil {
		env.Ui().Error(fmt.Sprintf("Failed to parse template: %s", err))
		return 1
	}

	// The component finder for our builds
	components := &packer.ComponentFinder{
		Builder:       env.Builder,
		Hook:          env.Hook,
		PostProcessor: env.PostProcessor,
		Provisioner:   env.Provisioner,
	}

	// Go through each builder and compile the builds that we care about
	builds, err := buildOptions.Builds(tpl, components)
	if err != nil {
		env.Ui().Error(err.Error())
		return 1
	}

	if cfgDebug {
		env.Ui().Say("Debug mode enabled. Builds will not be parallelized.")
	}

	// Compile all the UIs for the builds
	colors := [5]packer.UiColor{
		packer.UiColorGreen,
		packer.UiColorCyan,
		packer.UiColorMagenta,
		packer.UiColorYellow,
		packer.UiColorBlue,
	}

	buildUis := make(map[string]packer.Ui)
	for i, b := range builds {
		ui := &packer.ColoredUi{
			Color: colors[i%len(colors)],
			Ui:    env.Ui(),
		}

		buildUis[b.Name()] = ui
		ui.Say(fmt.Sprintf("%s output will be in this color.", b.Name()))
	}

	// Add a newline between the color output and the actual output
	env.Ui().Say("")

	log.Printf("Build debug mode: %v", cfgDebug)
	log.Printf("Force build: %v", cfgForce)

	// Set the debug and force mode and prepare all the builds
	for _, b := range builds {
		log.Printf("Preparing build: %s", b.Name())
		b.SetDebug(cfgDebug)
		b.SetForce(cfgForce)
		// TODO(mitchellh): Handle warnings
		_, err := b.Prepare(userVars)
		if err != nil {
			env.Ui().Error(err.Error())
			return 1
		}
	}

	// Run all the builds in parallel and wait for them to complete
	var interruptWg, wg sync.WaitGroup
	interrupted := false
	artifacts := make(map[string][]packer.Artifact)
	errors := make(map[string]error)
	for _, b := range builds {
		// Increment the waitgroup so we wait for this item to finish properly
		wg.Add(1)

		// Handle interrupts for this build
		sigCh := make(chan os.Signal, 1)
		signal.Notify(sigCh, os.Interrupt)
		defer signal.Stop(sigCh)
		go func(b packer.Build) {
			<-sigCh
			interruptWg.Add(1)
			defer interruptWg.Done()
			interrupted = true

			log.Printf("Stopping build: %s", b.Name())
			b.Cancel()
			log.Printf("Build cancelled: %s", b.Name())
		}(b)

		// Run the build in a goroutine
		go func(b packer.Build) {
			defer wg.Done()

			name := b.Name()
			log.Printf("Starting build run: %s", name)
			ui := buildUis[name]
			runArtifacts, err := b.Run(ui, env.Cache())

			if err != nil {
				ui.Error(fmt.Sprintf("Build '%s' errored: %s", name, err))
				errors[name] = err
			} else {
				ui.Say(fmt.Sprintf("Build '%s' finished.", name))
				artifacts[name] = runArtifacts
			}
		}(b)

		if cfgDebug {
			log.Printf("Debug enabled, so waiting for build to finish: %s", b.Name())
			wg.Wait()
		}

		if interrupted {
			log.Println("Interrupted, not going to start any more builds.")
			break
		}
	}

	// Wait for both the builds to complete and the interrupt handler,
	// if it is interrupted.
	log.Printf("Waiting on builds to complete...")
	wg.Wait()

	log.Printf("Builds completed. Waiting on interrupt barrier...")
	interruptWg.Wait()

	if interrupted {
		env.Ui().Say("Cleanly cancelled builds after being interrupted.")
		return 1
	}

	if len(errors) > 0 {
		env.Ui().Machine("error-count", strconv.FormatInt(int64(len(errors)), 10))

		env.Ui().Error("\n==> Some builds didn't complete successfully and had errors:")
		for name, err := range errors {
			// Create a UI for the machine readable stuff to be targetted
			ui := &packer.TargettedUi{
				Target: name,
				Ui:     env.Ui(),
			}

			ui.Machine("error", err.Error())

			env.Ui().Error(fmt.Sprintf("--> %s: %s", name, err))
		}
	}

	if len(artifacts) > 0 {
		env.Ui().Say("\n==> Builds finished. The artifacts of successful builds are:")
		for name, buildArtifacts := range artifacts {
			// Create a UI for the machine readable stuff to be targetted
			ui := &packer.TargettedUi{
				Target: name,
				Ui:     env.Ui(),
			}

			// Machine-readable helpful
			ui.Machine("artifact-count", strconv.FormatInt(int64(len(buildArtifacts)), 10))

			for i, artifact := range buildArtifacts {
				var message bytes.Buffer
				fmt.Fprintf(&message, "--> %s: ", name)

				if artifact != nil {
					fmt.Fprintf(&message, artifact.String())
				} else {
					fmt.Fprint(&message, "<nothing>")
				}

				iStr := strconv.FormatInt(int64(i), 10)
				if artifact != nil {
					ui.Machine("artifact", iStr, "builder-id", artifact.BuilderId())
					ui.Machine("artifact", iStr, "id", artifact.Id())
					ui.Machine("artifact", iStr, "string", artifact.String())

					files := artifact.Files()
					ui.Machine("artifact",
						iStr,
						"files-count", strconv.FormatInt(int64(len(files)), 10))
					for fi, file := range files {
						fiStr := strconv.FormatInt(int64(fi), 10)
						ui.Machine("artifact", iStr, "file", fiStr, file)
					}
				} else {
					ui.Machine("artifact", iStr, "nil")
				}

				ui.Machine("artifact", iStr, "end")
				env.Ui().Say(message.String())
			}
		}
	} else {
		env.Ui().Say("\n==> Builds finished but no artifacts were created.")
	}

	if len(errors) > 0 {
		// If any errors occurred, exit with a non-zero exit status
		return 1
	}

	return 0
}

func (Command) Synopsis() string {
	return "build image(s) from template"
}
<commit_msg>command/build: output warnings<commit_after>package build

import (
	"bytes"
	"flag"
	"fmt"
	cmdcommon "github.com/mitchellh/packer/common/command"
	"github.com/mitchellh/packer/packer"
	"log"
	"os"
	"os/signal"
	"strconv"
	"strings"
	"sync"
)

type Command byte

func (Command) Help() string {
	return strings.TrimSpace(helpText)
}

func (c Command) Run(env packer.Environment, args []string) int {
	var cfgDebug bool
	var cfgForce bool
	buildOptions := new(cmdcommon.BuildOptions)

	cmdFlags := flag.NewFlagSet("build", flag.ContinueOnError)
	cmdFlags.Usage = func() { env.Ui().Say(c.Help()) }
	cmdFlags.BoolVar(&cfgDebug, "debug", false, "debug mode for builds")
	cmdFlags.BoolVar(&cfgForce, "force", false, "force a build if artifacts exist")
	cmdcommon.BuildOptionFlags(cmdFlags, buildOptions)
	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	args = cmdFlags.Args()
	if len(args) != 1 {
		cmdFlags.Usage()
		return 1
	}

	if err := buildOptions.Validate(); err != nil {
		env.Ui().Error(err.Error())
		env.Ui().Error("")
		env.Ui().Error(c.Help())
		return 1
	}

	userVars, err := buildOptions.AllUserVars()
	if err != nil {
		env.Ui().Error(fmt.Sprintf("Error compiling user variables: %s", err))
		env.Ui().Error("")
		env.Ui().Error(c.Help())
		return 1
	}

	// Read the file into a byte array so that we can parse the template
	log.Printf("Reading template: %s", args[0])
	tpl, err := packer.ParseTemplateFile(args[0])
	if err != nil {
		env.Ui().Error(fmt.Sprintf("Failed to parse template: %s", err))
		return 1
	}

	// The component finder for our builds
	components := &packer.ComponentFinder{
		Builder:       env.Builder,
		Hook:          env.Hook,
		PostProcessor: env.PostProcessor,
		Provisioner:   env.Provisioner,
	}

	// Go through each builder and compile the builds that we care about
	builds, err := buildOptions.Builds(tpl, components)
	if err != nil {
		env.Ui().Error(err.Error())
		return 1
	}

	if cfgDebug {
		env.Ui().Say("Debug mode enabled. Builds will not be parallelized.")
	}

	// Compile all the UIs for the builds
	colors := [5]packer.UiColor{
		packer.UiColorGreen,
		packer.UiColorCyan,
		packer.UiColorMagenta,
		packer.UiColorYellow,
		packer.UiColorBlue,
	}

	buildUis := make(map[string]packer.Ui)
	for i, b := range builds {
		ui := &packer.ColoredUi{
			Color: colors[i%len(colors)],
			Ui:    env.Ui(),
		}

		buildUis[b.Name()] = ui
		ui.Say(fmt.Sprintf("%s output will be in this color.", b.Name()))
	}

	// Add a newline between the color output and the actual output
	env.Ui().Say("")

	log.Printf("Build debug mode: %v", cfgDebug)
	log.Printf("Force build: %v", cfgForce)

	// Set the debug and force mode and prepare all the builds
	for _, b := range builds {
		log.Printf("Preparing build: %s", b.Name())
		b.SetDebug(cfgDebug)
		b.SetForce(cfgForce)

		warnings, err := b.Prepare(userVars)
		if err != nil {
			env.Ui().Error(err.Error())
			return 1
		}
		if len(warnings) > 0 {
			ui := buildUis[b.Name()]
			ui.Say(fmt.Sprintf("Warnings for build '%s':\n", b.Name()))
			for _, warning := range warnings {
				ui.Say(fmt.Sprintf("* %s", warning))
			}
			ui.Say("")
		}
	}

	// Run all the builds in parallel and wait for them to complete
	var interruptWg, wg sync.WaitGroup
	interrupted := false
	artifacts := make(map[string][]packer.Artifact)
	errors := make(map[string]error)
	for _, b := range builds {
		// Increment the waitgroup so we wait for this item to finish properly
		wg.Add(1)

		// Handle interrupts for this build
		sigCh := make(chan os.Signal, 1)
		signal.Notify(sigCh, os.Interrupt)
		defer signal.Stop(sigCh)
		go func(b packer.Build) {
			<-sigCh
			interruptWg.Add(1)
			defer interruptWg.Done()
			interrupted = true

			log.Printf("Stopping build: %s", b.Name())
			b.Cancel()
			log.Printf("Build cancelled: %s", b.Name())
		}(b)

		// Run the build in a goroutine
		go func(b packer.Build) {
			defer wg.Done()

			name := b.Name()
			log.Printf("Starting build run: %s", name)
			ui := buildUis[name]
			runArtifacts, err := b.Run(ui, env.Cache())

			if err != nil {
				ui.Error(fmt.Sprintf("Build '%s' errored: %s", name, err))
				errors[name] = err
			} else {
				ui.Say(fmt.Sprintf("Build '%s' finished.", name))
				artifacts[name] = runArtifacts
			}
		}(b)

		if cfgDebug {
			log.Printf("Debug enabled, so waiting for build to finish: %s", b.Name())
			wg.Wait()
		}

		if interrupted {
			log.Println("Interrupted, not going to start any more builds.")
			break
		}
	}

	// Wait for both the builds to complete and the interrupt handler,
	// if it is interrupted.
	log.Printf("Waiting on builds to complete...")
	wg.Wait()

	log.Printf("Builds completed. Waiting on interrupt barrier...")
	interruptWg.Wait()

	if interrupted {
		env.Ui().Say("Cleanly cancelled builds after being interrupted.")
		return 1
	}

	if len(errors) > 0 {
		env.Ui().Machine("error-count", strconv.FormatInt(int64(len(errors)), 10))

		env.Ui().Error("\n==> Some builds didn't complete successfully and had errors:")
		for name, err := range errors {
			// Create a UI for the machine readable stuff to be targetted
			ui := &packer.TargettedUi{
				Target: name,
				Ui:     env.Ui(),
			}

			ui.Machine("error", err.Error())

			env.Ui().Error(fmt.Sprintf("--> %s: %s", name, err))
		}
	}

	if len(artifacts) > 0 {
		env.Ui().Say("\n==> Builds finished. The artifacts of successful builds are:")
		for name, buildArtifacts := range artifacts {
			// Create a UI for the machine readable stuff to be targetted
			ui := &packer.TargettedUi{
				Target: name,
				Ui:     env.Ui(),
			}

			// Machine-readable helpful
			ui.Machine("artifact-count", strconv.FormatInt(int64(len(buildArtifacts)), 10))

			for i, artifact := range buildArtifacts {
				var message bytes.Buffer
				fmt.Fprintf(&message, "--> %s: ", name)

				if artifact != nil {
					fmt.Fprintf(&message, artifact.String())
				} else {
					fmt.Fprint(&message, "<nothing>")
				}

				iStr := strconv.FormatInt(int64(i), 10)
				if artifact != nil {
					ui.Machine("artifact", iStr, "builder-id", artifact.BuilderId())
					ui.Machine("artifact", iStr, "id", artifact.Id())
					ui.Machine("artifact", iStr, "string", artifact.String())

					files := artifact.Files()
					ui.Machine("artifact",
						iStr,
						"files-count", strconv.FormatInt(int64(len(files)), 10))
					for fi, file := range files {
						fiStr := strconv.FormatInt(int64(fi), 10)
						ui.Machine("artifact", iStr, "file", fiStr, file)
					}
				} else {
					ui.Machine("artifact", iStr, "nil")
				}

				ui.Machine("artifact", iStr, "end")
				env.Ui().Say(message.String())
			}
		}
	} else {
		env.Ui().Say("\n==> Builds finished but no artifacts were created.")
	}

	if len(errors) > 0 {
		// If any errors occurred, exit with a non-zero exit status
		return 1
	}

	return 0
}

func (Command) Synopsis() string {
	return "build image(s) from template"
}
<|endoftext|>


<commit_before>package command

import (
	"flag"
	"fmt"
	"log"
	"os"
	"strings"

	"github.com/hashicorp/terraform/state"
	"github.com/hashicorp/terraform/state/remote"
	"github.com/hashicorp/terraform/terraform"
)

// remoteCommandConfig is used to encapsulate our configuration
type remoteCommandConfig struct {
	disableRemote bool
	pullOnDisable bool

	statePath  string
	backupPath string
}

// RemoteConfigCommand is a Command implementation that is used to
// enable and disable remote state management
type RemoteConfigCommand struct {
	Meta
	conf       remoteCommandConfig
	remoteConf terraform.RemoteState
}

func (c *RemoteConfigCommand) Run(args []string) int {
	args = c.Meta.process(args, false)
	config := make(map[string]string)
	cmdFlags := flag.NewFlagSet("remote", flag.ContinueOnError)
	cmdFlags.BoolVar(&c.conf.disableRemote, "disable", false, "")
	cmdFlags.BoolVar(&c.conf.pullOnDisable, "pull", true, "")
	cmdFlags.StringVar(&c.conf.statePath, "state", DefaultStateFilename, "path")
	cmdFlags.StringVar(&c.conf.backupPath, "backup", "", "path")
	cmdFlags.StringVar(&c.remoteConf.Type, "backend", "atlas", "")
	cmdFlags.Var((*FlagKV)(&config), "backend-config", "config")
	cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	// Set the local state path
	c.statePath = c.conf.statePath

	// Populate the various configurations
	c.remoteConf.Config = config

	// Get the state information. We specifically request the cache only
	// for the remote state here because it is possible the remote state
	// is invalid and we don't want to error.
	stateOpts := c.StateOpts()
	stateOpts.RemoteCacheOnly = true
	if _, err := c.StateRaw(stateOpts); err != nil {
		c.Ui.Error(fmt.Sprintf("Error loading local state: %s", err))
		return 1
	}

	// Get the local and remote [cached] state
	localState := c.stateResult.Local.State()
	var remoteState *terraform.State
	if remote := c.stateResult.Remote; remote != nil {
		remoteState = remote.State()
	}

	// Check if remote state is being disabled
	if c.conf.disableRemote {
		if !remoteState.IsRemote() {
			c.Ui.Error(fmt.Sprintf("Remote state management not enabled! Aborting."))
			return 1
		}
		if !localState.Empty() {
			c.Ui.Error(fmt.Sprintf("State file already exists at '%s'. Aborting.",
				c.conf.statePath))
			return 1
		}

		return c.disableRemoteState()
	}

	// Ensure there is no conflict
	haveCache := !remoteState.Empty()
	haveLocal := !localState.Empty()
	switch {
	case haveCache && haveLocal:
		c.Ui.Error(fmt.Sprintf("Remote state is enabled, but non-managed state file '%s' is also present!",
			c.conf.statePath))
		return 1

	case !haveCache && !haveLocal:
		// If we don't have either state file, initialize a blank state file
		return c.initBlankState()

	case haveCache && !haveLocal:
		// Update the remote state target potentially
		return c.updateRemoteConfig()

	case !haveCache && haveLocal:
		// Enable remote state management
		return c.enableRemoteState()
	}

	panic("unhandled case")
}

// disableRemoteState is used to disable remote state management,
// and move the state file into place.
func (c *RemoteConfigCommand) disableRemoteState() int {
	if c.stateResult == nil {
		c.Ui.Error(fmt.Sprintf(
			"Internal error. State() must be called internally before remote\n" +
				"state can be disabled. Please report this as a bug."))
		return 1
	}
	if !c.stateResult.State.State().IsRemote() {
		c.Ui.Error(fmt.Sprintf(
			"Remote state is not enabled. Can't disable remote state."))
		return 1
	}
	local := c.stateResult.Local
	remote := c.stateResult.Remote

	// Ensure we have the latest state before disabling
	if c.conf.pullOnDisable {
		log.Printf("[INFO] Refreshing local state from remote server")
		if err := remote.RefreshState(); err != nil {
			c.Ui.Error(fmt.Sprintf(
				"Failed to refresh from remote state: %s", err))
			return 1
		}

		// Exit if we were unable to update
		if change := remote.RefreshResult(); !change.SuccessfulPull() {
			c.Ui.Error(fmt.Sprintf("%s", change))
			return 1
		} else {
			log.Printf("[INFO] %s", change)
		}
	}

	// Clear the remote management, and copy into place
	newState := remote.State()
	newState.Remote = nil
	if err := local.WriteState(newState); err != nil {
		c.Ui.Error(fmt.Sprintf("Failed to encode state file '%s': %s",
			c.conf.statePath, err))
		return 1
	}
	if err := local.PersistState(); err != nil {
		c.Ui.Error(fmt.Sprintf("Failed to encode state file '%s': %s",
			c.conf.statePath, err))
		return 1
	}

	// Remove the old state file
	if err := os.Remove(c.stateResult.RemotePath); err != nil {
		c.Ui.Error(fmt.Sprintf("Failed to remove the local state file: %v", err))
		return 1
	}

	return 0
}

// validateRemoteConfig is used to verify that the remote configuration
// we have is valid
func (c *RemoteConfigCommand) validateRemoteConfig() error {
	conf := c.remoteConf
	_, err := remote.NewClient(conf.Type, conf.Config)
	if err != nil {
		c.Ui.Error(fmt.Sprintf(
			"%s\n\n"+
				"If the error message above mentions requiring or modifying configuration\n"+
				"options, these are set using the `-backend-config` flag. Example:\n"+
				"-backend-config=\"name=foo\" to set the `name` configuration",
			err))
	}
	return err
}

// initBlank state is used to initialize a blank state that is
// remote enabled
func (c *RemoteConfigCommand) initBlankState() int {
	// Validate the remote configuration
	if err := c.validateRemoteConfig(); err != nil {
		return 1
	}

	// Make a blank state, attach the remote configuration
	blank := terraform.NewState()
	blank.Remote = &c.remoteConf

	// Persist the state
	remote := &state.LocalState{Path: c.stateResult.RemotePath}
	if err := remote.WriteState(blank); err != nil {
		c.Ui.Error(fmt.Sprintf("Failed to initialize state file: %v", err))
		return 1
	}
	if err := remote.PersistState(); err != nil {
		c.Ui.Error(fmt.Sprintf("Failed to initialize state file: %v", err))
		return 1
	}

	// Success!
	c.Ui.Output("Initialized blank state with remote state enabled!")
	return 0
}

// updateRemoteConfig is used to update the configuration of the
// remote state store
func (c *RemoteConfigCommand) updateRemoteConfig() int {
	// Validate the remote configuration
	if err := c.validateRemoteConfig(); err != nil {
		return 1
	}

	// Read in the local state, which is just the cache of the remote state
	remote := c.stateResult.Remote.Cache

	// Update the configuration
	state := remote.State()
	state.Remote = &c.remoteConf
	if err := remote.WriteState(state); err != nil {
		c.Ui.Error(fmt.Sprintf("%s", err))
		return 1
	}
	if err := remote.PersistState(); err != nil {
		c.Ui.Error(fmt.Sprintf("%s", err))
		return 1
	}

	// Success!
	c.Ui.Output("Remote configuration updated")
	return 0
}

// enableRemoteState is used to enable remote state management
// and to move a state file into place
func (c *RemoteConfigCommand) enableRemoteState() int {
	// Validate the remote configuration
	if err := c.validateRemoteConfig(); err != nil {
		return 1
	}

	// Read the local state
	local := c.stateResult.Local
	if err := local.RefreshState(); err != nil {
		c.Ui.Error(fmt.Sprintf("Failed to read local state: %s", err))
		return 1
	}

	// Backup the state file before we modify it
	backupPath := c.conf.backupPath
	if backupPath != "-" {
		// Provide default backup path if none provided
		if backupPath == "" {
			backupPath = c.conf.statePath + DefaultBackupExtention
		}

		log.Printf("[INFO] Writing backup state to: %s", backupPath)
		backup := &state.LocalState{Path: backupPath}
		if err := backup.WriteState(local.State()); err != nil {
			c.Ui.Error(fmt.Sprintf("Error writing backup state file: %s", err))
			return 1
		}
		if err := backup.PersistState(); err != nil {
			c.Ui.Error(fmt.Sprintf("Error writing backup state file: %s", err))
			return 1
		}
	}

	// Update the local configuration, move into place
	state := local.State()
	state.Remote = &c.remoteConf
	remote := c.stateResult.Remote
	if err := remote.WriteState(state); err != nil {
		c.Ui.Error(fmt.Sprintf("%s", err))
		return 1
	}
	if err := remote.PersistState(); err != nil {
		c.Ui.Error(fmt.Sprintf("%s", err))
		return 1
	}

	// Remove the original, local state file
	log.Printf("[INFO] Removing state file: %s", c.conf.statePath)
	if err := os.Remove(c.conf.statePath); err != nil {
		c.Ui.Error(fmt.Sprintf("Failed to remove state file '%s': %v",
			c.conf.statePath, err))
		return 1
	}

	// Success!
	c.Ui.Output("Remote state management enabled")
	return 0
}

func (c *RemoteConfigCommand) Help() string {
	helpText := `
Usage: terraform remote [options]

  Configures Terraform to use a remote state server. This allows state
  to be pulled down when necessary and then pushed to the server when
  updated. In this mode, the state file does not need to be stored durably
  since the remote server provides the durability.

Options:

  -backend=Atlas         Specifies the type of remote backend. Must be one
                         of Atlas, Consul, or HTTP. Defaults to Atlas.

  -backend-config="k=v"  Specifies configuration for the remote storage
                         backend. This can be specified multiple times.

  -backup=path           Path to backup the existing state file before
                         modifying. Defaults to the "-state" path with
                         ".backup" extension. Set to "-" to disable backup.

  -disable               Disables remote state management and migrates the state
                         to the -state path.

  -pull=true             Controls if the remote state is pulled before disabling.
                         This defaults to true to ensure the latest state is cached
                         before disabling.

  -state=path            Path to read state. Defaults to "terraform.tfstate"
                         unless remote state is enabled.

`
	return strings.TrimSpace(helpText)
}

func (c *RemoteConfigCommand) Synopsis() string {
	return "Configures remote state management"
}
<commit_msg>command/remote-config: show flag parse errors<commit_after>package command

import (
	"flag"
	"fmt"
	"log"
	"os"
	"strings"

	"github.com/hashicorp/terraform/state"
	"github.com/hashicorp/terraform/state/remote"
	"github.com/hashicorp/terraform/terraform"
)

// remoteCommandConfig is used to encapsulate our configuration
type remoteCommandConfig struct {
	disableRemote bool
	pullOnDisable bool

	statePath  string
	backupPath string
}

// RemoteConfigCommand is a Command implementation that is used to
// enable and disable remote state management
type RemoteConfigCommand struct {
	Meta
	conf       remoteCommandConfig
	remoteConf terraform.RemoteState
}

func (c *RemoteConfigCommand) Run(args []string) int {
	args = c.Meta.process(args, false)
	config := make(map[string]string)
	cmdFlags := flag.NewFlagSet("remote", flag.ContinueOnError)
	cmdFlags.BoolVar(&c.conf.disableRemote, "disable", false, "")
	cmdFlags.BoolVar(&c.conf.pullOnDisable, "pull", true, "")
	cmdFlags.StringVar(&c.conf.statePath, "state", DefaultStateFilename, "path")
	cmdFlags.StringVar(&c.conf.backupPath, "backup", "", "path")
	cmdFlags.StringVar(&c.remoteConf.Type, "backend", "atlas", "")
	cmdFlags.Var((*FlagKV)(&config), "backend-config", "config")
	cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
	if err := cmdFlags.Parse(args); err != nil {
		c.Ui.Error(fmt.Sprintf("\nError parsing CLI flags: %s", err))
		return 1
	}

	// Set the local state path
	c.statePath = c.conf.statePath

	// Populate the various configurations
	c.remoteConf.Config = config

	// Get the state information. We specifically request the cache only
	// for the remote state here because it is possible the remote state
	// is invalid and we don't want to error.
	stateOpts := c.StateOpts()
	stateOpts.RemoteCacheOnly = true
	if _, err := c.StateRaw(stateOpts); err != nil {
		c.Ui.Error(fmt.Sprintf("Error loading local state: %s", err))
		return 1
	}

	// Get the local and remote [cached] state
	localState := c.stateResult.Local.State()
	var remoteState *terraform.State
	if remote := c.stateResult.Remote; remote != nil {
		remoteState = remote.State()
	}

	// Check if remote state is being disabled
	if c.conf.disableRemote {
		if !remoteState.IsRemote() {
			c.Ui.Error(fmt.Sprintf("Remote state management not enabled! Aborting."))
			return 1
		}
		if !localState.Empty() {
			c.Ui.Error(fmt.Sprintf("State file already exists at '%s'. Aborting.",
				c.conf.statePath))
			return 1
		}

		return c.disableRemoteState()
	}

	// Ensure there is no conflict
	haveCache := !remoteState.Empty()
	haveLocal := !localState.Empty()
	switch {
	case haveCache && haveLocal:
		c.Ui.Error(fmt.Sprintf("Remote state is enabled, but non-managed state file '%s' is also present!",
			c.conf.statePath))
		return 1

	case !haveCache && !haveLocal:
		// If we don't have either state file, initialize a blank state file
		return c.initBlankState()

	case haveCache && !haveLocal:
		// Update the remote state target potentially
		return c.updateRemoteConfig()

	case !haveCache && haveLocal:
		// Enable remote state management
		return c.enableRemoteState()
	}

	panic("unhandled case")
}

// disableRemoteState is used to disable remote state management,
// and move the state file into place.
func (c *RemoteConfigCommand) disableRemoteState() int {
	if c.stateResult == nil {
		c.Ui.Error(fmt.Sprintf(
			"Internal error. State() must be called internally before remote\n" +
				"state can be disabled. Please report this as a bug."))
		return 1
	}
	if !c.stateResult.State.State().IsRemote() {
		c.Ui.Error(fmt.Sprintf(
			"Remote state is not enabled. Can't disable remote state."))
		return 1
	}
	local := c.stateResult.Local
	remote := c.stateResult.Remote

	// Ensure we have the latest state before disabling
	if c.conf.pullOnDisable {
		log.Printf("[INFO] Refreshing local state from remote server")
		if err := remote.RefreshState(); err != nil {
			c.Ui.Error(fmt.Sprintf(
				"Failed to refresh from remote state: %s", err))
			return 1
		}

		// Exit if we were unable to update
		if change := remote.RefreshResult(); !change.SuccessfulPull() {
			c.Ui.Error(fmt.Sprintf("%s", change))
			return 1
		} else {
			log.Printf("[INFO] %s", change)
		}
	}

	// Clear the remote management, and copy into place
	newState := remote.State()
	newState.Remote = nil
	if err := local.WriteState(newState); err != nil {
		c.Ui.Error(fmt.Sprintf("Failed to encode state file '%s': %s",
			c.conf.statePath, err))
		return 1
	}
	if err := local.PersistState(); err != nil {
		c.Ui.Error(fmt.Sprintf("Failed to encode state file '%s': %s",
			c.conf.statePath, err))
		return 1
	}

	// Remove the old state file
	if err := os.Remove(c.stateResult.RemotePath); err != nil {
		c.Ui.Error(fmt.Sprintf("Failed to remove the local state file: %v", err))
		return 1
	}

	return 0
}

// validateRemoteConfig is used to verify that the remote configuration
// we have is valid
func (c *RemoteConfigCommand) validateRemoteConfig() error {
	conf := c.remoteConf
	_, err := remote.NewClient(conf.Type, conf.Config)
	if err != nil {
		c.Ui.Error(fmt.Sprintf(
			"%s\n\n"+
				"If the error message above mentions requiring or modifying configuration\n"+
				"options, these are set using the `-backend-config` flag. Example:\n"+
				"-backend-config=\"name=foo\" to set the `name` configuration",
			err))
	}
	return err
}

// initBlank state is used to initialize a blank state that is
// remote enabled
func (c *RemoteConfigCommand) initBlankState() int {
	// Validate the remote configuration
	if err := c.validateRemoteConfig(); err != nil {
		return 1
	}

	// Make a blank state, attach the remote configuration
	blank := terraform.NewState()
	blank.Remote = &c.remoteConf

	// Persist the state
	remote := &state.LocalState{Path: c.stateResult.RemotePath}
	if err := remote.WriteState(blank); err != nil {
		c.Ui.Error(fmt.Sprintf("Failed to initialize state file: %v", err))
		return 1
	}
	if err := remote.PersistState(); err != nil {
		c.Ui.Error(fmt.Sprintf("Failed to initialize state file: %v", err))
		return 1
	}

	// Success!
	c.Ui.Output("Initialized blank state with remote state enabled!")
	return 0
}

// updateRemoteConfig is used to update the configuration of the
// remote state store
func (c *RemoteConfigCommand) updateRemoteConfig() int {
	// Validate the remote configuration
	if err := c.validateRemoteConfig(); err != nil {
		return 1
	}

	// Read in the local state, which is just the cache of the remote state
	remote := c.stateResult.Remote.Cache

	// Update the configuration
	state := remote.State()
	state.Remote = &c.remoteConf
	if err := remote.WriteState(state); err != nil {
		c.Ui.Error(fmt.Sprintf("%s", err))
		return 1
	}
	if err := remote.PersistState(); err != nil {
		c.Ui.Error(fmt.Sprintf("%s", err))
		return 1
	}

	// Success!
	c.Ui.Output("Remote configuration updated")
	return 0
}

// enableRemoteState is used to enable remote state management
// and to move a state file into place
func (c *RemoteConfigCommand) enableRemoteState() int {
	// Validate the remote configuration
	if err := c.validateRemoteConfig(); err != nil {
		return 1
	}

	// Read the local state
	local := c.stateResult.Local
	if err := local.RefreshState(); err != nil {
		c.Ui.Error(fmt.Sprintf("Failed to read local state: %s", err))
		return 1
	}

	// Backup the state file before we modify it
	backupPath := c.conf.backupPath
	if backupPath != "-" {
		// Provide default backup path if none provided
		if backupPath == "" {
			backupPath = c.conf.statePath + DefaultBackupExtention
		}

		log.Printf("[INFO] Writing backup state to: %s", backupPath)
		backup := &state.LocalState{Path: backupPath}
		if err := backup.WriteState(local.State()); err != nil {
			c.Ui.Error(fmt.Sprintf("Error writing backup state file: %s", err))
			return 1
		}
		if err := backup.PersistState(); err != nil {
			c.Ui.Error(fmt.Sprintf("Error writing backup state file: %s", err))
			return 1
		}
	}

	// Update the local configuration, move into place
	state := local.State()
	state.Remote = &c.remoteConf
	remote := c.stateResult.Remote
	if err := remote.WriteState(state); err != nil {
		c.Ui.Error(fmt.Sprintf("%s", err))
		return 1
	}
	if err := remote.PersistState(); err != nil {
		c.Ui.Error(fmt.Sprintf("%s", err))
		return 1
	}

	// Remove the original, local state file
	log.Printf("[INFO] Removing state file: %s", c.conf.statePath)
	if err := os.Remove(c.conf.statePath); err != nil {
		c.Ui.Error(fmt.Sprintf("Failed to remove state file '%s': %v",
			c.conf.statePath, err))
		return 1
	}

	// Success!
	c.Ui.Output("Remote state management enabled")
	return 0
}

func (c *RemoteConfigCommand) Help() string {
	helpText := `
Usage: terraform remote [options]

  Configures Terraform to use a remote state server. This allows state
  to be pulled down when necessary and then pushed to the server when
  updated. In this mode, the state file does not need to be stored durably
  since the remote server provides the durability.

Options:

  -backend=Atlas         Specifies the type of remote backend. Must be one
                         of Atlas, Consul, or HTTP. Defaults to Atlas.

  -backend-config="k=v"  Specifies configuration for the remote storage
                         backend. This can be specified multiple times.

  -backup=path           Path to backup the existing state file before
                         modifying. Defaults to the "-state" path with
                         ".backup" extension. Set to "-" to disable backup.

  -disable               Disables remote state management and migrates the state
                         to the -state path.

  -pull=true             Controls if the remote state is pulled before disabling.
                         This defaults to true to ensure the latest state is cached
                         before disabling.

  -state=path            Path to read state. Defaults to "terraform.tfstate"
                         unless remote state is enabled.

`
	return strings.TrimSpace(helpText)
}

func (c *RemoteConfigCommand) Synopsis() string {
	return "Configures remote state management"
}
<|endoftext|>


<commit_before>package command

import (
	"fmt"

	"github.com/Sirupsen/logrus"
	"github.com/mitchellh/cli"
	v1payload "github.com/nerdalize/nerd/nerd/client/batch/v1/payload"
	"github.com/pkg/errors"
)

// SecretCreateOpts describes the options to the SecretCreate command
type SecretCreateOpts struct {
	DockerServer   string `long:"docker-server" default:"" default-mask:"" description:"https://index.docker.io/v1/': Server location for Docker registry"`
	DockerUsername string `long:"docker-username" default:"" default-mask:"" description:"Username for Docker registry authentication"`
	DockerPassword string `long:"docker-password" default:"" default-mask:"" description:"Password for Docker registry authentication"`
	DockerEmail    string `long:"docker-email" default:"" default-mask:"" description:"email for Docker registry"`
}

//SecretCreate command
type SecretCreate struct {
	*command
	opts *SecretCreateOpts
}

//SecretCreateFactory returns a factory method for the join command
func SecretCreateFactory() (cli.Command, error) {
	opts := &SecretCreateOpts{}
	comm, err := newCommand("nerd secret create <name> [key] [value]", "create secrets to be used by workers", "", opts)
	if err != nil {
		return nil, errors.Wrap(err, "failed to create command")
	}
	cmd := &SecretCreate{
		command: comm,
	}
	cmd.runFunc = cmd.DoRun

	return cmd, nil
}

//DoRun is called by run and allows an error to be returned
func (cmd *SecretCreate) DoRun(args []string) (err error) {
	isPullSecret := cmd.opts.DockerServer == "" ||
		cmd.opts.DockerUsername == "" ||
		cmd.opts.DockerPassword == "" ||
		cmd.opts.DockerEmail == ""

	if len(args) < 3 && !isPullSecret {
		return fmt.Errorf("not enough arguments, see --help")
	} else if len(args) < 1 {
		return fmt.Errorf("please provide a pull secret name")
	}

	bclient, err := NewClient(cmd.ui, cmd.config, cmd.session)
	if err != nil {
		HandleError(err)
	}

	ss, err := cmd.session.Read()
	if err != nil {
		HandleError(err)
	}

	var out *v1payload.CreateSecretOutput
	if isPullSecret {
		out, err = bclient.CreatePullSecret(ss.Project.Name,
			args[0],
			cmd.opts.DockerServer,
			cmd.opts.DockerUsername,
			cmd.opts.DockerPassword,
			cmd.opts.DockerEmail)
		if err != nil {
			HandleError(err)
		}
	} else {
		out, err = bclient.CreateSecret(ss.Project.Name, args[0], args[1], args[2])
		if err != nil {
			HandleError(err)
		}
	}

	logrus.Infof("Secret Creation: %v", out)
	return nil
}
<commit_msg>Fix logic bug<commit_after>package command

import (
	"fmt"

	"github.com/Sirupsen/logrus"
	"github.com/mitchellh/cli"
	v1payload "github.com/nerdalize/nerd/nerd/client/batch/v1/payload"
	"github.com/pkg/errors"
)

// SecretCreateOpts describes the options to the SecretCreate command
type SecretCreateOpts struct {
	DockerServer   string `long:"docker-server" default:"" default-mask:"" description:"https://index.docker.io/v1/': Server location for Docker registry"`
	DockerUsername string `long:"docker-username" default:"" default-mask:"" description:"Username for Docker registry authentication"`
	DockerPassword string `long:"docker-password" default:"" default-mask:"" description:"Password for Docker registry authentication"`
	DockerEmail    string `long:"docker-email" default:"" default-mask:"" description:"email for Docker registry"`
}

//SecretCreate command
type SecretCreate struct {
	*command
	opts *SecretCreateOpts
}

//SecretCreateFactory returns a factory method for the join command
func SecretCreateFactory() (cli.Command, error) {
	opts := &SecretCreateOpts{}
	comm, err := newCommand("nerd secret create <name> [key] [value]", "create secrets to be used by workers", "", opts)
	if err != nil {
		return nil, errors.Wrap(err, "failed to create command")
	}
	cmd := &SecretCreate{
		command: comm,
		opts:    opts,
	}
	cmd.runFunc = cmd.DoRun

	return cmd, nil
}

//DoRun is called by run and allows an error to be returned
func (cmd *SecretCreate) DoRun(args []string) (err error) {
	isPullSecret := cmd.opts.DockerServer != "" &&
		cmd.opts.DockerUsername != "" &&
		cmd.opts.DockerPassword != "" &&
		cmd.opts.DockerEmail != ""

	if len(args) < 3 && !isPullSecret {
		return fmt.Errorf("not enough arguments, see --help")
	} else if len(args) < 1 {
		return fmt.Errorf("please provide a pull secret name")
	}

	bclient, err := NewClient(cmd.ui, cmd.config, cmd.session)
	if err != nil {
		HandleError(err)
	}

	ss, err := cmd.session.Read()
	if err != nil {
		HandleError(err)
	}

	var out *v1payload.CreateSecretOutput
	if isPullSecret {
		out, err = bclient.CreatePullSecret(ss.Project.Name,
			args[0],
			cmd.opts.DockerServer,
			cmd.opts.DockerUsername,
			cmd.opts.DockerPassword,
			cmd.opts.DockerEmail)
		if err != nil {
			HandleError(err)
		}
	} else {
		out, err = bclient.CreateSecret(ss.Project.Name, args[0], args[1], args[2])
		if err != nil {
			HandleError(err)
		}
	}

	logrus.Infof("Secret Creation: %v", out)
	return nil
}
<|endoftext|>


<commit_before>/*
Copyright 2014 Workiva, LLC

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 futures is useful for broadcasting an identical message to a multitude
of listeners as opposed to channels which will choose a listener at random
if multiple listeners are listening to the same channel.  The future will
also cache the result so any future interest will be immediately returned
to the consumer.
*/
package futures

import (
	"fmt"
	"sync"
	"time"
)

// Completer is a channel that the future expects to receive
// a result on.  The future only receives on this channel.
type Completer <-chan interface{}

// Future represents an object that can be used to perform asynchronous
// tasks.  The constructor of the future will complete it, and listeners
// will block on getresult until a result is received.  This is different
// from a channel in that the future is only completed once, and anyone
// listening on the future will get the result, regardless of the number
// of listeners.
type Future struct {
	triggered bool // because item can technically be nil and still be valid
	item      interface{}
	err       error
	lock      sync.Mutex
	wg        sync.WaitGroup
}

// GetResult will immediately fetch the result if it exists
// or wait on the result until it is ready.
func (f *Future) GetResult() (interface{}, error) {
	f.lock.Lock()
	if f.triggered {
		f.lock.Unlock()
		return f.item, f.err
	}
	f.lock.Unlock()

	f.wg.Wait()
	return f.item, f.err
}

func (f *Future) setItem(item interface{}, err error) {
	f.lock.Lock()
	f.triggered = true
	f.item = item
	f.err = err
	f.lock.Unlock()
	f.wg.Done()
}

func listenForResult(f *Future, ch Completer, timeout time.Duration, wg *sync.WaitGroup) {
	wg.Done()
	select {
	case item := <-ch:
		f.setItem(item, nil)
	case <-time.After(timeout):
		f.setItem(nil, fmt.Errorf(`Timeout after %f seconds.`, timeout.Seconds()))
	}
}

// New is the constructor to generate a new future.  Pass the completed
// item to the toComplete channel and any listeners will get
// notified.  If timeout is hit before toComplete is called,
// any listeners will get passed an error.
func New(completer Completer, timeout time.Duration) *Future {
	f := &Future{}
	f.wg.Add(1)
	var wg sync.WaitGroup
	wg.Add(1)
	go listenForResult(f, completer, timeout, &wg)
	wg.Wait()
	return f
}
<commit_msg>Add an explicit timer and stop it after we get the result we want to aid GC.<commit_after>/*
Copyright 2014 Workiva, LLC

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 futures is useful for broadcasting an identical message to a multitude
of listeners as opposed to channels which will choose a listener at random
if multiple listeners are listening to the same channel.  The future will
also cache the result so any future interest will be immediately returned
to the consumer.
*/
package futures

import (
	"fmt"
	"sync"
	"time"
)

// Completer is a channel that the future expects to receive
// a result on.  The future only receives on this channel.
type Completer <-chan interface{}

// Future represents an object that can be used to perform asynchronous
// tasks.  The constructor of the future will complete it, and listeners
// will block on getresult until a result is received.  This is different
// from a channel in that the future is only completed once, and anyone
// listening on the future will get the result, regardless of the number
// of listeners.
type Future struct {
	triggered bool // because item can technically be nil and still be valid
	item      interface{}
	err       error
	lock      sync.Mutex
	wg        sync.WaitGroup
}

// GetResult will immediately fetch the result if it exists
// or wait on the result until it is ready.
func (f *Future) GetResult() (interface{}, error) {
	f.lock.Lock()
	if f.triggered {
		f.lock.Unlock()
		return f.item, f.err
	}
	f.lock.Unlock()

	f.wg.Wait()
	return f.item, f.err
}

func (f *Future) setItem(item interface{}, err error) {
	f.lock.Lock()
	f.triggered = true
	f.item = item
	f.err = err
	f.lock.Unlock()
	f.wg.Done()
}

func listenForResult(f *Future, ch Completer, timeout time.Duration, wg *sync.WaitGroup) {
	wg.Done()
	t := time.NewTimer(timeout)
	select {
	case item := <-ch:
		f.setItem(item, nil)
		t.Stop() // we want to trigger GC of this timer as soon as it's no longer needed
	case <-t.C:
		f.setItem(nil, fmt.Errorf(`timeout after %f seconds`, timeout.Seconds()))
	}
}

// New is the constructor to generate a new future.  Pass the completed
// item to the toComplete channel and any listeners will get
// notified.  If timeout is hit before toComplete is called,
// any listeners will get passed an error.
func New(completer Completer, timeout time.Duration) *Future {
	f := &Future{}
	f.wg.Add(1)
	var wg sync.WaitGroup
	wg.Add(1)
	go listenForResult(f, completer, timeout, &wg)
	wg.Wait()
	return f
}
<|endoftext|>


<commit_before>package commands

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

// retriveUserInput is a function that can retrive user input in form of string. By default,
// it will prompt the user. In test, you can replace this with code that returns the appropriate response.
var retrieveUserInput = func(message string) (string, error) {
	reader := bufio.NewReader(os.Stdin)
	warnConfirm("Are you sure you want to " + message + " (y/N) ? ")
	answer, err := reader.ReadString('\n')
	if err != nil {
		return "", err
	}
	return strings.ToLower(strings.Replace(answer, "\n", "", 1)), nil
}

// AskForConfirm parses and verifies user input for confirmation.
func AskForConfirm(message string) error {
	answer, err := retrieveUserInput(message)
	if err != nil {
		return fmt.Errorf("unable to parse users input: %s", err)
	}

	if answer != "y" && answer != "ye" && answer != "yes" {
		return fmt.Errorf("invalid user input")
	}

	return nil
}
<commit_msg>confirmation: fix confirmation behavior on windows cmd and powershell<commit_after>package commands

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

// retriveUserInput is a function that can retrive user input in form of string. By default,
// it will prompt the user. In test, you can replace this with code that returns the appropriate response.
var retrieveUserInput = func(message string) (string, error) {
	reader := bufio.NewReader(os.Stdin)
	warnConfirm("Are you sure you want to " + message + " (y/N) ? ")
	answer, err := reader.ReadString('\n')
	if err != nil {
		return "", err
	}

	answer = strings.Replace(answer, "\r", "", 1)
	answer = strings.Replace(answer, "\n", "", 1)

	return strings.ToLower(answer), nil
}

// AskForConfirm parses and verifies user input for confirmation.
func AskForConfirm(message string) error {
	answer, err := retrieveUserInput(message)
	if err != nil {
		return fmt.Errorf("unable to parse users input: %s", err)
	}

	if answer != "y" && answer != "ye" && answer != "yes" {
		return fmt.Errorf("invalid user input")
	}

	return nil
}
<|endoftext|>


<commit_before>package linedb

import (
	"bytes"
	"fmt"
	"io"
	"regexp"
	"strconv"
	"strings"
	"unicode"
	"unicode/utf8"
)

type encoderState int

const (
	encoderNewElem encoderState = 1 << iota
	encoderScalar
	encoderRowStart
	encoderRowAfterStart
)

type Encoder struct {
	state             encoderState
	error             error
	writer            io.Writer
	buffer            []byte
	tableFirstRowSize int
	tableRowSize      int
}

func NewByteEncoder() *Encoder {
	return NewEncoder(nil)
}

func NewEncoder(writer io.Writer) *Encoder {
	return &Encoder{
		state:  encoderNewElem,
		writer: writer,
		buffer: make([]byte, 0, 1024),
	}
}

var validNamePattern = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z_0-9]*$`)

func isValidName(name string) bool {
	return validNamePattern.MatchString(name)
}

func checkValidName(name string) {
	if !isValidName(name) {
		panic(fmt.Errorf("'%s' does not match %s, the pattern for valid linedb names", name, validNamePattern))
	}
}

func (e *Encoder) checkState(stateBitset encoderState) {
	if e.state&stateBitset == 0 {
		panic(fmt.Errorf("unexpected state %d", e.state))
	}
}

func (e *Encoder) GetError() error {
	return e.error
}

func (e *Encoder) GetBytes() []byte {
	if e.writer != nil {
		panic("GetBytes can only be used with encoder without a Writer")
	}
	return e.buffer
}

func (e *Encoder) Flush() {
	e.checkState(encoderNewElem)
	if e.writer != nil && len(e.buffer) != 0 && e.error == nil {
		_, e.error = e.writer.Write(e.buffer)
		e.buffer = e.buffer[:0]
	}
}

func (e *Encoder) EmptyLine() {
	e.checkState(encoderNewElem)
	e.addLineEnd()
}

func (e *Encoder) Comment(text string) {
	if strings.IndexAny(text, "\r\n") >= 0 {
		panic("comment string cannoy contain line break chars")
	}
	e.checkState(encoderNewElem)
	e.buffer = append(e.buffer, "# "...)
	e.buffer = append(e.buffer, text...)
	e.addLineEnd()
}

func (e *Encoder) Scalar(name string) *Encoder {
	e.checkState(encoderNewElem)
	e.buffer = append(e.buffer, name...)
	e.buffer = append(e.buffer, ' ')
	e.state = encoderScalar
	return e
}

func (e *Encoder) Table(name string) {
	e.checkState(encoderNewElem)
	e.buffer = append(e.buffer, "@table "...)
	e.buffer = append(e.buffer, name...)
	e.addLineEnd()
	e.state = encoderRowStart
	e.tableFirstRowSize = -1
	e.tableRowSize = 0
}

func (e *Encoder) EndRow() {
	if e.state == encoderRowStart {
		panic("table cannot have empty rows")
	} else {
		e.checkState(encoderRowAfterStart)
	}
	if e.tableFirstRowSize < 0 {
		e.tableFirstRowSize = e.tableRowSize
	} else if e.tableFirstRowSize != e.tableRowSize {
		panic("Attempt to write a table row with less elements than in the first row")
	}
	e.addLineEnd()
	e.tableRowSize = 0
	e.state = encoderRowStart
}

func (e *Encoder) EndTable() {
	if e.state == encoderRowAfterStart {
		panic("missing EndRow call")
	} else {
		e.checkState(encoderRowStart)
	}
	e.buffer = append(e.buffer, "@end"...)
	e.addLineEnd()
	e.state = encoderNewElem
}

func (e *Encoder) AddInt(i int) *Encoder {
	return e.AddInt64(int64(i))
}

func (e *Encoder) AddInt64(i int64) *Encoder {
	e.beforeValueWrite()
	e.buffer = strconv.AppendInt(e.buffer, i, 10)
	e.afterValueWrite()
	return e
}

func (e *Encoder) AddString(s string) *Encoder {
	e.beforeValueWrite()
	e.buffer = strconv.AppendQuote(e.buffer, s)
	e.afterValueWrite()
	return e
}

func (e *Encoder) addLineEnd() {
	e.buffer = append(e.buffer, '\n')
	if e.writer != nil && len(e.buffer) > 4096 && e.error == nil {
		_, e.error = e.writer.Write(e.buffer)
		e.buffer = e.buffer[:0]
	}
}

func (e *Encoder) beforeValueWrite() {
	if e.state == encoderRowAfterStart {
		e.buffer = append(e.buffer, ' ')
	} else if e.state == encoderRowStart {
		e.state = encoderRowAfterStart
	} else {
		e.checkState(encoderScalar)
	}
}

func (e *Encoder) afterValueWrite() {
	if e.state == encoderScalar {
		e.addLineEnd()
		e.state = encoderNewElem
	} else if e.state == encoderRowAfterStart {
		e.tableRowSize++
		if e.tableFirstRowSize >= 0 && e.tableFirstRowSize < e.tableRowSize {
			panic("Attempt to write more table row elements than in the first row")
		}
	}
}

type ItemKind int

const (
	NoItemKind ItemKind = iota
	ScalarItem
	TableItem
)

type Decoder struct {
	ItemKind
	ItemName     string
	error        error
	data         []byte
	currentLine  []byte
	insideScalar bool
	insideRow    bool
	rowCounter   int
}

func NewByteDecoder(data []byte) *Decoder {
	return &Decoder{
		data: data,
	}
}

func (d *Decoder) GetError() error {
	return d.error
}

func (d *Decoder) NextItem() bool {
	if d.error != nil {
		return false
	}
	if !d.readLine() {
		return false
	}
	token := d.nextCharsWithoutSpace()
	if token[0] == '@' {
		if string(token) != "@table" {
			d.error = fmt.Errorf("Unknown line keyword '%s'", token)
			return false
		}
		if len(d.currentLine) == 0 {
			d.error = fmt.Errorf("%s is not followed by name", token)
			return false
		}
		name := d.nextCharsWithoutSpace()
		if !isValidName(d.ItemName) {
			d.error = fmt.Errorf("%s %s is not a valid table name", token, name)
			return false
		}
		if len(d.currentLine) != 0 {
			d.error = fmt.Errorf("unexpected extra characters after %s %s", token, name)
			return false
		}
		d.ItemKind = TableItem
		d.ItemName = string(name)
		d.rowCounter = 0
		return true
	}
	d.ItemName = string(token)
	if !isValidName(d.ItemName) {
		d.error = fmt.Errorf("'%s' is not a valid scalar name", token)
		return false
	}
	if len(d.currentLine) == 0 {
		d.error = fmt.Errorf("scalar %s is not followed by a value", token)
		return false
	}
	d.ItemKind = ScalarItem
	d.insideScalar = true
	return true
}

func (d *Decoder) RowCounter() int {
	if d.ItemKind != TableItem {
		panic("call outside table context")
	}
	return d.rowCounter
}

func (d *Decoder) NextRow() bool {
	if d.ItemKind != TableItem {
		panic("call outside table context")
	}
	if len(d.currentLine) != 0 {
		d.error = fmt.Errorf("Unread row element")
		return false
	}
	if !d.readLine() {
		if d.error == nil {
			d.error = fmt.Errorf("Unterminated table")
		}
		return false
	}
	if d.currentLine[0] == '@' {
		token := d.nextCharsWithoutSpace()
		if string(token) != "@end" || len(d.currentLine) != 0 {
			d.error = fmt.Errorf("invalid table terminator format")
		}
		d.insideRow = false
		d.ItemKind = NoItemKind
		return false
	}
	d.insideRow = true
	d.rowCounter++
	return true
}

func (d *Decoder) GetInt() int {
	i64 := d.GetInt64()
	i := int(i64)
	if int64(i) != i64 {
		d.error = fmt.Errorf("%d is outside int range", i64)
		i = 0
	}
	return i
}

func (d *Decoder) GetInt64() int64 {
	if !d.beforeValueRead() {
		return 0
	}
	token := d.nextCharsWithoutSpace()
	i, err := strconv.ParseInt(string(token), 10, 64)
	if err != nil {
		d.error = err
		return 0
	}
	d.afterValueRead()
	return i
}

func (d *Decoder) GetString() string {
	if !d.beforeValueRead() {
		return ""
	}
	if d.currentLine[0] != '"' {
		d.error = fmt.Errorf("String value must strt with \"")
		return ""
	}

	// Find the terminating quote
	i := 1
	for {
		if i == len(d.currentLine) {
			d.error = fmt.Errorf("unterminated string literal")
			return ""
		}
		if d.currentLine[i] == '"' {
			break
		}
		if d.currentLine[i] == '\\' {
			i++
			if i == len(d.currentLine) {
				d.error = fmt.Errorf("unterminated string literal")
				return ""
			}
		}
		r, n := utf8.DecodeRune(d.currentLine[i:])
		if r == utf8.RuneError {
			d.error = fmt.Errorf("string literal contains invalid utf-8, use \\x escape to represent arbitrary binary")
			return ""
		}
		i += n
	}
	s := string(d.currentLine[0 : i+1])
	d.currentLine = d.currentLine[i+1:]
	d.skipLineWhitespace()

	s, d.error = strconv.Unquote(s)
	if d.error != nil {
		return ""
	}
	d.afterValueRead()
	return s
}

// find next non-empty line that is not a comment.
func (d *Decoder) readLine() bool {
	if d.error != nil {
		return false
	}
	for len(d.data) != 0 {
		i := bytes.IndexByte(d.data, '\n')
		if i < 0 {
			d.currentLine = d.data
			d.data = nil
		} else {
			d.currentLine = d.data[0:i]
			d.data = d.data[i+1:]
		}
		d.skipLineWhitespace()

		// Ignore empty line or comments
		if len(d.currentLine) != 0 && d.currentLine[0] != '#' {
			return true
		}
	}
	return false
}

func (d *Decoder) beforeValueRead() bool {
	if d.error != nil {
		return false
	}
	if !d.insideScalar && !d.insideRow {
		panic("Can only be called for scalar or row")
	}
	if len(d.currentLine) == 0 {
		d.error = fmt.Errorf("unexpected line end while looking for value")
		return false
	}
	return true
}

func (d *Decoder) afterValueRead() {
	if d.error != nil {
		return
	}
	if d.insideScalar {
		if len(d.currentLine) != 0 {
			d.error = fmt.Errorf("unexpected extra characters after scalar value")
			return
		}
		d.insideScalar = false
		d.ItemKind = NoItemKind
	}
}

func (d *Decoder) skipLineWhitespace() {
	d.currentLine = bytes.TrimLeftFunc(d.currentLine, unicode.IsSpace)
}

func (d *Decoder) nextCharsWithoutSpace() []byte {
	i := bytes.IndexFunc(d.currentLine, unicode.IsSpace)
	var s []byte
	if i < 0 {
		s = d.currentLine
		d.currentLine = nil
		return s
	}
	s = d.currentLine[0:i]
	d.currentLine = d.currentLine[i+1:]
	d.skipLineWhitespace()
	return s
}
<commit_msg>allow unquoted string values in linedb<commit_after>package linedb

import (
	"bytes"
	"fmt"
	"io"
	"regexp"
	"strconv"
	"strings"
	"unicode"
	"unicode/utf8"
)

type encoderState int

const (
	encoderNewElem encoderState = 1 << iota
	encoderScalar
	encoderRowStart
	encoderRowAfterStart
)

type Encoder struct {
	state             encoderState
	error             error
	writer            io.Writer
	buffer            []byte
	tableFirstRowSize int
	tableRowSize      int
}

func NewByteEncoder() *Encoder {
	return NewEncoder(nil)
}

func NewEncoder(writer io.Writer) *Encoder {
	return &Encoder{
		state:  encoderNewElem,
		writer: writer,
		buffer: make([]byte, 0, 1024),
	}
}

var validNamePattern = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z_0-9]*$`)

func isValidName(name string) bool {
	return validNamePattern.MatchString(name)
}

func checkValidName(name string) {
	if !isValidName(name) {
		panic(fmt.Errorf("'%s' does not match %s, the pattern for valid linedb names", name, validNamePattern))
	}
}

func (e *Encoder) checkState(stateBitset encoderState) {
	if e.state&stateBitset == 0 {
		panic(fmt.Errorf("unexpected state %d", e.state))
	}
}

func (e *Encoder) GetError() error {
	return e.error
}

func (e *Encoder) GetBytes() []byte {
	if e.writer != nil {
		panic("GetBytes can only be used with encoder without a Writer")
	}
	return e.buffer
}

func (e *Encoder) Flush() {
	e.checkState(encoderNewElem)
	if e.writer != nil && len(e.buffer) != 0 && e.error == nil {
		_, e.error = e.writer.Write(e.buffer)
		e.buffer = e.buffer[:0]
	}
}

func (e *Encoder) EmptyLine() {
	e.checkState(encoderNewElem)
	e.addLineEnd()
}

func (e *Encoder) Comment(text string) {
	if strings.IndexAny(text, "\r\n") >= 0 {
		panic("comment string cannoy contain line break chars")
	}
	e.checkState(encoderNewElem)
	e.buffer = append(e.buffer, "# "...)
	e.buffer = append(e.buffer, text...)
	e.addLineEnd()
}

func (e *Encoder) Scalar(name string) *Encoder {
	e.checkState(encoderNewElem)
	e.buffer = append(e.buffer, name...)
	e.buffer = append(e.buffer, ' ')
	e.state = encoderScalar
	return e
}

func (e *Encoder) Table(name string) {
	e.checkState(encoderNewElem)
	e.buffer = append(e.buffer, "@table "...)
	e.buffer = append(e.buffer, name...)
	e.addLineEnd()
	e.state = encoderRowStart
	e.tableFirstRowSize = -1
	e.tableRowSize = 0
}

func (e *Encoder) EndRow() {
	if e.state == encoderRowStart {
		panic("table cannot have empty rows")
	} else {
		e.checkState(encoderRowAfterStart)
	}
	if e.tableFirstRowSize < 0 {
		e.tableFirstRowSize = e.tableRowSize
	} else if e.tableFirstRowSize != e.tableRowSize {
		panic("Attempt to write a table row with less elements than in the first row")
	}
	e.addLineEnd()
	e.tableRowSize = 0
	e.state = encoderRowStart
}

func (e *Encoder) EndTable() {
	if e.state == encoderRowAfterStart {
		panic("missing EndRow call")
	} else {
		e.checkState(encoderRowStart)
	}
	e.buffer = append(e.buffer, "@end"...)
	e.addLineEnd()
	e.state = encoderNewElem
}

func (e *Encoder) AddInt(i int) *Encoder {
	return e.AddInt64(int64(i))
}

func (e *Encoder) AddInt64(i int64) *Encoder {
	e.beforeValueWrite()
	e.buffer = strconv.AppendInt(e.buffer, i, 10)
	e.afterValueWrite()
	return e
}

func (e *Encoder) AddString(s string) *Encoder {
	e.beforeValueWrite()
	shouldQuote := true
	if s != "" {
		firstRune, _ := utf8.DecodeRuneInString(s)
		if unicode.IsLetter(firstRune) || firstRune == '_' {
			if strings.IndexFunc(s, unicode.IsSpace) < 0 {
				e.buffer = append(e.buffer, s...)
				shouldQuote = false
			}
		}
	}
	if shouldQuote {
		e.buffer = strconv.AppendQuote(e.buffer, s)
	}
	e.afterValueWrite()
	return e
}

func (e *Encoder) addLineEnd() {
	e.buffer = append(e.buffer, '\n')
	if e.writer != nil && len(e.buffer) > 4096 && e.error == nil {
		_, e.error = e.writer.Write(e.buffer)
		e.buffer = e.buffer[:0]
	}
}

func (e *Encoder) beforeValueWrite() {
	if e.state == encoderRowAfterStart {
		e.buffer = append(e.buffer, ' ')
	} else if e.state == encoderRowStart {
		e.state = encoderRowAfterStart
	} else {
		e.checkState(encoderScalar)
	}
}

func (e *Encoder) afterValueWrite() {
	if e.state == encoderScalar {
		e.addLineEnd()
		e.state = encoderNewElem
	} else if e.state == encoderRowAfterStart {
		e.tableRowSize++
		if e.tableFirstRowSize >= 0 && e.tableFirstRowSize < e.tableRowSize {
			panic("Attempt to write more table row elements than in the first row")
		}
	}
}

type ItemKind int

const (
	NoItemKind ItemKind = iota
	ScalarItem
	TableItem
)

type Decoder struct {
	ItemKind
	ItemName     string
	error        error
	data         []byte
	currentLine  []byte
	insideScalar bool
	insideRow    bool
	atRowStart   bool
	rowCounter   int
}

func NewByteDecoder(data []byte) *Decoder {
	return &Decoder{
		data: data,
	}
}

func (d *Decoder) GetError() error {
	return d.error
}

func (d *Decoder) NextItem() bool {
	if d.error != nil {
		return false
	}
	if !d.readLine() {
		return false
	}
	token := d.nextCharsWithoutSpace()
	if token[0] == '@' {
		if string(token) != "@table" {
			d.error = fmt.Errorf("Unknown line keyword '%s'", token)
			return false
		}
		if len(d.currentLine) == 0 {
			d.error = fmt.Errorf("%s is not followed by name", token)
			return false
		}
		name := d.nextCharsWithoutSpace()
		if !isValidName(d.ItemName) {
			d.error = fmt.Errorf("%s %s is not a valid table name", token, name)
			return false
		}
		if len(d.currentLine) != 0 {
			d.error = fmt.Errorf("unexpected extra characters after %s %s", token, name)
			return false
		}
		d.ItemKind = TableItem
		d.ItemName = string(name)
		d.rowCounter = 0
		return true
	}
	d.ItemName = string(token)
	if !isValidName(d.ItemName) {
		d.error = fmt.Errorf("'%s' is not a valid scalar name", token)
		return false
	}
	if len(d.currentLine) == 0 {
		d.error = fmt.Errorf("scalar %s is not followed by a value", token)
		return false
	}
	d.ItemKind = ScalarItem
	d.insideScalar = true
	return true
}

func (d *Decoder) RowCounter() int {
	if d.ItemKind != TableItem {
		panic("call outside table context")
	}
	return d.rowCounter
}

func (d *Decoder) NextRow() bool {
	if d.ItemKind != TableItem {
		panic("call outside table context")
	}

	// If the current line is not read report an error unless we are
	// at the start of the first item. This allows to skip unknown for
	// application tables.
	if len(d.currentLine) != 0 && !d.atRowStart {
		d.error = fmt.Errorf("Unread row element")
		return false
	}
	if !d.readLine() {
		if d.error == nil {
			d.error = fmt.Errorf("Unterminated table")
		}
		return false
	}
	if d.currentLine[0] == '@' {
		token := d.nextCharsWithoutSpace()
		if string(token) != "@end" || len(d.currentLine) != 0 {
			d.error = fmt.Errorf("invalid table terminator format")
		}
		d.insideRow = false
		d.ItemKind = NoItemKind
		return false
	}
	d.insideRow = true
	d.atRowStart = true
	d.rowCounter++
	return true
}

func (d *Decoder) GetInt() int {
	i64 := d.GetInt64()
	i := int(i64)
	if int64(i) != i64 {
		d.error = fmt.Errorf("%d is outside int range", i64)
		i = 0
	}
	return i
}

func (d *Decoder) GetInt64() int64 {
	if !d.beforeValueRead() {
		return 0
	}
	token := d.nextCharsWithoutSpace()
	i, err := strconv.ParseInt(string(token), 10, 64)
	if err != nil {
		d.error = err
		return 0
	}
	d.afterValueRead()
	return i
}

func (d *Decoder) GetString() string {
	if !d.beforeValueRead() {
		return ""
	}
	var s string
	if d.currentLine[0] != '"' {
		firstRune, _ := utf8.DecodeRune(d.currentLine)
		if !unicode.IsLetter(firstRune) && firstRune != '_' {
			d.error = fmt.Errorf("String values must strt with unless they starts with letter or underscore")
			return ""
		}
		s = string(d.nextCharsWithoutSpace())
	} else {
		// Find the terminating quote
		i := 1
		for {
			if i == len(d.currentLine) {
				d.error = fmt.Errorf("unterminated string literal")
				return ""
			}
			if d.currentLine[i] == '"' {
				break
			}
			if d.currentLine[i] == '\\' {
				i++
				if i == len(d.currentLine) {
					d.error = fmt.Errorf("unterminated string literal")
					return ""
				}
			}
			_, n := utf8.DecodeRune(d.currentLine[i:])
			i += n
		}
		s = string(d.currentLine[0 : i+1])
		d.currentLine = d.currentLine[i+1:]
		d.skipLineWhitespace()

		s, d.error = strconv.Unquote(s)
		if d.error != nil {
			return ""
		}
	}
	d.afterValueRead()
	return s
}

// find next non-empty line that is not a comment.
func (d *Decoder) readLine() bool {
	if d.error != nil {
		return false
	}
	for len(d.data) != 0 {
		i := bytes.IndexByte(d.data, '\n')
		if i < 0 {
			d.currentLine = d.data
			d.data = nil
		} else {
			d.currentLine = d.data[0:i]
			d.data = d.data[i+1:]
		}
		if !utf8.Valid(d.currentLine) {
			d.error = fmt.Errorf(
				"input is not a valid UTF8, use string with \\x escapes to encode arbitrary binary data",
			)
			return false
		}
		d.skipLineWhitespace()

		// Ignore empty line or comments
		if len(d.currentLine) != 0 && d.currentLine[0] != '#' {
			return true
		}
	}
	return false
}

func (d *Decoder) beforeValueRead() bool {
	if d.error != nil {
		return false
	}
	if d.insideRow {
		d.atRowStart = false
	} else if !d.insideScalar {
		panic("Can only be called for scalar or row")
	}
	if len(d.currentLine) == 0 {
		d.error = fmt.Errorf("unexpected line end while looking for value")
		return false
	}

	return true
}

func (d *Decoder) afterValueRead() {
	if d.error != nil {
		return
	}
	if d.insideScalar {
		if len(d.currentLine) != 0 {
			d.error = fmt.Errorf("unexpected extra characters after scalar value")
			return
		}
		d.insideScalar = false
		d.ItemKind = NoItemKind
	}
}

func (d *Decoder) skipLineWhitespace() {
	d.currentLine = bytes.TrimLeftFunc(d.currentLine, unicode.IsSpace)
}

func (d *Decoder) nextCharsWithoutSpace() []byte {
	i := bytes.IndexFunc(d.currentLine, unicode.IsSpace)
	var s []byte
	if i < 0 {
		s = d.currentLine
		d.currentLine = nil
		return s
	}
	s = d.currentLine[0:i]
	d.currentLine = d.currentLine[i+1:]
	d.skipLineWhitespace()
	return s
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"crypto/tls"
	"crypto/x509"
	"encoding/json"
	"expvar"
	"flag"
	"fmt"
	"github.com/lhchavez/quark/common"
	"github.com/lhchavez/quark/runner"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"sync"
	"sync/atomic"
	"time"
)

var (
	insecure   = flag.Bool("insecure", false, "Do not use TLS")
	configPath = flag.String("config", "/etc/omegaup/grader/config.json",
		"Grader configuration file")
	globalContext atomic.Value
	ioLock        sync.Mutex
)

func loadContext() error {
	ctx, err := common.NewContext(*configPath)
	if err != nil {
		return err
	}
	globalContext.Store(ctx)
	return nil
}

func main() {
	flag.Parse()

	if err := loadContext(); err != nil {
		panic(err)
	}

	ctx := globalContext.Load().(*common.Context)
	expvar.Publish("config", &globalContext.Load().(*common.Context).Config)
	common.InitInputManager(ctx)
	go runner.PreloadInputs(ctx, &ioLock)
	var client *http.Client
	if *insecure {
		client = http.DefaultClient
	} else {
		cert, err := ioutil.ReadFile(ctx.Config.TLS.CertFile)
		if err != nil {
			panic(err)
		}
		certPool := x509.NewCertPool()
		certPool.AppendCertsFromPEM(cert)
		keyPair, err := tls.LoadX509KeyPair(ctx.Config.TLS.CertFile, ctx.Config.TLS.KeyFile)
		if err != nil {
			panic(err)
		}
		tr := &http.Transport{
			TLSClientConfig: &tls.Config{
				Certificates: []tls.Certificate{keyPair},
				RootCAs:      certPool,
				ClientAuth:   tls.RequireAndVerifyClientCert,
			},
			DisableCompression: true,
		}
		client = &http.Client{Transport: tr}
	}

	baseURL, err := url.Parse(ctx.Config.Runner.GraderURL)
	if err != nil {
		panic(err)
	}

	ctx.Log.Info("omegaUp runner ready to serve")

	var sleepTime int64 = 1

	for {
		if err := processRun(ctx, client, baseURL); err != nil {
			ctx.Log.Error("error grading run", "err", err)
			time.Sleep(time.Duration(sleepTime) * time.Second)
			if sleepTime < 64 {
				sleepTime *= 2
			}
		} else {
			sleepTime = 1
		}
	}
}

// A reader that blocks until the data is available.
// This is used so that the HTTP connection can be established quickly and then
// block until the results are in. This sends a single byte upon connection
// establishment and relies on the fact that all the data it sends is
// JSON-encoded, so it always sends a '{'.
type blockingReader struct {
	hasRead    bool
	reader     io.Reader
	readerChan chan io.Reader
}

func (r *blockingReader) Read(p []byte) (int, error) {
	if r.reader == nil {
		if !r.hasRead {
			r.hasRead = true
			p[0] = '{'
			return 1, nil
		}
		r.reader = <-r.readerChan
		close(r.readerChan)
		// Make sure the first byte was actually a brace. Otherwise raise an error.
		brace := make([]byte, 1)
		if n, err := r.reader.Read(brace); err != nil || n != 1 || brace[0] != '{' {
			return 0, io.ErrUnexpectedEOF
		}
	}
	return r.reader.Read(p)
}

func processRun(ctx *common.Context, client *http.Client, baseURL *url.URL) error {
	requestURL, err := baseURL.Parse("run/request/")
	if err != nil {
		panic(err)
	}
	resp, err := client.Get(requestURL.String())
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	decoder := json.NewDecoder(resp.Body)
	var run common.Run
	if err := decoder.Decode(&run); err != nil {
		return err
	}

	uploadURL, err := baseURL.Parse(fmt.Sprintf("run/%d/results/", run.ID))
	if err != nil {
		return err
	}
	requestBody := &blockingReader{
		readerChan: make(chan io.Reader),
	}
	finished := make(chan error)
	go func() {
		response, err := client.Post(uploadURL.String(), "text/json", requestBody)
		if err != nil {
			finished <- err
		} else {
			response.Body.Close()
			finished <- nil
		}
	}()

	// Make sure no other I/O is being made while we grade this run.
	ioLock.Lock()
	defer ioLock.Unlock()

	input, err := common.DefaultInputManager.Add(run.InputHash,
		runner.NewRunnerInputFactory(&run, client, &ctx.Config))
	if err != nil {
		return err
	}
	defer input.Release()
	result, err := runner.Grade(ctx, client, baseURL, &run, input)
	if err != nil {
		ctx.Log.Error("Error while grading", "err", err)
	}
	var resultBytes bytes.Buffer
	encoder := json.NewEncoder(&resultBytes)
	if err := encoder.Encode(result); err != nil {
		return err
	}
	requestBody.readerChan <- &resultBytes
	return <-finished
}
<commit_msg>Exponential backoff for runner reconnect<commit_after>package main

import (
	"bytes"
	"crypto/tls"
	"crypto/x509"
	"encoding/json"
	"expvar"
	"flag"
	"fmt"
	"github.com/lhchavez/quark/common"
	"github.com/lhchavez/quark/runner"
	"io"
	"io/ioutil"
	"math/rand"
	"net/http"
	"net/url"
	"sync"
	"sync/atomic"
	"time"
)

var (
	insecure   = flag.Bool("insecure", false, "Do not use TLS")
	configPath = flag.String("config", "/etc/omegaup/grader/config.json",
		"Grader configuration file")
	globalContext atomic.Value
	ioLock        sync.Mutex
)

func loadContext() error {
	ctx, err := common.NewContext(*configPath)
	if err != nil {
		return err
	}
	globalContext.Store(ctx)
	return nil
}

func main() {
	rand.Seed(time.Now().UTC().UnixNano())
	flag.Parse()

	if err := loadContext(); err != nil {
		panic(err)
	}

	ctx := globalContext.Load().(*common.Context)
	expvar.Publish("config", &globalContext.Load().(*common.Context).Config)
	common.InitInputManager(ctx)
	go runner.PreloadInputs(ctx, &ioLock)
	var client *http.Client
	if *insecure {
		client = http.DefaultClient
	} else {
		cert, err := ioutil.ReadFile(ctx.Config.TLS.CertFile)
		if err != nil {
			panic(err)
		}
		certPool := x509.NewCertPool()
		certPool.AppendCertsFromPEM(cert)
		keyPair, err := tls.LoadX509KeyPair(ctx.Config.TLS.CertFile, ctx.Config.TLS.KeyFile)
		if err != nil {
			panic(err)
		}
		tr := &http.Transport{
			TLSClientConfig: &tls.Config{
				Certificates: []tls.Certificate{keyPair},
				RootCAs:      certPool,
				ClientAuth:   tls.RequireAndVerifyClientCert,
			},
			DisableCompression: true,
		}
		client = &http.Client{Transport: tr}
	}

	baseURL, err := url.Parse(ctx.Config.Runner.GraderURL)
	if err != nil {
		panic(err)
	}

	ctx.Log.Info("omegaUp runner ready to serve")

	var sleepTime float32 = 1

	for {
		if err := processRun(ctx, client, baseURL); err != nil {
			ctx.Log.Error("error grading run", "err", err)
			// Randomized exponential backoff.
			time.Sleep(time.Duration(rand.Float32()*sleepTime) * time.Second)
			if sleepTime < 64 {
				sleepTime *= 2
			}
		} else {
			sleepTime = 1
		}
	}
}

// A reader that blocks until the data is available.
// This is used so that the HTTP connection can be established quickly and then
// block until the results are in. This sends a single byte upon connection
// establishment and relies on the fact that all the data it sends is
// JSON-encoded, so it always sends a '{'.
type blockingReader struct {
	hasRead    bool
	reader     io.Reader
	readerChan chan io.Reader
}

func (r *blockingReader) Read(p []byte) (int, error) {
	if r.reader == nil {
		if !r.hasRead {
			r.hasRead = true
			p[0] = '{'
			return 1, nil
		}
		r.reader = <-r.readerChan
		close(r.readerChan)
		// Make sure the first byte was actually a brace. Otherwise raise an error.
		brace := make([]byte, 1)
		if n, err := r.reader.Read(brace); err != nil || n != 1 || brace[0] != '{' {
			return 0, io.ErrUnexpectedEOF
		}
	}
	return r.reader.Read(p)
}

func processRun(ctx *common.Context, client *http.Client, baseURL *url.URL) error {
	requestURL, err := baseURL.Parse("run/request/")
	if err != nil {
		panic(err)
	}
	resp, err := client.Get(requestURL.String())
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	decoder := json.NewDecoder(resp.Body)
	var run common.Run
	if err := decoder.Decode(&run); err != nil {
		return err
	}

	uploadURL, err := baseURL.Parse(fmt.Sprintf("run/%d/results/", run.ID))
	if err != nil {
		return err
	}
	requestBody := &blockingReader{
		readerChan: make(chan io.Reader),
	}
	finished := make(chan error)
	go func() {
		response, err := client.Post(uploadURL.String(), "text/json", requestBody)
		if err != nil {
			finished <- err
		} else {
			response.Body.Close()
			finished <- nil
		}
	}()

	// Make sure no other I/O is being made while we grade this run.
	ioLock.Lock()
	defer ioLock.Unlock()

	input, err := common.DefaultInputManager.Add(run.InputHash,
		runner.NewRunnerInputFactory(&run, client, &ctx.Config))
	if err != nil {
		return err
	}
	defer input.Release()
	result, err := runner.Grade(ctx, client, baseURL, &run, input)
	if err != nil {
		ctx.Log.Error("Error while grading", "err", err)
	}
	var resultBytes bytes.Buffer
	encoder := json.NewEncoder(&resultBytes)
	if err := encoder.Encode(result); err != nil {
		return err
	}
	requestBody.readerChan <- &resultBytes
	return <-finished
}
<|endoftext|>


<commit_before>package tileregistry

type (
	//TileGenerator - interface for a tile creating object
	TileGenerator interface {
		New(tileSpec TileSpec) (Tile, error)
	}
	//Tile - definition for what a tile looks like
	Tile interface {
		Backup() error
		Restore() error
	}
	//TileSpec -- defines what a tile would need to be initialized
	TileSpec struct {
		OpsManagerHost   string
		AdminUser        string
		AdminPass        string
		OpsManagerUser   string
		OpsManagerPass   string
		ArchiveDirectory string
	}
)
<commit_msg>[#113547215] adding RemoteArchivePath to TileSpec structure<commit_after>package tileregistry

type (
	//TileGenerator - interface for a tile creating object
	TileGenerator interface {
		New(tileSpec TileSpec) (Tile, error)
	}
	//Tile - definition for what a tile looks like
	Tile interface {
		Backup() error
		Restore() error
	}
	//TileSpec -- defines what a tile would need to be initialized
	TileSpec struct {
		OpsManagerHost    string
		AdminUser         string
		AdminPass         string
		OpsManagerUser    string
		OpsManagerPass    string
		ArchiveDirectory  string
		RemoteArchivePath string
	}
)
<|endoftext|>