<commit_before>package questions

import (
	"fmt"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestQuestionOne(t *testing.T) {
	tests := []struct {
		name     string
		x        int64
		y        int64
		expected int64
	}{
		{
			name:     "simple",
			x:        1,
			y:        1,
			expected: 2,
		}, {
			name:     "larger",
			x:        759,
			y:        674,
			expected: 1433,
		},
	}
	for _, test := range tests {
		tt := test
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()
			result := QuestionOne(tt.x, tt.y)
			assert.Equal(t, tt.expected, result)
		})
	}
}

func TestQuestionTwo(t *testing.T) {
	deck := initDeck()
	fmt.Println("\ninitial")
	for _, card := range deck {
		fmt.Print(card.Print())
	}
	result := QuestionTwo(deck, 51)

	fmt.Println("\nshuffled")
	for _, card := range result {
		fmt.Print(card.Print())
	}
	assert.Equal(t, len(deck), len(result))
	if !testDecks(deck, result) {
		t.Error("decks don't match")
	}
}

func testDecks(a, b []*Card) bool {
	for _, card := range a {
		if !checkCard(card, b) {
			return false
		}
	}
	return true
}

func checkCard(card *Card, deck []*Card) bool {
	for _, c := range deck {
		if (card.suit == c.suit) && (card.value == c.value) {
			return true
		}
	}
	return false
}

func TestQuestionThree(t *testing.T) {
	test := []int{1, 4, 6, 7, 8}
	fmt.Println(QuestionThree(test, 3))
	fmt.Println(QuestionThree(test, 3))
	fmt.Println(QuestionThree(test, 3))
}

func TestQuestionFour(t *testing.T) {
	tests := []struct {
		name string
		N    int64
		m    int64
	}{
		{
			name: "small",
			N:    4,
			m:    1,
		}, {
			name: "medium",
			N:    8,
			m:    4,
		}, {
			name: "large",
			N:    32,
			m:    24,
		}, {
			name: "huge",
			N:    645,
			m:    325,
		},
	}
	for _, test := range tests {
		tt := test
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()
			list := initIntModList(tt.N, tt.m)
			result := QuestionFour(list, 0)
			assert.Equal(t, tt.m, result)

			for _, i := range list {
				fmt.Print(i.value, " ", i.Get(1))
			}
		})
	}
}

func initIntModList(N, m int64) []*IntMod {
	list := []*IntMod{}
	for i := int64(0); i < N; i++ {
		if i == m {
			continue
		}
		list = append(list, &IntMod{i})
	}
	return list
}

func TestQuestionFive(t *testing.T) {
	tests := []struct {
		name string
		full []string
		sub  []string
	}{
		{
			name: "base",
			full: []string{"A", "B", "A"},
			sub:  []string{"A", "B"},
		}, {
			name: "long",
			full: []string{"A", "B", "A", "A", "B", "B", "B", "A", "B"},
			sub:  []string{"A", "B", "A", "A", "B", "B", "B", "A"},
		}, {
			name: "split",
			full: []string{"A", "B", "A", "A", "A", "A", "A", "B", "B"},
			sub:  []string{"A", "A", "B", "B"},
		}, {
			name: "nil",
			full: []string{"A", "A", "A"},
			sub:  nil,
		},
	}
	for _, test := range tests {
		tt := test
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()
			result := QuestionFive(tt.full)
			assert.Equal(t, tt.sub, result)
		})
	}
}

func TestQuestionSix(t *testing.T) {
	tests := []struct {
		name     string
		N        int
		expected int
	}{
		{
			name:     "base",
			N:        22,
			expected: 6,
		}, {
			name:     "other",
			N:        25,
			expected: 9,
		}, {
			name:     "zero",
			N:        1,
			expected: 0,
		}, {
			name:     "large",
			N:        1000,
			expected: 300,
		}, {
			name:     "odd",
			N:        245,
			expected: 101,
		}, {
			name:     "big",
			N:        2456,
			expected: 1253,
		},
	}
	for _, test := range tests {
		tt := test
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()
			result := QuestionSix(tt.N)
			assert.Equal(t, tt.expected, result)
		})
	}
}

func TestQuestionSeven(t *testing.T) {
	tests := []struct {
		name        string
		frequencies map[string]int
		synonyms    [][]string
		expected    map[string]int
	}{
		{
			name: "base",
			frequencies: map[string]int{
				"A": 1,
				"B": 2,
				"a": 3,
			},
			synonyms: [][]string{
				[]string{"A", "a"},
			},
			expected: map[string]int{
				"A": 4,
				"B": 2,
			},
		}, {
			name: "names",
			frequencies: map[string]int{
				"John":        15,
				"Jon":         12,
				"Chris":       13,
				"Kris":        4,
				"Christopher": 19,
			},
			synonyms: [][]string{
				[]string{"John", "Jon"},
				[]string{"John", "Johnny"},
				[]string{"Chris", "Kris"},
				[]string{"Chris", "Christopher"},
			},
			expected: map[string]int{
				"John":  27,
				"Chris": 36,
			},
		},
	}
	for _, test := range tests {
		tt := test
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()
			result := QuestionSeven(tt.frequencies, tt.synonyms)
			assert.Equal(t, tt.expected, result)
		})
	}
}
<commit_msg>break tests with chain<commit_after>package questions

import (
	"fmt"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestQuestionOne(t *testing.T) {
	tests := []struct {
		name     string
		x        int64
		y        int64
		expected int64
	}{
		{
			name:     "simple",
			x:        1,
			y:        1,
			expected: 2,
		}, {
			name:     "larger",
			x:        759,
			y:        674,
			expected: 1433,
		},
	}
	for _, test := range tests {
		tt := test
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()
			result := QuestionOne(tt.x, tt.y)
			assert.Equal(t, tt.expected, result)
		})
	}
}

func TestQuestionTwo(t *testing.T) {
	deck := initDeck()
	fmt.Println("\ninitial")
	for _, card := range deck {
		fmt.Print(card.Print())
	}
	result := QuestionTwo(deck, 51)

	fmt.Println("\nshuffled")
	for _, card := range result {
		fmt.Print(card.Print())
	}
	assert.Equal(t, len(deck), len(result))
	if !testDecks(deck, result) {
		t.Error("decks don't match")
	}
}

func testDecks(a, b []*Card) bool {
	for _, card := range a {
		if !checkCard(card, b) {
			return false
		}
	}
	return true
}

func checkCard(card *Card, deck []*Card) bool {
	for _, c := range deck {
		if (card.suit == c.suit) && (card.value == c.value) {
			return true
		}
	}
	return false
}

func TestQuestionThree(t *testing.T) {
	test := []int{1, 4, 6, 7, 8}
	fmt.Println(QuestionThree(test, 3))
	fmt.Println(QuestionThree(test, 3))
	fmt.Println(QuestionThree(test, 3))
}

func TestQuestionFour(t *testing.T) {
	tests := []struct {
		name string
		N    int64
		m    int64
	}{
		{
			name: "small",
			N:    4,
			m:    1,
		}, {
			name: "medium",
			N:    8,
			m:    4,
		}, {
			name: "large",
			N:    32,
			m:    24,
		}, {
			name: "huge",
			N:    645,
			m:    325,
		},
	}
	for _, test := range tests {
		tt := test
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()
			list := initIntModList(tt.N, tt.m)
			result := QuestionFour(list, 0)
			assert.Equal(t, tt.m, result)

			for _, i := range list {
				fmt.Print(i.value, " ", i.Get(1))
			}
		})
	}
}

func initIntModList(N, m int64) []*IntMod {
	list := []*IntMod{}
	for i := int64(0); i < N; i++ {
		if i == m {
			continue
		}
		list = append(list, &IntMod{i})
	}
	return list
}

func TestQuestionFive(t *testing.T) {
	tests := []struct {
		name string
		full []string
		sub  []string
	}{
		{
			name: "base",
			full: []string{"A", "B", "A"},
			sub:  []string{"A", "B"},
		}, {
			name: "long",
			full: []string{"A", "B", "A", "A", "B", "B", "B", "A", "B"},
			sub:  []string{"A", "B", "A", "A", "B", "B", "B", "A"},
		}, {
			name: "split",
			full: []string{"A", "B", "A", "A", "A", "A", "A", "B", "B"},
			sub:  []string{"A", "A", "B", "B"},
		}, {
			name: "nil",
			full: []string{"A", "A", "A"},
			sub:  nil,
		},
	}
	for _, test := range tests {
		tt := test
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()
			result := QuestionFive(tt.full)
			assert.Equal(t, tt.sub, result)
		})
	}
}

func TestQuestionSix(t *testing.T) {
	tests := []struct {
		name     string
		N        int
		expected int
	}{
		{
			name:     "base",
			N:        22,
			expected: 6,
		}, {
			name:     "other",
			N:        25,
			expected: 9,
		}, {
			name:     "zero",
			N:        1,
			expected: 0,
		}, {
			name:     "large",
			N:        1000,
			expected: 300,
		}, {
			name:     "odd",
			N:        245,
			expected: 101,
		}, {
			name:     "big",
			N:        2456,
			expected: 1253,
		},
	}
	for _, test := range tests {
		tt := test
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()
			result := QuestionSix(tt.N)
			assert.Equal(t, tt.expected, result)
		})
	}
}

func TestQuestionSeven(t *testing.T) {
	tests := []struct {
		name        string
		frequencies map[string]int
		synonyms    [][]string
		expected    map[string]int
	}{
		{
			name: "base",
			frequencies: map[string]int{
				"A": 1,
				"B": 2,
				"a": 3,
			},
			synonyms: [][]string{
				[]string{"A", "a"},
			},
			expected: map[string]int{
				"A": 4,
				"B": 2,
			},
		}, {
			name: "names",
			frequencies: map[string]int{
				"John":        15,
				"Jon":         12,
				"Chris":       13,
				"Kris":        4,
				"Christopher": 19,
			},
			synonyms: [][]string{
				[]string{"John", "Jon"},
				[]string{"John", "Johnny"},
				[]string{"Chris", "Kris"},
				[]string{"Kris", "Christopher"},
			},
			expected: map[string]int{
				"John":  27,
				"Chris": 36,
			},
		},
	}
	for _, test := range tests {
		tt := test
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()
			result := QuestionSeven(tt.frequencies, tt.synonyms)
			assert.Equal(t, tt.expected, result)
		})
	}
}
<|endoftext|>


<commit_before>package arel

import (
	"strconv"
)

type SelectManager struct {
	Engine Engine
	Ast    SelectStatementNode
	Ctx    *SelectCoreNode
	BaseNode
}

func NewSelectManager(t *Table) SelectManager {
	stmt := SelectStatementNode{Cores: make([]*SelectCoreNode, 0)}
	core := NewSelectCoreNode()
	stmt.Cores = append(stmt.Cores, &core)
	ctx := stmt.Cores[len(stmt.Cores)-1]
	manager := SelectManager{
		Engine:   t.Engine,
		Ast:      stmt,
		Ctx:      ctx,
		BaseNode: NewBaseNode(),
	}
	manager.From(t)
	return manager
}

func (s *SelectManager) ToSql() string {
	return s.Engine.Visitor().Accept(s.Ast)
}

func (s *SelectManager) Project(projections ...interface{}) *SelectManager {
	var projection SqlLiteralNode
	for _, p := range projections {
		switch p.(type) {
		case string:
			projection = Sql(p.(string))
		default:
			projection = Sql("*")
		}

		if s.Ctx.Projections == nil {
			nodeslice := make([]AstNode, 0)
			s.Ctx.Projections = &nodeslice
		}

		if s.Ctx.Projections != nil {
			*s.Ctx.Projections = append(*s.Ctx.Projections, projection)
		}
	}
	return s
}

func (s *SelectManager) From(t *Table) *SelectManager {
	s.Ctx.Source.Left = t
	return s
}

func (s *SelectManager) Join(a ...AstNode) *SelectManager {
	return s
}

func (s *SelectManager) Take(a ...AstNode) *SelectManager {
	return s
}

func (s *SelectManager) Order(a ...AstNode) *SelectManager {
	return s
}

func (s *SelectManager) Where(a ...AstNode) *SelectManager {
	return s
}

func (s *SelectManager) Group(a ...AstNode) *SelectManager {
	return s
}

func (s *SelectManager) Skip(i int) *SelectManager {
	offset := NewOffsetNode(Sql(strconv.Itoa(i)))
	s.Ast.Offset = &offset
	return s
}

func (s *SelectManager) Offset(i int) *SelectManager {
	return s.Skip(i)
}

func (s *SelectManager) Having(things ...interface{}) *SelectManager {
	return s
}
<commit_msg>Update SelectMananger#Having to only accept astnodes<commit_after>package arel

import (
	"strconv"
)

type SelectManager struct {
	Engine Engine
	Ast    SelectStatementNode
	Ctx    *SelectCoreNode
	BaseNode
}

func NewSelectManager(t *Table) SelectManager {
	stmt := SelectStatementNode{Cores: make([]*SelectCoreNode, 0)}
	core := NewSelectCoreNode()
	stmt.Cores = append(stmt.Cores, &core)
	ctx := stmt.Cores[len(stmt.Cores)-1]
	manager := SelectManager{
		Engine:   t.Engine,
		Ast:      stmt,
		Ctx:      ctx,
		BaseNode: NewBaseNode(),
	}
	manager.From(t)
	return manager
}

func (s *SelectManager) ToSql() string {
	return s.Engine.Visitor().Accept(s.Ast)
}

func (s *SelectManager) Project(projections ...interface{}) *SelectManager {
	var projection SqlLiteralNode
	for _, p := range projections {
		switch p.(type) {
		case string:
			projection = Sql(p.(string))
		default:
			projection = Sql("*")
		}

		if s.Ctx.Projections == nil {
			nodeslice := make([]AstNode, 0)
			s.Ctx.Projections = &nodeslice
		}

		if s.Ctx.Projections != nil {
			*s.Ctx.Projections = append(*s.Ctx.Projections, projection)
		}
	}
	return s
}

func (s *SelectManager) From(t *Table) *SelectManager {
	s.Ctx.Source.Left = t
	return s
}

func (s *SelectManager) Join(a ...AstNode) *SelectManager {
	return s
}

func (s *SelectManager) Take(a ...AstNode) *SelectManager {
	return s
}

func (s *SelectManager) Order(a ...AstNode) *SelectManager {
	return s
}

func (s *SelectManager) Where(a ...AstNode) *SelectManager {
	return s
}

func (s *SelectManager) Group(a ...AstNode) *SelectManager {
	return s
}

func (s *SelectManager) Skip(i int) *SelectManager {
	offset := NewOffsetNode(Sql(strconv.Itoa(i)))
	s.Ast.Offset = &offset
	return s
}

func (s *SelectManager) Offset(i int) *SelectManager {
	return s.Skip(i)
}

func (s *SelectManager) Having(a ...AstNode) *SelectManager {
	return s
}
<|endoftext|>


<commit_before>package boardgame

import (
	"encoding/json"
	"github.com/jkomoros/boardgame/errors"
	"time"
)

//MoveType represents a type of a move in a game, and information about that
//MoveType. New Moves are constructed by calling its NewMove() method. Fields
//are hidden to prevent modifying them once a game has been SetUp. New ones
//cannot be created directly; they are created via
//GameManager.AddMoveType(moveTypeConfig).
type moveType struct {
	name                string
	constructor         func() Move
	validator           *readerValidator
	customConfiguration PropertyCollection
	manager             *GameManager
}

//MoveConfig is a collection of information used to create a Move. Your
//delegate's ConfigureMoves() will emit a slice of them. Typically you'll use
//moves.Combine, moves.Add, moves.AddWithPhase, combined with
//moves.AutoConfigurer.Configure() to generate these. This is an interface and
//not a concrete struct because other packages, like moves, add more behavior
//to the ones they return. If you want just a vanilla one without using the
//moves package, use NewMoveConfig.
type MoveConfig interface {
	//Name is the name for this type of move. No other Move structs
	//in use in this game should have the same name, but it should be human-
	//friendly. For example, "Place Token" is a reasonable name, as long as no
	//other types of Move-structs will return that name in this game. Required.
	Name() string

	//Constructor should return a zero-valued Move of the given type. Normally
	//very simple: just a new(MyMoveType). Required. If you have a field that
	//is an enum.Var you'll need to initalize it with a variable for the
	//correct enum (generally necessitating a multi-line constructor),
	//otherwise your move will fail to register. If that field has a struct
	//tag of `enum:"ENUMNAME"` then so long as ENUMNAME is the name of a valid
	//enum in the game's Chest.Enums, it will auto-instantiate a enum.Var for
	//the correct enum for that field, allowing you to maintain a single-line
	//constructor.
	Constructor() func() Move

	//CustomConfiguration is an optional PropertyCollection. Some move types--
	//especially in the `moves` package--stash configuration options here that
	//will change how all moves of this type behave. Individual moves would
	//reach through via Info().Type().CustomConfiguration() to retrieve the
	//values stored there. Different move types will store different types of
	//information there--to avoid a collision the convention is to use a
	//string name that starts with your fully qualified package name, then a
	//dot, then the propertyname, like so:
	//"github.com/jkomoros/boardgame/moves.MoveName". Those strings are often
	//encoded as package-private constants, and a
	//interfaces.CustomConfigurationOption functor factory is provided to set
	//those from outside the package. Generally you don't use this directly,
	//but auto.Config() will help you set these for what specific
	//moves in that package expect.
	CustomConfiguration() PropertyCollection
}

type defaultMoveConfig struct {
	name                string
	constructor         func() Move
	customConfiguration PropertyCollection
}

func (d defaultMoveConfig) Name() string {
	return d.name
}

func (d defaultMoveConfig) Constructor() func() Move {
	return d.constructor
}

func (d defaultMoveConfig) CustomConfiguration() PropertyCollection {
	return d.customConfiguration
}

//NewMoveConfig returns a simple MoveConfig that will return the provided
//parameters from its getters. Typically you don't use this, but rather use
//the output of moves.AutoConfigurer.Config().
func NewMoveConfig(name string, constructor func() Move, customConfiguration PropertyCollection) MoveConfig {
	return defaultMoveConfig{
		name,
		constructor,
		customConfiguration,
	}
}

const newMoveTypeErrNoManagerPassed = "No manager passed, so we can'd do validation"

//NewMoveType takes a MoveConfig and returns a MoveType associated with
//the given manager. The returned move type will not yet have been added to
//the manager in question. In general you don't call this directly, and
//instead use manager.AddMove, which accepts a MoveConfig.
func newMoveType(config MoveConfig, manager *GameManager) (*moveType, error) {
	if config == nil {
		return nil, errors.New("No config provided")
	}

	if config.Name() == "" {
		return nil, errors.New("No name provided")
	}

	if config.Constructor() == nil {
		return nil, errors.New("No MoveConstructor provided")
	}

	exampleMove := config.Constructor()()

	if exampleMove == nil {
		return nil, errors.New("Constructor returned nil")
	}

	readSetter := exampleMove.ReadSetter()

	if readSetter == nil {
		return nil, errors.New("Constructor's readsetter returned nil")
	}

	var validator *readerValidator
	var err error

	//moves.Defaultconfig will call this without a manager. So return a half-
	//useful object in that case... but also an error so anyone else who
	//checks the error will ignore the half-useful move type.
	if manager != nil {
		validator, err = newReaderValidator(readSetter, readSetter, exampleMove, moveTypeIllegalPropTypes, manager.Chest(), false)

		if err != nil {
			return nil, errors.New("Couldn't create validator: " + err.Error())
		}
	} else {
		//moves.DefaultConfig hackily looks for exactly this error string.
		err = errors.New(newMoveTypeErrNoManagerPassed)
	}

	return &moveType{
		name:                config.Name(),
		constructor:         config.Constructor(),
		customConfiguration: config.CustomConfiguration(),
		validator:           validator,
		manager:             manager,
	}, err

}

//OrphanExampleMove returns a move from the config that will be similar to a
//real move, in terms of struct-based auto-inflation, etc. This is exposed
//primarily for moves.AutoConfigrer, and generally shouldn't be used by
//others.
func OrphanExampleMove(config MoveConfig) (Move, error) {
	throwAwayMoveType, err := newMoveType(config, nil)

	if err != nil {
		//Look for exatly the single kind of error we're OK with. Yes, this is a hack.
		if err.Error() != newMoveTypeErrNoManagerPassed {
			return nil, errors.New("Couldn't create intermediate move type: " + err.Error())
		}
	}
	return throwAwayMoveType.NewMove(nil), nil
}

//MoveInfo is an object that contains meta-information about a move.
type MoveInfo struct {
	moveType  *moveType
	version   int
	initiator int
	name      string
	timestamp time.Time
}

//Move's are how all modifications are made to Game States after
//initialization. Packages define structs that implement Move for all
//modifications. The Move should be JSON-able (that is, all persistable state
//should be in public fields), and it may not include Timers, Stacks, or
//EnumValues. Use moves.Base for a convenient composable base Move that will
//allow you to skip most of the boilerplate overhead.
type Move interface {

	//Info returns the MoveInfo objec that was affiliated with this object by
	//SetInfo.
	Info() *MoveInfo

	//Legal returns nil if this proposed move is legal, or an error if the
	//move is not legal. The error message may be shown directly to the end-
	//user so be sure to make it user friendly. proposer is set to the
	//notional player that is proposing the move. proposer might be a valid
	//player index, or AdminPlayerIndex (for example, if it is a FixUpMove it
	//will typically be AdminPlayerIndex). AdminPlayerIndex is always allowed
	//to make any move. It will never be ObserverPlayerIndex, because by
	//definition Observers may not make moves. If you want to check that the
	//person proposing is able to apply the move for the given player, and
	//that it is their turn, you would do something like test
	//m.TargetPlayerIndex.Equivalent(proposer),
	//m.TargetPlayerIndex.Equivalent(game.CurrentPlayer).
	Legal(state ImmutableState, proposer PlayerIndex) error

	//Apply applies the move to the state. It is handed a copy of the state to
	//modify. If error is non-nil it will not be applied to the game. It
	//should not be called directly; use Game.ProposeMove.
	Apply(state State) error

	//Sets the move to have reasonable defaults for the given state.For
	//example, if the Move has a TargetPlayerIndex property, a reasonable
	//default is state.CurrentPlayer().
	DefaultsForState(state ImmutableState)

	//HelpText is a human-readable sentence describing what the move does in
	//general. HelpText should be the same for all moves of the same type, and
	//should not vary with the Move's specific properties. For example, the
	//HelpText for "Place Token" might be "Places the current user's token in
	//the specified slot on the board."
	HelpText() string

	//Description is a human-readable prose description of the effects that
	//this particular move will have, including any move configuration. For
	//example the Description for "Place Token" might be "Player 0 places a
	//token in position 3".
	Description() string

	//IsFixUp should return true if this type of move is a candidate to be
	//returned from ProposeFixUpMove. Doesn't do anything in the core engine,
	//but many other things (like DefaultGameDelegate's ProposeFixUpMove) want
	//to know this, so it's part of the default signature.
	IsFixUp() bool

	//SetInfo will be called after the constructor is called to set the
	//information, including what type the move is. Splitting this out allows
	//the basic constructors not in the base classes to be very small, because
	//in most cases you'll compose a moves.Base.
	SetInfo(m *MoveInfo)

	//TopLevelStruct should return the value that was set via
	//SetTopLevelStruct. It returns the Move that is at the top of the
	//embedding chain (because structs that are embedded anonymously can only
	//access themselves and not their embedders). This is useful because in a
	//number of cases embeded moves (for example moves in the moves package)
	//need to consult a method on their embedder.
	TopLevelStruct() Move

	//SetTopLevelStruct is called right after the move is constructed.
	//Splitting this out allows the basic constructors not in the base classes
	//to be very small, because in most cases you'll compose a moves.Base.
	SetTopLevelStruct(m Move)

	//ValidConfiguration will be checked when the game manager is SetUp, and
	//if it returns an error the manager will fail to SetUp. Some Moves,
	//especially sub-classes of moves in the moves package, require set up
	//that can only be verified at run time (for example, verifying that the
	//embedder implements a certain inteface). This is a useful way to detect
	//those misconfigurations at the earliest moment. In most cases you never
	//need to implement this yourself; moves in the moves package that need it
	//will implement it.
	ValidConfiguration(exampleState State) error

	ReadSetConfigurer
}

//StorageRecordForMove returns a MoveStorageRecord. Can't hang off of Move
//itself since Moves are provided by users of the library.
func StorageRecordForMove(move Move, currentPhase int) *MoveStorageRecord {

	blob, err := json.MarshalIndent(move, "", "\t")

	if err != nil {
		return nil
	}

	return &MoveStorageRecord{
		Name:      move.Info().Name(),
		Version:   move.Info().version,
		Initiator: move.Info().initiator,
		Timestamp: move.Info().timestamp,
		Phase:     currentPhase,
		Blob:      blob,
	}
}

//Name returns the name of the move type that this move is. Calling
//manager.ExampleMove() with that string value will return a similar struct.
func (m *MoveInfo) Name() string {
	return m.name
}

//Version returns the version of this move--or the version that it will be
//when successfully committed.
func (m *MoveInfo) Version() int {
	return m.version
}

//Timestamp returns the time that the given move was made.
func (m *MoveInfo) Timestamp() time.Time {
	return m.timestamp
}

//CustomConfiguration returns the configuration object associatd with this
//move.
func (m *MoveInfo) CustomConfiguration() PropertyCollection {
	if m.moveType == nil {
		return nil
	}
	return m.moveType.customConfiguration
}

//Initiator returns the move version that initiated this causal chain: the
//PlayerMove that was applied that led to this chain of FixUp moves. The
//Initiator of a PlayerMove is its own version, so this value will be less
//than or equal to its own version. The value of Initator is unspecified until
//after the move has been successfully committed.
func (m *MoveInfo) Initiator() int {
	return m.initiator
}

var moveTypeIllegalPropTypes = map[PropertyType]bool{
	TypeStack: true,
	TypeBoard: true,
	TypeTimer: true,
}

//Name returns the unique name for this type of move.
func (m *moveType) Name() string {
	return m.name
}

//NewMove returns a new move of this type, with defaults set for the given
//state. If state is nil, then DefaultsForState will not be called.
func (m *moveType) NewMove(state ImmutableState) Move {
	move := m.constructor()
	if move == nil {
		return nil
	}

	info := &MoveInfo{
		moveType: m,
		name:     m.Name(),
	}

	if state != nil {
		info.version = state.Version() + 1
	}

	move.SetInfo(info)
	move.SetTopLevelStruct(move)

	readSetConfigurer := move.ReadSetConfigurer()

	if readSetConfigurer == nil {
		//This shouldn't happen because we verified that ReadSetter returned
		//non-nil when the movetype was registered.
		m.manager.Logger().Error("ReadSetConfigurer for move unexpectedly returned nil")
		return nil
	}

	//validator might be nil if we have a half-functioning MoveType. (Like
	//what will be returned, along with an error, when NewMoveType is called
	//during moves.DefaultConfig)
	if m.validator != nil {
		if err := m.validator.AutoInflate(readSetConfigurer, state); err != nil {
			m.manager.Logger().Error("AutoInflate had an error: " + err.Error())
			return nil
		}

		if err := m.validator.Valid(readSetConfigurer); err != nil {
			m.manager.Logger().Error("Move was not valid: " + err.Error())
			return nil
		}
	}

	if state != nil {
		move.DefaultsForState(state)
	}
	return move
}

//We implement a private stub of moves.Base in this package just for the
//convience of our own test structs.
type baseMove struct {
	info           MoveInfo
	topLevelStruct Move
}

//baseFixUpMove is same as baseMove but returns true for IsFixUp.
type baseFixUpMove struct {
	baseMove
}

func (d *baseMove) HelpText() string {
	return "Unimplemented"
}

func (d *baseMove) SetInfo(m *MoveInfo) {
	d.info = *m
}

func (d *baseMove) Info() *MoveInfo {
	return &d.info
}

func (d *baseMove) SetTopLevelStruct(m Move) {
	d.topLevelStruct = m
}

func (d *baseMove) TopLevelStruct() Move {
	return d.topLevelStruct
}

func (d *baseMove) IsFixUp() bool {
	return false
}

func (d *baseFixUpMove) IsFixUp() bool {
	return true
}

//DefaultsForState doesn't do anything
func (d *baseMove) DefaultsForState(state ImmutableState) {
	return
}

//Description defaults to returning the Type's HelpText()
func (d *baseMove) Description() string {
	return d.TopLevelStruct().HelpText()
}

func (d *baseMove) ValidConfiguration(exampleState State) error {
	return nil
}
<commit_msg>Fix up out-of-date documentation from a few commits ago.<commit_after>package boardgame

import (
	"encoding/json"
	"github.com/jkomoros/boardgame/errors"
	"time"
)

//MoveType represents a type of a move in a game, and information about that
//MoveType. New Moves are constructed by calling its NewMove() method. Fields
//are hidden to prevent modifying them once a game has been SetUp. New ones
//cannot be created directly; they are created via
//GameManager.AddMoveType(moveTypeConfig).
type moveType struct {
	name                string
	constructor         func() Move
	validator           *readerValidator
	customConfiguration PropertyCollection
	manager             *GameManager
}

//MoveConfig is a collection of information used to create a Move. Your
//delegate's ConfigureMoves() will emit a slice of them. Typically you'll use
//moves.Combine, moves.Add, moves.AddWithPhase, combined with
//moves.AutoConfigurer.Configure() to generate these. This is an interface and
//not a concrete struct because other packages, like moves, add more behavior
//to the ones they return. If you want just a vanilla one without using the
//moves package, use NewMoveConfig.
type MoveConfig interface {
	//Name is the name for this type of move. No other Move structs
	//in use in this game should have the same name, but it should be human-
	//friendly. For example, "Place Token" is a reasonable name, as long as no
	//other types of Move-structs will return that name in this game. Required.
	Name() string

	//Constructor should return a zero-valued Move of the given type. Normally
	//very simple: just a new(MyMoveType). Required. If you have a field that
	//is an enum.Var you'll need to initalize it with a variable for the
	//correct enum (generally necessitating a multi-line constructor),
	//otherwise your move will fail to register. If that field has a struct
	//tag of `enum:"ENUMNAME"` then so long as ENUMNAME is the name of a valid
	//enum in the game's Chest.Enums, it will auto-instantiate a enum.Var for
	//the correct enum for that field, allowing you to maintain a single-line
	//constructor.
	Constructor() func() Move

	//CustomConfiguration is an optional PropertyCollection. Some move types--
	//especially in the `moves` package--stash configuration options here that
	//will change how all moves of this type behave. Individual moves would
	//reach through via Info().CustomConfiguration() to retrieve the
	//values stored there. Different move types will store different types of
	//information there--to avoid a collision the convention is to use a
	//string name that starts with your fully qualified package name, then a
	//dot, then the propertyname, like so:
	//"github.com/jkomoros/boardgame/moves.MoveName". Those strings are often
	//encoded as package-private constants, and a
	//interfaces.CustomConfigurationOption functor factory is provided to set
	//those from outside the package. Generally you don't use this directly,
	//but moves.AutoConfigurer will help you set these for what specific
	//moves in that package expect.
	CustomConfiguration() PropertyCollection
}

type defaultMoveConfig struct {
	name                string
	constructor         func() Move
	customConfiguration PropertyCollection
}

func (d defaultMoveConfig) Name() string {
	return d.name
}

func (d defaultMoveConfig) Constructor() func() Move {
	return d.constructor
}

func (d defaultMoveConfig) CustomConfiguration() PropertyCollection {
	return d.customConfiguration
}

//NewMoveConfig returns a simple MoveConfig that will return the provided
//parameters from its getters. Typically you don't use this, but rather use
//the output of moves.AutoConfigurer.Config().
func NewMoveConfig(name string, constructor func() Move, customConfiguration PropertyCollection) MoveConfig {
	return defaultMoveConfig{
		name,
		constructor,
		customConfiguration,
	}
}

const newMoveTypeErrNoManagerPassed = "No manager passed, so we can'd do validation"

//NewMoveType takes a MoveConfig and returns a MoveType associated with
//the given manager. The returned move type will not yet have been added to
//the manager in question. In general you don't call this directly, and
//instead use manager.AddMove, which accepts a MoveConfig.
func newMoveType(config MoveConfig, manager *GameManager) (*moveType, error) {
	if config == nil {
		return nil, errors.New("No config provided")
	}

	if config.Name() == "" {
		return nil, errors.New("No name provided")
	}

	if config.Constructor() == nil {
		return nil, errors.New("No MoveConstructor provided")
	}

	exampleMove := config.Constructor()()

	if exampleMove == nil {
		return nil, errors.New("Constructor returned nil")
	}

	readSetter := exampleMove.ReadSetter()

	if readSetter == nil {
		return nil, errors.New("Constructor's readsetter returned nil")
	}

	var validator *readerValidator
	var err error

	//moves.Defaultconfig will call this without a manager. So return a half-
	//useful object in that case... but also an error so anyone else who
	//checks the error will ignore the half-useful move type.
	if manager != nil {
		validator, err = newReaderValidator(readSetter, readSetter, exampleMove, moveTypeIllegalPropTypes, manager.Chest(), false)

		if err != nil {
			return nil, errors.New("Couldn't create validator: " + err.Error())
		}
	} else {
		//moves.DefaultConfig hackily looks for exactly this error string.
		err = errors.New(newMoveTypeErrNoManagerPassed)
	}

	return &moveType{
		name:                config.Name(),
		constructor:         config.Constructor(),
		customConfiguration: config.CustomConfiguration(),
		validator:           validator,
		manager:             manager,
	}, err

}

//OrphanExampleMove returns a move from the config that will be similar to a
//real move, in terms of struct-based auto-inflation, etc. This is exposed
//primarily for moves.AutoConfigrer, and generally shouldn't be used by
//others.
func OrphanExampleMove(config MoveConfig) (Move, error) {
	throwAwayMoveType, err := newMoveType(config, nil)

	if err != nil {
		//Look for exatly the single kind of error we're OK with. Yes, this is a hack.
		if err.Error() != newMoveTypeErrNoManagerPassed {
			return nil, errors.New("Couldn't create intermediate move type: " + err.Error())
		}
	}
	return throwAwayMoveType.NewMove(nil), nil
}

//MoveInfo is an object that contains meta-information about a move.
type MoveInfo struct {
	moveType  *moveType
	version   int
	initiator int
	name      string
	timestamp time.Time
}

//Move's are how all modifications are made to Game States after
//initialization. Packages define structs that implement Move for all
//modifications. The Move should be JSON-able (that is, all persistable state
//should be in public fields), and it may not include Timers, Stacks, or
//EnumValues. Use moves.Base for a convenient composable base Move that will
//allow you to skip most of the boilerplate overhead.
type Move interface {

	//Info returns the MoveInfo objec that was affiliated with this object by
	//SetInfo.
	Info() *MoveInfo

	//Legal returns nil if this proposed move is legal, or an error if the
	//move is not legal. The error message may be shown directly to the end-
	//user so be sure to make it user friendly. proposer is set to the
	//notional player that is proposing the move. proposer might be a valid
	//player index, or AdminPlayerIndex (for example, if it is a FixUpMove it
	//will typically be AdminPlayerIndex). AdminPlayerIndex is always allowed
	//to make any move. It will never be ObserverPlayerIndex, because by
	//definition Observers may not make moves. If you want to check that the
	//person proposing is able to apply the move for the given player, and
	//that it is their turn, you would do something like test
	//m.TargetPlayerIndex.Equivalent(proposer),
	//m.TargetPlayerIndex.Equivalent(game.CurrentPlayer).
	Legal(state ImmutableState, proposer PlayerIndex) error

	//Apply applies the move to the state. It is handed a copy of the state to
	//modify. If error is non-nil it will not be applied to the game. It
	//should not be called directly; use Game.ProposeMove.
	Apply(state State) error

	//Sets the move to have reasonable defaults for the given state.For
	//example, if the Move has a TargetPlayerIndex property, a reasonable
	//default is state.CurrentPlayer().
	DefaultsForState(state ImmutableState)

	//HelpText is a human-readable sentence describing what the move does in
	//general. HelpText should be the same for all moves of the same type, and
	//should not vary with the Move's specific properties. For example, the
	//HelpText for "Place Token" might be "Places the current user's token in
	//the specified slot on the board."
	HelpText() string

	//Description is a human-readable prose description of the effects that
	//this particular move will have, including any move configuration. For
	//example the Description for "Place Token" might be "Player 0 places a
	//token in position 3".
	Description() string

	//IsFixUp should return true if this type of move is a candidate to be
	//returned from ProposeFixUpMove. Doesn't do anything in the core engine,
	//but many other things (like DefaultGameDelegate's ProposeFixUpMove) want
	//to know this, so it's part of the default signature.
	IsFixUp() bool

	//SetInfo will be called after the constructor is called to set the
	//information, including what type the move is. Splitting this out allows
	//the basic constructors not in the base classes to be very small, because
	//in most cases you'll compose a moves.Base.
	SetInfo(m *MoveInfo)

	//TopLevelStruct should return the value that was set via
	//SetTopLevelStruct. It returns the Move that is at the top of the
	//embedding chain (because structs that are embedded anonymously can only
	//access themselves and not their embedders). This is useful because in a
	//number of cases embeded moves (for example moves in the moves package)
	//need to consult a method on their embedder.
	TopLevelStruct() Move

	//SetTopLevelStruct is called right after the move is constructed.
	//Splitting this out allows the basic constructors not in the base classes
	//to be very small, because in most cases you'll compose a moves.Base.
	SetTopLevelStruct(m Move)

	//ValidConfiguration will be checked when the game manager is SetUp, and
	//if it returns an error the manager will fail to SetUp. Some Moves,
	//especially sub-classes of moves in the moves package, require set up
	//that can only be verified at run time (for example, verifying that the
	//embedder implements a certain inteface). This is a useful way to detect
	//those misconfigurations at the earliest moment. In most cases you never
	//need to implement this yourself; moves in the moves package that need it
	//will implement it.
	ValidConfiguration(exampleState State) error

	ReadSetConfigurer
}

//StorageRecordForMove returns a MoveStorageRecord. Can't hang off of Move
//itself since Moves are provided by users of the library.
func StorageRecordForMove(move Move, currentPhase int) *MoveStorageRecord {

	blob, err := json.MarshalIndent(move, "", "\t")

	if err != nil {
		return nil
	}

	return &MoveStorageRecord{
		Name:      move.Info().Name(),
		Version:   move.Info().version,
		Initiator: move.Info().initiator,
		Timestamp: move.Info().timestamp,
		Phase:     currentPhase,
		Blob:      blob,
	}
}

//Name returns the name of the move type that this move is. Calling
//manager.ExampleMove() with that string value will return a similar struct.
func (m *MoveInfo) Name() string {
	return m.name
}

//Version returns the version of this move--or the version that it will be
//when successfully committed.
func (m *MoveInfo) Version() int {
	return m.version
}

//Timestamp returns the time that the given move was made.
func (m *MoveInfo) Timestamp() time.Time {
	return m.timestamp
}

//CustomConfiguration returns the configuration object associated with this
//move when it was installed from its MoveConfig.CustomConfiguration().
func (m *MoveInfo) CustomConfiguration() PropertyCollection {
	if m.moveType == nil {
		return nil
	}
	return m.moveType.customConfiguration
}

//Initiator returns the move version that initiated this causal chain: the
//PlayerMove that was applied that led to this chain of FixUp moves. The
//Initiator of a PlayerMove is its own version, so this value will be less
//than or equal to its own version. The value of Initator is unspecified until
//after the move has been successfully committed.
func (m *MoveInfo) Initiator() int {
	return m.initiator
}

var moveTypeIllegalPropTypes = map[PropertyType]bool{
	TypeStack: true,
	TypeBoard: true,
	TypeTimer: true,
}

//Name returns the unique name for this type of move.
func (m *moveType) Name() string {
	return m.name
}

//NewMove returns a new move of this type, with defaults set for the given
//state. If state is nil, then DefaultsForState will not be called.
func (m *moveType) NewMove(state ImmutableState) Move {
	move := m.constructor()
	if move == nil {
		return nil
	}

	info := &MoveInfo{
		moveType: m,
		name:     m.Name(),
	}

	if state != nil {
		info.version = state.Version() + 1
	}

	move.SetInfo(info)
	move.SetTopLevelStruct(move)

	readSetConfigurer := move.ReadSetConfigurer()

	if readSetConfigurer == nil {
		//This shouldn't happen because we verified that ReadSetter returned
		//non-nil when the movetype was registered.
		m.manager.Logger().Error("ReadSetConfigurer for move unexpectedly returned nil")
		return nil
	}

	//validator might be nil if we have a half-functioning MoveType. (Like
	//what will be returned, along with an error, when NewMoveType is called
	//during moves.DefaultConfig)
	if m.validator != nil {
		if err := m.validator.AutoInflate(readSetConfigurer, state); err != nil {
			m.manager.Logger().Error("AutoInflate had an error: " + err.Error())
			return nil
		}

		if err := m.validator.Valid(readSetConfigurer); err != nil {
			m.manager.Logger().Error("Move was not valid: " + err.Error())
			return nil
		}
	}

	if state != nil {
		move.DefaultsForState(state)
	}
	return move
}

//We implement a private stub of moves.Base in this package just for the
//convience of our own test structs.
type baseMove struct {
	info           MoveInfo
	topLevelStruct Move
}

//baseFixUpMove is same as baseMove but returns true for IsFixUp.
type baseFixUpMove struct {
	baseMove
}

func (d *baseMove) HelpText() string {
	return "Unimplemented"
}

func (d *baseMove) SetInfo(m *MoveInfo) {
	d.info = *m
}

func (d *baseMove) Info() *MoveInfo {
	return &d.info
}

func (d *baseMove) SetTopLevelStruct(m Move) {
	d.topLevelStruct = m
}

func (d *baseMove) TopLevelStruct() Move {
	return d.topLevelStruct
}

func (d *baseMove) IsFixUp() bool {
	return false
}

func (d *baseFixUpMove) IsFixUp() bool {
	return true
}

//DefaultsForState doesn't do anything
func (d *baseMove) DefaultsForState(state ImmutableState) {
	return
}

//Description defaults to returning the Type's HelpText()
func (d *baseMove) Description() string {
	return d.TopLevelStruct().HelpText()
}

func (d *baseMove) ValidConfiguration(exampleState State) error {
	return nil
}
<|endoftext|>


<commit_before>package sensu

import (
	"errors"

	stdCheck "github.com/upfluence/sensu-client-go/Godeps/_workspace/src/github.com/upfluence/sensu-go/sensu/check"
	"github.com/upfluence/sensu-client-go/sensu/check"
)

type CheckResponse struct {
	Check  stdCheck.CheckOutput `json:"check"`
	Client string               `json:"client"`
}

func executeCheck(input *stdCheck.CheckRequest) (*stdCheck.CheckOutput, error) {
	var output stdCheck.CheckOutput

	if ch, ok := check.Store[input.Extension]; input.Extension != "" && ok {
		output = ch.Execute()
	} else if ch, ok := check.Store[input.Name]; ok {
		output = ch.Execute()
	} else if input.Command == "" {
		return nil, errors.New("Command key not fileed")
	} else {
		output = (&check.ExternalCheck{Request: input}).Execute()
	}

	output.CheckRequest = input

	return &output, nil
}
<commit_msg>Correct the filled typo<commit_after>package sensu

import (
	"errors"

	stdCheck "github.com/upfluence/sensu-client-go/Godeps/_workspace/src/github.com/upfluence/sensu-go/sensu/check"
	"github.com/upfluence/sensu-client-go/sensu/check"
)

type CheckResponse struct {
	Check  stdCheck.CheckOutput `json:"check"`
	Client string               `json:"client"`
}

func executeCheck(input *stdCheck.CheckRequest) (*stdCheck.CheckOutput, error) {
	var output stdCheck.CheckOutput

	if ch, ok := check.Store[input.Extension]; input.Extension != "" && ok {
		output = ch.Execute()
	} else if ch, ok := check.Store[input.Name]; ok {
		output = ch.Execute()
	} else if input.Command == "" {
		return nil, errors.New("Command key not filled")
	} else {
		output = (&check.ExternalCheck{Request: input}).Execute()
	}

	output.CheckRequest = input

	return &output, nil
}
<|endoftext|>


<commit_before>package google

import (
	"fmt"
	"testing"

	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

func TestAccLoggingBucketConfigFolder_basic(t *testing.T) {
	t.Parallel()

	context := map[string]interface{}{
		"random_suffix": randString(t, 10),
		"folder_name":   "tf-test-" + randString(t, 10),
		"org_id":        getTestOrgFromEnv(t),
	}

	vcrTest(t, resource.TestCase{
		PreCheck:  func() { testAccPreCheck(t) },
		Providers: testAccProviders,
		Steps: []resource.TestStep{
			{
				Config: testAccLoggingBucketConfigFolder_basic(context, 30),
			},
			{
				ResourceName:            "google_logging_folder_bucket_config.basic",
				ImportState:             true,
				ImportStateVerify:       true,
				ImportStateVerifyIgnore: []string{"folder"},
			},
			{
				Config: testAccLoggingBucketConfigFolder_basic(context, 40),
			},
			{
				ResourceName:            "google_logging_folder_bucket_config.basic",
				ImportState:             true,
				ImportStateVerify:       true,
				ImportStateVerifyIgnore: []string{"folder"},
			},
		},
	})
}

func TestAccLoggingBucketConfigProject_basic(t *testing.T) {
	t.Parallel()

	context := map[string]interface{}{
		"random_suffix": randString(t, 10),
		"project_name":  "tf-test-" + randString(t, 10),
		"org_id":        getTestOrgFromEnv(t),
	}

	vcrTest(t, resource.TestCase{
		PreCheck:  func() { testAccPreCheck(t) },
		Providers: testAccProviders,
		Steps: []resource.TestStep{
			{
				Config: testAccLoggingBucketConfigProject_basic(context, 30),
			},
			{
				ResourceName:            "google_logging_project_bucket_config.basic",
				ImportState:             true,
				ImportStateVerify:       true,
				ImportStateVerifyIgnore: []string{"project"},
			},
			{
				Config: testAccLoggingBucketConfigProject_basic(context, 40),
			},
			{
				ResourceName:            "google_logging_project_bucket_config.basic",
				ImportState:             true,
				ImportStateVerify:       true,
				ImportStateVerifyIgnore: []string{"project"},
			},
		},
	})
}

func TestAccLoggingBucketConfigBillingAccount_basic(t *testing.T) {
	t.Parallel()

	context := map[string]interface{}{
		"random_suffix":        randString(t, 10),
		"billing_account_name": "billingAccounts/" + getTestBillingAccountFromEnv(t),
		"org_id":               getTestOrgFromEnv(t),
	}

	vcrTest(t, resource.TestCase{
		PreCheck:  func() { testAccPreCheck(t) },
		Providers: testAccProviders,
		Steps: []resource.TestStep{
			{
				Config: testAccLoggingBucketConfigBillingAccount_basic(context, 30),
			},
			{
				ResourceName:            "google_logging_billing_account_bucket_config.basic",
				ImportState:             true,
				ImportStateVerify:       true,
				ImportStateVerifyIgnore: []string{"billing_account"},
			},
			{
				Config: testAccLoggingBucketConfigBillingAccount_basic(context, 40),
			},
			{
				ResourceName:            "google_logging_billing_account_bucket_config.basic",
				ImportState:             true,
				ImportStateVerify:       true,
				ImportStateVerifyIgnore: []string{"billing_account"},
			},
		},
	})
}

func TestAccLoggingBucketConfigOrganization_basic(t *testing.T) {
	t.Parallel()

	context := map[string]interface{}{
		"random_suffix": randString(t, 10),
		"org_id":        getTestOrgFromEnv(t),
	}

	vcrTest(t, resource.TestCase{
		PreCheck:  func() { testAccPreCheck(t) },
		Providers: testAccProviders,
		Steps: []resource.TestStep{
			{
				Config: testAccLoggingBucketConfigOrganization_basic(context, 30),
			},
			{
				ResourceName:            "google_logging_organization_bucket_config.basic",
				ImportState:             true,
				ImportStateVerify:       true,
				ImportStateVerifyIgnore: []string{"organization"},
			},
			{
				Config: testAccLoggingBucketConfigOrganization_basic(context, 40),
			},
			{
				ResourceName:            "google_logging_organization_bucket_config.basic",
				ImportState:             true,
				ImportStateVerify:       true,
				ImportStateVerifyIgnore: []string{"organization"},
			},
		},
	})
}

func testAccLoggingBucketConfigFolder_basic(context map[string]interface{}, retention int) string {
	return fmt.Sprintf(Nprintf(`
resource "google_folder" "default" {
	display_name = "%{folder_name}"
	parent       = "organizations/%{org_id}"
}

resource "google_logging_folder_bucket_config" "basic" {
	folder    = google_folder.default.name
	location  = "global"
	retention_days = %d
	description = "retention test %d days"
	bucket_id = "_Default"
}
`, context), retention, retention)
}

func testAccLoggingBucketConfigProject_basic(context map[string]interface{}, retention int) string {
	return fmt.Sprintf(Nprintf(`
resource "google_project" "default" {
	project_id = "%{project_name}"
	name       = "%{project_name}"
	org_id     = "%{org_id}"
}

resource "google_logging_project_bucket_config" "basic" {
	project    = google_project.default.name
	location  = "global"
	retention_days = %d
	description = "retention test %d days"
	bucket_id = "_Default"
}
`, context), retention, retention)
}

func TestAccLoggingBucketConfig_CreateBuckets_withCustomId(t *testing.T) {
	t.Parallel()

	context := map[string]interface{}{
		"random_suffix":        randString(t, 10),
		"billing_account_name": "billingAccounts/" + getTestBillingAccountFromEnv(t),
		"org_id":               getTestOrgFromEnv(t),
		"project_name":         "tf-test-" + randString(t, 10),
		"bucket_id":            "tf-test-bucket-" + randString(t, 10),
	}

	configList := getLoggingBucketConfigs(context)

	for res, config := range configlst {
		vcrTest(t, resource.TestCase{
			PreCheck:  func() { testAccPreCheck(t) },
			Providers: testAccProviders,
			Steps: []resource.TestStep{
				{
					Config: config,
				},
				{
					ResourceName:            fmt.Sprintf("google_logging_%s_bucket_config.basic", res),
					ImportState:             true,
					ImportStateVerify:       true,
					ImportStateVerifyIgnore: []string{res},
				},
			},
		})
	}
}

func testAccLoggingBucketConfigBillingAccount_basic(context map[string]interface{}, retention int) string {
	return fmt.Sprintf(Nprintf(`

data "google_billing_account" "default" {
	billing_account = "%{billing_account_name}"
}

resource "google_logging_billing_account_bucket_config" "basic" {
	billing_account    = data.google_billing_account.default.billing_account
	location  = "global"
	retention_days = %d
	description = "retention test %d days"
	bucket_id = "_Default"
}
`, context), retention, retention)
}

func testAccLoggingBucketConfigOrganization_basic(context map[string]interface{}, retention int) string {
	return fmt.Sprintf(Nprintf(`
data "google_organization" "default" {
	organization = "%{org_id}"
}

resource "google_logging_organization_bucket_config" "basic" {
	organization    = data.google_organization.default.organization
	location  = "global"
	retention_days = %d
	description = "retention test %d days"
	bucket_id = "_Default"
}
`, context), retention, retention)
}

func getLoggingBucketConfigs(context map[string]interface{}) map[string]string {

	return map[string]string{
		"project": Nprintf(`resource "google_project" "default" {
				project_id = "%{project_name}"
				name       = "%{project_name}"
				org_id     = "%{org_id}"
			}

			resource "google_logging_project_bucket_config" "basic" {
				project    = google_project.default.name
				location  = "global"
				retention_days = 10
				description = "retention test 10 days"
				bucket_id = "%{bucket_id}"
			}`, context),
	}

}
<commit_msg>update variable name configList (#4090)<commit_after>package google

import (
	"fmt"
	"testing"

	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

func TestAccLoggingBucketConfigFolder_basic(t *testing.T) {
	t.Parallel()

	context := map[string]interface{}{
		"random_suffix": randString(t, 10),
		"folder_name":   "tf-test-" + randString(t, 10),
		"org_id":        getTestOrgFromEnv(t),
	}

	vcrTest(t, resource.TestCase{
		PreCheck:  func() { testAccPreCheck(t) },
		Providers: testAccProviders,
		Steps: []resource.TestStep{
			{
				Config: testAccLoggingBucketConfigFolder_basic(context, 30),
			},
			{
				ResourceName:            "google_logging_folder_bucket_config.basic",
				ImportState:             true,
				ImportStateVerify:       true,
				ImportStateVerifyIgnore: []string{"folder"},
			},
			{
				Config: testAccLoggingBucketConfigFolder_basic(context, 40),
			},
			{
				ResourceName:            "google_logging_folder_bucket_config.basic",
				ImportState:             true,
				ImportStateVerify:       true,
				ImportStateVerifyIgnore: []string{"folder"},
			},
		},
	})
}

func TestAccLoggingBucketConfigProject_basic(t *testing.T) {
	t.Parallel()

	context := map[string]interface{}{
		"random_suffix": randString(t, 10),
		"project_name":  "tf-test-" + randString(t, 10),
		"org_id":        getTestOrgFromEnv(t),
	}

	vcrTest(t, resource.TestCase{
		PreCheck:  func() { testAccPreCheck(t) },
		Providers: testAccProviders,
		Steps: []resource.TestStep{
			{
				Config: testAccLoggingBucketConfigProject_basic(context, 30),
			},
			{
				ResourceName:            "google_logging_project_bucket_config.basic",
				ImportState:             true,
				ImportStateVerify:       true,
				ImportStateVerifyIgnore: []string{"project"},
			},
			{
				Config: testAccLoggingBucketConfigProject_basic(context, 40),
			},
			{
				ResourceName:            "google_logging_project_bucket_config.basic",
				ImportState:             true,
				ImportStateVerify:       true,
				ImportStateVerifyIgnore: []string{"project"},
			},
		},
	})
}

func TestAccLoggingBucketConfigBillingAccount_basic(t *testing.T) {
	t.Parallel()

	context := map[string]interface{}{
		"random_suffix":        randString(t, 10),
		"billing_account_name": "billingAccounts/" + getTestBillingAccountFromEnv(t),
		"org_id":               getTestOrgFromEnv(t),
	}

	vcrTest(t, resource.TestCase{
		PreCheck:  func() { testAccPreCheck(t) },
		Providers: testAccProviders,
		Steps: []resource.TestStep{
			{
				Config: testAccLoggingBucketConfigBillingAccount_basic(context, 30),
			},
			{
				ResourceName:            "google_logging_billing_account_bucket_config.basic",
				ImportState:             true,
				ImportStateVerify:       true,
				ImportStateVerifyIgnore: []string{"billing_account"},
			},
			{
				Config: testAccLoggingBucketConfigBillingAccount_basic(context, 40),
			},
			{
				ResourceName:            "google_logging_billing_account_bucket_config.basic",
				ImportState:             true,
				ImportStateVerify:       true,
				ImportStateVerifyIgnore: []string{"billing_account"},
			},
		},
	})
}

func TestAccLoggingBucketConfigOrganization_basic(t *testing.T) {
	t.Parallel()

	context := map[string]interface{}{
		"random_suffix": randString(t, 10),
		"org_id":        getTestOrgFromEnv(t),
	}

	vcrTest(t, resource.TestCase{
		PreCheck:  func() { testAccPreCheck(t) },
		Providers: testAccProviders,
		Steps: []resource.TestStep{
			{
				Config: testAccLoggingBucketConfigOrganization_basic(context, 30),
			},
			{
				ResourceName:            "google_logging_organization_bucket_config.basic",
				ImportState:             true,
				ImportStateVerify:       true,
				ImportStateVerifyIgnore: []string{"organization"},
			},
			{
				Config: testAccLoggingBucketConfigOrganization_basic(context, 40),
			},
			{
				ResourceName:            "google_logging_organization_bucket_config.basic",
				ImportState:             true,
				ImportStateVerify:       true,
				ImportStateVerifyIgnore: []string{"organization"},
			},
		},
	})
}

func testAccLoggingBucketConfigFolder_basic(context map[string]interface{}, retention int) string {
	return fmt.Sprintf(Nprintf(`
resource "google_folder" "default" {
	display_name = "%{folder_name}"
	parent       = "organizations/%{org_id}"
}

resource "google_logging_folder_bucket_config" "basic" {
	folder    = google_folder.default.name
	location  = "global"
	retention_days = %d
	description = "retention test %d days"
	bucket_id = "_Default"
}
`, context), retention, retention)
}

func testAccLoggingBucketConfigProject_basic(context map[string]interface{}, retention int) string {
	return fmt.Sprintf(Nprintf(`
resource "google_project" "default" {
	project_id = "%{project_name}"
	name       = "%{project_name}"
	org_id     = "%{org_id}"
}

resource "google_logging_project_bucket_config" "basic" {
	project    = google_project.default.name
	location  = "global"
	retention_days = %d
	description = "retention test %d days"
	bucket_id = "_Default"
}
`, context), retention, retention)
}

func TestAccLoggingBucketConfig_CreateBuckets_withCustomId(t *testing.T) {
	t.Parallel()

	context := map[string]interface{}{
		"random_suffix":        randString(t, 10),
		"billing_account_name": "billingAccounts/" + getTestBillingAccountFromEnv(t),
		"org_id":               getTestOrgFromEnv(t),
		"project_name":         "tf-test-" + randString(t, 10),
		"bucket_id":            "tf-test-bucket-" + randString(t, 10),
	}

	configList := getLoggingBucketConfigs(context)

	for res, config := range configList {
		vcrTest(t, resource.TestCase{
			PreCheck:  func() { testAccPreCheck(t) },
			Providers: testAccProviders,
			Steps: []resource.TestStep{
				{
					Config: config,
				},
				{
					ResourceName:            fmt.Sprintf("google_logging_%s_bucket_config.basic", res),
					ImportState:             true,
					ImportStateVerify:       true,
					ImportStateVerifyIgnore: []string{res},
				},
			},
		})
	}
}

func testAccLoggingBucketConfigBillingAccount_basic(context map[string]interface{}, retention int) string {
	return fmt.Sprintf(Nprintf(`

data "google_billing_account" "default" {
	billing_account = "%{billing_account_name}"
}

resource "google_logging_billing_account_bucket_config" "basic" {
	billing_account    = data.google_billing_account.default.billing_account
	location  = "global"
	retention_days = %d
	description = "retention test %d days"
	bucket_id = "_Default"
}
`, context), retention, retention)
}

func testAccLoggingBucketConfigOrganization_basic(context map[string]interface{}, retention int) string {
	return fmt.Sprintf(Nprintf(`
data "google_organization" "default" {
	organization = "%{org_id}"
}

resource "google_logging_organization_bucket_config" "basic" {
	organization    = data.google_organization.default.organization
	location  = "global"
	retention_days = %d
	description = "retention test %d days"
	bucket_id = "_Default"
}
`, context), retention, retention)
}

func getLoggingBucketConfigs(context map[string]interface{}) map[string]string {

	return map[string]string{
		"project": Nprintf(`resource "google_project" "default" {
				project_id = "%{project_name}"
				name       = "%{project_name}"
				org_id     = "%{org_id}"
			}

			resource "google_logging_project_bucket_config" "basic" {
				project    = google_project.default.name
				location  = "global"
				retention_days = 10
				description = "retention test 10 days"
				bucket_id = "%{bucket_id}"
			}`, context),
	}

}
<|endoftext|>


<commit_before>// myLG is command line looking glass that written with Go language
// it tries from its own icmp and external looking glasses tools
package main

import (
	"errors"
	"github.com/briandowns/spinner"
	"github.com/mehrdadrad/mylg/cli"
	"github.com/mehrdadrad/mylg/icmp"
	"github.com/mehrdadrad/mylg/lg"
	"github.com/mehrdadrad/mylg/ripe"
	"net"
	"regexp"
	"strings"
	"time"
)

type Provider interface {
	Set(host, version string)
	GetDefaultNode() string
	GetNodes() map[string]string
	ChangeNode(node string)
	Ping() (string, error)
}

var (
	providers = map[string]Provider{"telia": new(lg.Telia), "level3": new(lg.Level3), "cogent": new(lg.Cogent)}
	pNames    = providerNames()
)

func providerNames() map[string]string {
	pNames := map[string]string{}
	for p := range providers {
		pNames[p] = p
	}
	return pNames
}

func validateProvider(p string) (string, error) {
	pNames := []string{}
	match, _ := regexp.MatchString("("+strings.Join(pNames, "|")+")", p)
	p = strings.ToLower(p)
	if match {
		return p, nil
	} else {
		return "", errors.New("provider not support")
	}
}

func main() {
	var (
		err     error
		request string
		loop    bool   = true
		cPName  string = "local"
	)

	rep := make(chan string, 1)
	req := make(chan string, 1)
	nxt := make(chan struct{}, 1)

	c := cli.Init("local")
	c.UpdateCompleter("connect", pNames)
	go c.Run(req, nxt)

	r, _ := regexp.Compile(`(ping|connect|node|local|asn|help|exit|quit)\s{0,1}(.*)`)
	s := spinner.New(spinner.CharSets[26], 220*time.Millisecond)

	for loop {
		select {
		case request, loop = <-req:
			if !loop {
				break
			}
			subReq := r.FindStringSubmatch(request)
			if len(subReq) == 0 {
				println("syntax error")
				nxt <- struct{}{}
				continue
			}
			cmd := strings.TrimSpace(subReq[1])
			args := strings.TrimSpace(subReq[2])
			switch {
			case cmd == "ping" && cPName == "local":
				p := icmp.NewPing()
				ra, err := net.ResolveIPAddr("ip", args)
				if err != nil {
					println("cannot resolve", args, ": Unknown host")
					nxt <- struct{}{}
					continue
				}
				p.IP(ra.String())
				for n := 0; n < 4; n++ {
					p.Ping(rep)
					println(<-rep)
				}
				nxt <- struct{}{}
			case cmd == "ping":
				s.Prefix = "please wait "
				s.Start()
				providers[cPName].Set(args, "ipv4")
				m, _ := providers[cPName].Ping()
				s.Stop()
				println(m)
				nxt <- struct{}{}
			case cmd == "node":
				if _, ok := providers[cPName]; ok {
					providers[cPName].ChangeNode(args)
					c.SetPrompt(cPName + "/" + args)
				} else {
					println("it doesn't support")
				}
				nxt <- struct{}{}
			case cmd == "local":
				cPName = "local"
				c.SetPrompt(cPName)
				nxt <- struct{}{}
			case cmd == "connect":
				var pName string
				if pName, err = validateProvider(args); err != nil {
					println("provider not available")
					nxt <- struct{}{}
					continue
				}
				cPName = pName
				if _, ok := providers[cPName]; ok {
					c.SetPrompt(cPName + "/" + providers[cPName].GetDefaultNode())
					go func() {
						c.UpdateCompleter("node", providers[cPName].GetNodes())
					}()
				} else {
					println("it doesn't support")
				}
				nxt <- struct{}{}
			case cmd == "asn":
				asn := ripe.ASN{Number: args}
				asn.GetData()
				asn.PrettyPrint()
				nxt <- struct{}{}
			case cmd == "mode":
				// todo
			case cmd == "help":
				c.Help()
				nxt <- struct{}{}
			case cmd == "exit", cmd == "quit":
				c.Close(nxt)
				close(req)
				// todo
			}
		}
	}
}
<commit_msg>added lg/mode/dns handlers and replace nxt with next method<commit_after>// myLG is command line looking glass that written with Go language
// it tries from its own icmp and external looking glasses tools
package main

import (
	"errors"
	"github.com/briandowns/spinner"
	"github.com/mehrdadrad/mylg/cli"
	"github.com/mehrdadrad/mylg/dns"
	"github.com/mehrdadrad/mylg/icmp"
	"github.com/mehrdadrad/mylg/lg"
	"github.com/mehrdadrad/mylg/ripe"
	"net"
	"regexp"
	"strings"
	"time"
)

type Provider interface {
	Set(host, version string)
	GetDefaultNode() string
	GetNodes() []string
	ChangeNode(node string)
	Ping() (string, error)
}

var (
	providers = map[string]Provider{"telia": new(lg.Telia), "level3": new(lg.Level3), "cogent": new(lg.Cogent)}
	pNames    = providerNames()
)

func providerNames() []string {
	pNames := []string{}
	for p := range providers {
		pNames = append(pNames, p)
	}
	return pNames
}

func validateProvider(p string) (string, error) {
	pNames := []string{}
	match, _ := regexp.MatchString("("+strings.Join(pNames, "|")+")", p)
	p = strings.ToLower(p)
	if match {
		return p, nil
	} else {
		return "", errors.New("provider not support")
	}
}

func main() {
	var (
		err     error
		request string
		loop    bool   = true
		cPName  string = "local"
	)

	rep := make(chan string, 1)
	req := make(chan string, 1)
	nxt := make(chan struct{}, 1)

	c := cli.Init("local")
	go c.Run(req, nxt)

	r, _ := regexp.Compile(`(ping|lg|dns|asn|connect|node|local|mode|help|exit|quit)\s{0,1}(.*)`)
	s := spinner.New(spinner.CharSets[26], 220*time.Millisecond)

	for loop {
		select {
		case request, loop = <-req:
			if !loop {
				break
			}
			subReq := r.FindStringSubmatch(request)
			if len(subReq) == 0 {
				println("syntax error")
				c.Next()
				continue
			}
			prompt := c.GetPrompt()
			cmd := strings.TrimSpace(subReq[1])
			args := strings.TrimSpace(subReq[2])
			switch {
			case cmd == "ping" && cPName == "local":
				p := icmp.NewPing()
				ra, err := net.ResolveIPAddr("ip", args)
				if err != nil {
					println("cannot resolve", args, ": Unknown host")
					c.Next()
					continue
				}
				p.IP(ra.String())
				for n := 0; n < 4; n++ {
					p.Ping(rep)
					println(<-rep)
				}
				c.Next()
			case cmd == "ping":
				s.Prefix = "please wait "
				s.Start()
				providers[cPName].Set(args, "ipv4")
				m, _ := providers[cPName].Ping()
				s.Stop()
				println(m)
				c.Next()
			case cmd == "node":
				if _, ok := providers[cPName]; ok {
					providers[cPName].ChangeNode(args)
					c.SetPrompt(cPName + "/" + args)
				} else {
					println("it doesn't support")
				}
				c.Next()
			case cmd == "local":
				cPName = "local"
				c.SetPrompt(cPName)
				c.Next()
			case cmd == "lg":
				c.SetPrompt("lg")
				c.UpdateCompleter("connect", pNames)
				c.Next()
			case cmd == "connect":
				if strings.HasPrefix(prompt, "dns") {
					println("todo")
				} else {
					var pName string
					if pName, err = validateProvider(args); err != nil {
						println("provider not available")
						c.Next()
						continue
					}
					cPName = pName
					if _, ok := providers[cPName]; ok {
						c.SetPrompt(cPName + "/" + providers[cPName].GetDefaultNode())
						go func() {
							c.UpdateCompleter("node", providers[cPName].GetNodes())
						}()
					} else {
						println("it doesn't support")
					}
				}
				c.Next()
			case cmd == "dns":
				d := dns.NewRequest()
				go d.Init(c)
				c.Next()
			case cmd == "asn":
				asn := ripe.ASN{Number: args}
				asn.GetData()
				asn.PrettyPrint()
				c.Next()
			case cmd == "mode":
				if args == "vim" {
					c.SetVim()
				} else if args == "emacs" {
					c.SetEmacs()
				} else {
					println("the request mode doesn't support")
				}
				c.Next()
			case cmd == "help":
				c.Help()
				c.Next()
			case cmd == "exit", cmd == "quit":
				c.Close(nxt)
				close(req)
				// todo
			}
		}
	}
}
<|endoftext|>


<commit_before>package command

import (
	"os"

	log "github.com/Sirupsen/logrus"

	"github.com/luizbafilho/fusis/api"
	"github.com/luizbafilho/fusis/config"
	"github.com/luizbafilho/fusis/fusis"
	"github.com/luizbafilho/fusis/net"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

var conf config.BalancerConfig

func init() {
	FusisCmd.AddCommand(NewBalancerCommand())
}

func NewBalancerCommand() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "balancer [options]",
		Short: "starts a new balancer",
		Long: `fusis balancer is the command used to run the balancer process.

	It's responsible for creating new Services and watching for Agents joining the cluster,
	and add routes to them in the Load Balancer.`,
		PreRun: func(cmd *cobra.Command, args []string) {
			viper.Unmarshal(&conf)
		},
		RunE: balancerCommandFunc,
	}

	setupBalancerCmdFlags(cmd)

	return cmd
}

func setupBalancerCmdFlags(cmd *cobra.Command) {
	hostname, _ := os.Hostname()
	cmd.Flags().StringVarP(&conf.Name, "name", "n", hostname, "node name (unique in the cluster)")
	cmd.Flags().StringVarP(&conf.Interface, "interface", "", "eth0", "Network interface")
	cmd.Flags().StringVarP(&conf.ConfigPath, "config-path", "", "/etc/fusis", "Configuration directory")
	cmd.Flags().BoolVar(&conf.Bootstrap, "bootstrap", false, "starts balancer in boostrap mode")
	cmd.Flags().BoolVar(&conf.DevMode, "dev", false, "Initialize balancer in dev mode")
	cmd.Flags().StringSliceVarP(&conf.Join, "join", "j", []string{}, "Join balancer pool")

	err := viper.BindPFlags(cmd.Flags())
	if err != nil {
		log.Errorf("error binding pflags: %v", err)
	}
}

func balancerCommandFunc(cmd *cobra.Command, args []string) error {
	if err := net.SetIpForwarding(); err != nil {
		log.Warn("Fusis couldn't set net.ipv4.ip_forward=1")
		log.Fatal(err)
	}

	balancer, err := fusis.NewBalancer(&conf)
	if err != nil {
		log.Fatal(err)
	}

	if len(conf.Join) > 0 {
		balancer.JoinPool()
	}

	apiService := api.NewAPI(balancer)
	go apiService.Serve()

	waitSignals(balancer)

	return nil
}
<commit_msg>Added LogInterval as a command line option argument<commit_after>package command

import (
	"os"

	log "github.com/Sirupsen/logrus"

	"github.com/luizbafilho/fusis/api"
	"github.com/luizbafilho/fusis/config"
	"github.com/luizbafilho/fusis/fusis"
	"github.com/luizbafilho/fusis/net"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

var conf config.BalancerConfig

func init() {
	FusisCmd.AddCommand(NewBalancerCommand())
}

func NewBalancerCommand() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "balancer [options]",
		Short: "starts a new balancer",
		Long: `fusis balancer is the command used to run the balancer process.

	It's responsible for creating new Services and watching for Agents joining the cluster,
	and add routes to them in the Load Balancer.`,
		PreRun: func(cmd *cobra.Command, args []string) {
			viper.Unmarshal(&conf)
		},
		RunE: balancerCommandFunc,
	}

	setupBalancerCmdFlags(cmd)

	return cmd
}

func setupBalancerCmdFlags(cmd *cobra.Command) {
	hostname, _ := os.Hostname()
	cmd.Flags().StringVarP(&conf.Name, "name", "n", hostname, "node name (unique in the cluster)")
	cmd.Flags().StringVarP(&conf.Interface, "interface", "", "eth0", "Network interface")
	cmd.Flags().StringVarP(&conf.ConfigPath, "config-path", "", "/etc/fusis", "Configuration directory")
	cmd.Flags().BoolVar(&conf.Bootstrap, "bootstrap", false, "starts balancer in boostrap mode")
	cmd.Flags().BoolVar(&conf.DevMode, "dev", false, "Initialize balancer in dev mode")
	cmd.Flags().StringSliceVarP(&conf.Join, "join", "j", []string{}, "Join balancer pool")
    cmd.Flags().Uint16VarP(&conf.LogInterval, "log-interval", "i", 0, "Number in seconds of the frequency of statistics collection from ip_vs")
	err := viper.BindPFlags(cmd.Flags())
	if err != nil {
		log.Errorf("error binding pflags: %v", err)
	}
}

func balancerCommandFunc(cmd *cobra.Command, args []string) error {
	if err := net.SetIpForwarding(); err != nil {
		log.Warn("Fusis couldn't set net.ipv4.ip_forward=1")
		log.Fatal(err)
	}

	balancer, err := fusis.NewBalancer(&conf)
	if err != nil {
		log.Fatal(err)
	}

	if len(conf.Join) > 0 {
		balancer.JoinPool()
	}

	apiService := api.NewAPI(balancer)
	go apiService.Serve()

	waitSignals(balancer)

	return nil
}
<|endoftext|>


<commit_before>package command

/*
 Cribbed **heavily** from https://github.com/hashicorp/consul
*/

import (
	"fmt"
	"github.com/mitchellh/cli"
	"os"
	"log"
	"strings"
	"github.com/PolkaBand/polka/utils"
	"text/template"
)

type GenerateCommand struct {
	Name string
	Ui   cli.Ui
}

type Concept struct {
	Name string
}

func (c *GenerateCommand) Help() string {
	helpText := `
Usage: polka generate [subcommand] concept

Generate a lambda function of type [subcommand] to implement the concept.

Subcommands:

	endpoint	an endpoint that supports CRUD and a health check on (concept)\n
`
	return strings.TrimSpace(helpText)
}

func GetEndpoints() []string {
	endpoints := []string{
		"create.js",
		"read.js",
		"update.js",
		"delete.js",
		"health.js",
	}
	return endpoints
}

func MakeAllEndpoints(name string) {
	concept := Concept{name}
	for _, templateName := range GetEndpoints() {
		FindAndExecuteTemplate(templateName, concept)
	}
}

func MakeEndpointDir() (string, error) {
	if appDir, err := GetAppDir(); err == nil {
		endpointDir := fmt.Sprintf("%v/app/endpoint", appDir )
		log.Printf("trying to make %v\n", endpointDir )
		if err := os.MkdirAll(endpointDir, 0777); err == nil {
			log.Printf("should have made %v\n", endpointDir )
			return endpointDir, nil
		} else {
			return "", err
		}
	} else {
		return "", err
	}
}

func FindAndExecuteTemplate(templateName string, concept Concept) {

	if templateDir, err := utils.FindTemplateDir(); err == nil {

		if endpointDir, err := MakeEndpointDir(); err == nil {
			//TODO assume that js is the only implementation language for now
			templatesGlob := fmt.Sprintf("%v/js/endpoint/*.js", templateDir )

			if t, err := template.ParseGlob(templatesGlob); err == nil {

				outputFileName := fmt.Sprintf("%v/%v", endpointDir, templateName )
				log.Println(outputFileName)

				outputFilename, err := os.Create(outputFileName)

				if err = t.ExecuteTemplate(outputFilename, templateName, concept); err != nil {
					log.Fatal(err)
				}
			}
		}
	}
}

func (c *GenerateCommand) Run(args []string) int {
	if len(args) < 2 {
		fmt.Printf("%v", c.Help())
		return 1
	}

	subcommand := args[0]

	switch subcommand {
	case "endpoint":
		MakeAllEndpoints(args[1])
	case "integration":
		log.Println("generating integrations are not implemented yet")
	}

	return 0
}

func (c *GenerateCommand) Synopsis() string {
	return "generates lambda functions for endpoints"
}
<commit_msg>refactored generate command<commit_after>package command

/*
 Cribbed **heavily** from https://github.com/hashicorp/consul
*/

import (
	"fmt"
	"github.com/mitchellh/cli"
	"os"
	"log"
	"strings"
	"github.com/PolkaBand/polka/utils"
	"text/template"
)

type GenerateCommand struct {
	Name string
	Ui   cli.Ui
}

type Concept struct {
	Name string
}

func (c *GenerateCommand) Help() string {
	helpText := `
Usage: polka generate [subcommand] concept

Generate a lambda function of type [subcommand] to implement the concept.

Subcommands:

	endpoint	an endpoint that supports CRUD and a health check on (concept)\n
`
	return strings.TrimSpace(helpText)
}

func GetEndpoints() []string {
	endpoints := []string{
		"create.js",
		"read.js",
		"update.js",
		"delete.js",
		"health.js",
	}
	return endpoints
}

func MakeAllEndpoints(name string) {
	concept := Concept{name}
	for _, templateName := range GetEndpoints() {
		FindAndExecuteTemplate(templateName, concept)
	}
}

func MakeEndpointDir() (string, error) {
	if appDir, err := GetAppDir(); err == nil {
		endpointDir := fmt.Sprintf("%v/app/endpoint", appDir )
		log.Printf("trying to make %v\n", endpointDir )
		if err := os.MkdirAll(endpointDir, 0777); err == nil {
			log.Printf("should have made %v\n", endpointDir )
			return endpointDir, nil
		} else {
			return "", err
		}
	} else {
		return "", err
	}
}

func FindAndExecuteTemplate(templateName string, concept Concept) {

	if templateDir, err := utils.FindTemplateDir(); err == nil {

		if endpointDir, err := MakeEndpointDir(); err == nil {
			//TODO assume that js is the only implementation language for now
			templatesGlob := fmt.Sprintf("%v/js/endpoint/*.js", templateDir )

			if t, err := template.ParseGlob(templatesGlob); err == nil {

				outputFileName := fmt.Sprintf("%v/%v", endpointDir, templateName )
				log.Println(outputFileName)

				outputFile, err := os.Create(outputFileName)

				if err = t.ExecuteTemplate(outputFile, templateName, concept); err != nil {
					log.Fatal(err)
				}
			}
		}
	}
}

func (c *GenerateCommand) Run(args []string) int {
	if len(args) < 2 {
		fmt.Printf("%v", c.Help())
		return 1
	}

	subcommand := args[0]

	switch subcommand {
	case "endpoint":
		MakeAllEndpoints(args[1])
	case "integration":
		log.Println("generating integrations are not implemented yet")
	}

	return 0
}

func (c *GenerateCommand) Synopsis() string {
	return "generates lambda functions for endpoints"
}
<|endoftext|>


<commit_before>package commands

import (
	"fmt"
	"context"
	"os"
	"io/ioutil"
	"os/user"
	"path"

	"github.com/urfave/cli"
	"github.com/cbegin/graven/domain"
	"github.com/google/go-github/github"
	"golang.org/x/oauth2"
	"gopkg.in/yaml.v2"
	"github.com/bgentry/speakeasy"
	"github.com/cbegin/graven/util"
	"strings"
)

type ConfigMap map[string]map[string]string
type Validator func(stdout, stderr string) error

var ReleaseCommand = cli.Command{
	Name: "release",
	Usage:       "Releases artifacts to repositories",
	Action: release,
	Flags: []cli.Flag{
		cli.BoolFlag{
			Name: "login",
			Usage: "Prompts for repo login credentials.",
		},
	},
}

func release(c *cli.Context) error {
	project, err := domain.FindProject()
	if err != nil {
		return err
	}

	if err := verifyRepoState(project); err != nil {
		return err
	}

	if c.Bool("login") {
		return loginToGithub()
	}

	if err := pkg(c); err != nil {
		return err
	}

	return releaseToGithub(project)
}

func loginToGithub() error {
	token, err := readSecret("Please type or paste a github token (will not echo): ")
	config, err := readConfig()
	if err != nil {
		config = ConfigMap{}
	}
	config["github"] = map[string]string{}
	config["github"]["token"] = token
	err = writeConfig(config)
	if err != nil {
		return fmt.Errorf("Error writing configuration file. %v", err)
	}
	return nil
}

func releaseToGithub(project *domain.Project) error {

	gh, ctx, err := authenticate()
	if err != nil {
		return err
	}

	repo, ok := project.Repositories["github"]
	if !ok {
		return fmt.Errorf("Sorry, could not find gihub repo configuration")
	}

	ownerName := repo["owner"]
	repoName := repo["repo"]

	tagName := fmt.Sprintf("v%s", project.Version)
	releaseName := tagName
	release := &github.RepositoryRelease{
		TagName: &tagName,
		Name: &releaseName,
	}

	release, _, err = gh.Repositories.CreateRelease(ctx, ownerName, repoName, release)
	if err != nil {
		return err
	}
	fmt.Printf("Created release %v/%v:%v\n", ownerName, repoName, *release.Name)

	for _, a := range project.Artifacts {
		filename := a.ArtifactFile(project)
		sourceFile, err := os.Open(project.TargetPath(filename))
		if err != nil {
			return err
		}
		opts := &github.UploadOptions{
			Name: filename,
		}
		_, _, err = gh.Repositories.UploadReleaseAsset(ctx, ownerName, repoName, *release.ID, opts, sourceFile)
		if err != nil {
			return err
		}
		fmt.Printf("Uploaded %v/%v/%v\n", ownerName, repoName, filename)
	}

	return err
}

func authenticate() (*github.Client, context.Context, error) {
	config, err := readConfig()
	if err != nil {
		return nil, nil, fmt.Errorf("Error reading configuration (try: release --login): %v", err)
	}

	ctx := context.Background()
	ts := oauth2.StaticTokenSource(
		&oauth2.Token{AccessToken: config["github"]["token"]},
	)
	tc := oauth2.NewClient(ctx, ts)

	client := github.NewClient(tc)

	return client, ctx, nil
}

func readSecret(prompt string) (string, error) {
	password, err := speakeasy.Ask(prompt)
	if err != nil {
		return "", fmt.Errorf("Error reading secret from terminal: %v", err)
	}
	return password, nil
}

func readConfig() (ConfigMap, error) {
	usr, err := user.Current()
	if err != nil {
		return nil, err
	}
	file, err := os.Open(path.Join(usr.HomeDir, ".graven.yaml"))
	if err != nil {
		return nil, err
	}
	bytes, err := ioutil.ReadAll(file)
	if err != nil {
		return nil, err
	}
	config := ConfigMap{}
	err = yaml.Unmarshal(bytes, config)
	if err != nil {
		return nil, err
	}
	return config, nil
}

func writeConfig(config ConfigMap) (error) {
	usr, err := user.Current()
	if err != nil {
		return err
	}
	bytes, err := yaml.Marshal(config)
	if err != nil {
		return err
	}
	err = ioutil.WriteFile(path.Join(usr.HomeDir, ".graven.yaml"), bytes, 0600)
	if err != nil {
		return err
	}

	return nil
}

func verifyRepoState(project *domain.Project) error {
	remoteName := "origin"
	branchName := "master"

	// Check if on expected branch (e.g. master)
	if err := verifyGitState(func(stdout, stderr string) error {
		actualBranch := strings.TrimSpace(stdout)
		if actualBranch != branchName {
			return fmt.Errorf("Expected to be on branch %v but found branch %v", branchName, actualBranch)
		}
		return nil
	}, project, "rev-parse", "--abbrev-ref", "HEAD"); err != nil {
		return err
	}

	// Ensure no uncommitted changes
	if err := verifyGitState(func(stdout, stderr string) error {
		if strings.TrimSpace(stdout) != "" || strings.TrimSpace(stderr) != "" {
			return fmt.Errorf("Cannot release with uncommitted changes.")
		}
		return nil
	}, project, "status", "--porcelain"); err != nil {
		return err
	}

	// Check if changes exist on server
	if err := verifyGitState(func(stdout, stderr string) error {
		lineCount := len(strings.Split(strings.TrimSpace(stderr), "\n"))
		if lineCount > 2 {
			return fmt.Errorf("Changes were detected on the remote %v for branch %v.", remoteName, branchName)
		}
		return nil
	}, project, "fetch", "--dry-run", remoteName, branchName); err != nil {
		return err
	}

	// Check if local changes are pushed
	if err := verifyGitState(func(stdout, stderr string) error {
		parts := strings.Split(strings.TrimSpace(stdout), "\n")
		if strings.TrimSpace(parts[0]) != strings.TrimSpace(parts[1]) {
			return fmt.Errorf("Not all local changes for branch %v have been pushed to remote %v.", branchName, remoteName)
		}
		return nil
	}, project, "rev-parse", branchName, fmt.Sprintf("%v/%v", remoteName, branchName)); err != nil {
		return err
	}

	return nil
}

func verifyGitState(validator Validator, project *domain.Project, args... string) error {
	sout, serr, err := util.RunCommand(project.ProjectPath(), nil, "git", args...)
	if err != nil {
		return fmt.Errorf("ERROR running Git command: %v\n", err)
	}
	return validator(sout, serr)
}<commit_msg>intermediate commit during release testing<commit_after>package commands

import (
	"fmt"
	"context"
	"os"
	"io/ioutil"
	"os/user"
	"path"

	"github.com/urfave/cli"
	"github.com/cbegin/graven/domain"
	"github.com/google/go-github/github"
	"golang.org/x/oauth2"
	"gopkg.in/yaml.v2"
	"github.com/bgentry/speakeasy"
	"github.com/cbegin/graven/util"
	"strings"
)

type ConfigMap map[string]map[string]string
type Validator func(stdout, stderr string) error

var ReleaseCommand = cli.Command{
	Name: "release",
	Usage:       "Releases artifacts to repositories",
	Action: release,
	Flags: []cli.Flag{
		cli.BoolFlag{
			Name: "login",
			Usage: "Prompts for repo login credentials.",
		},
	},
}

func release(c *cli.Context) error {
	project, err := domain.FindProject()
	if err != nil {
		return err
	}

	if err := verifyRepoState(project); err != nil {
		return err
	}

	if c.Bool("login") {
		return loginToGithub()
	}

	if err := pkg(c); err != nil {
		return err
	}

	return releaseToGithub(project)
}

func loginToGithub() error {
	token, err := readSecret("Please type or paste a github token (will not echo): ")
	config, err := readConfig()
	if err != nil {
		config = ConfigMap{}
	}
	config["github"] = map[string]string{}
	config["github"]["token"] = token
	err = writeConfig(config)
	if err != nil {
		return fmt.Errorf("Error writing configuration file. %v", err)
	}
	return nil
}

func releaseToGithub(project *domain.Project) error {

	gh, ctx, err := authenticate()
	if err != nil {
		return err
	}

	repo, ok := project.Repositories["github"]
	if !ok {
		return fmt.Errorf("Sorry, could not find gihub repo configuration")
	}

	ownerName := repo["owner"]
	repoName := repo["repo"]

	tagName := fmt.Sprintf("v%s", project.Version)
	releaseName := tagName
	release := &github.RepositoryRelease{
		TagName: &tagName,
		Name: &releaseName,
	}

	{
		sout, serr, err := util.RunCommand(project.ProjectPath(), nil, "git", "tag", tagName)
		fmt.Println("Tagging  %v\n%v\n%v", sout, serr, err)
	}
	{
		sout, serr, err := util.RunCommand(project.ProjectPath(), nil, "git", "push", "--tags")
		fmt.Println("PushTags %v\n%v\n%v", sout, serr, err)
	}

	release, _, err = gh.Repositories.CreateRelease(ctx, ownerName, repoName, release)
	if err != nil {
		return err
	}
	fmt.Printf("Created release %v/%v:%v\n", ownerName, repoName, *release.Name)

	for _, a := range project.Artifacts {
		filename := a.ArtifactFile(project)
		sourceFile, err := os.Open(project.TargetPath(filename))
		if err != nil {
			return err
		}
		opts := &github.UploadOptions{
			Name: filename,
		}
		_, _, err = gh.Repositories.UploadReleaseAsset(ctx, ownerName, repoName, *release.ID, opts, sourceFile)
		if err != nil {
			return err
		}
		fmt.Printf("Uploaded %v/%v/%v\n", ownerName, repoName, filename)
	}

	return err
}

func authenticate() (*github.Client, context.Context, error) {
	config, err := readConfig()
	if err != nil {
		return nil, nil, fmt.Errorf("Error reading configuration (try: release --login): %v", err)
	}

	ctx := context.Background()
	ts := oauth2.StaticTokenSource(
		&oauth2.Token{AccessToken: config["github"]["token"]},
	)
	tc := oauth2.NewClient(ctx, ts)

	client := github.NewClient(tc)

	return client, ctx, nil
}

func readSecret(prompt string) (string, error) {
	password, err := speakeasy.Ask(prompt)
	if err != nil {
		return "", fmt.Errorf("Error reading secret from terminal: %v", err)
	}
	return password, nil
}

func readConfig() (ConfigMap, error) {
	usr, err := user.Current()
	if err != nil {
		return nil, err
	}
	file, err := os.Open(path.Join(usr.HomeDir, ".graven.yaml"))
	if err != nil {
		return nil, err
	}
	bytes, err := ioutil.ReadAll(file)
	if err != nil {
		return nil, err
	}
	config := ConfigMap{}
	err = yaml.Unmarshal(bytes, config)
	if err != nil {
		return nil, err
	}
	return config, nil
}

func writeConfig(config ConfigMap) (error) {
	usr, err := user.Current()
	if err != nil {
		return err
	}
	bytes, err := yaml.Marshal(config)
	if err != nil {
		return err
	}
	err = ioutil.WriteFile(path.Join(usr.HomeDir, ".graven.yaml"), bytes, 0600)
	if err != nil {
		return err
	}

	return nil
}

func verifyRepoState(project *domain.Project) error {
	remoteName := "origin"
	branchName := "master"

	// Check if on expected branch (e.g. master)
	if err := verifyGitState(func(stdout, stderr string) error {
		actualBranch := strings.TrimSpace(stdout)
		if actualBranch != branchName {
			return fmt.Errorf("Expected to be on branch %v but found branch %v", branchName, actualBranch)
		}
		return nil
	}, project, "rev-parse", "--abbrev-ref", "HEAD"); err != nil {
		return err
	}

	// Ensure no uncommitted changes
	if err := verifyGitState(func(stdout, stderr string) error {
		if strings.TrimSpace(stdout) != "" || strings.TrimSpace(stderr) != "" {
			return fmt.Errorf("Cannot release with uncommitted changes.")
		}
		return nil
	}, project, "status", "--porcelain"); err != nil {
		return err
	}

	// Check if changes exist on server
	if err := verifyGitState(func(stdout, stderr string) error {
		lineCount := len(strings.Split(strings.TrimSpace(stderr), "\n"))
		if lineCount > 2 {
			return fmt.Errorf("Changes were detected on the remote %v for branch %v.", remoteName, branchName)
		}
		return nil
	}, project, "fetch", "--dry-run", remoteName, branchName); err != nil {
		return err
	}

	// Check if local changes are pushed
	if err := verifyGitState(func(stdout, stderr string) error {
		parts := strings.Split(strings.TrimSpace(stdout), "\n")
		if strings.TrimSpace(parts[0]) != strings.TrimSpace(parts[1]) {
			return fmt.Errorf("Not all local changes for branch %v have been pushed to remote %v.", branchName, remoteName)
		}
		return nil
	}, project, "rev-parse", branchName, fmt.Sprintf("%v/%v", remoteName, branchName)); err != nil {
		return err
	}

	return nil
}

func verifyGitState(validator Validator, project *domain.Project, args... string) error {
	sout, serr, err := util.RunCommand(project.ProjectPath(), nil, "git", args...)
	if err != nil {
		return fmt.Errorf("ERROR running Git command: %v\n", err)
	}
	return validator(sout, serr)
}<|endoftext|>