<commit_before>package main

import (
	"fmt"
	"strings"
)

// A Square represents a square on the board in little-endian rank-file order (a1 = 0, a2 = 1, h8 = 63).
// Behavior is undefined for values outside of [0, 64).
type Square byte

// Rank returns the rank of the input Square in the range [0, 7).
func (s Square) Rank() byte { return byte(s >> 3) }

// File returns the file of the input Square in the range [0, 7).
func (s Square) File() byte { return byte(s & 7) }

// Diagonal returns the number of the southwest-northeast diagonal on which the input Square lies, from 0 (h1) to 14 (a8).
func (s Square) Diagonal() byte { return 7 + s.Rank() - s.File() }

// AntiDiagonal returns the number of the northwest-southeast anti-diagonal on which the input Square lies, from 0 (a1) to 14 (h8).
func (s Square) AntiDiagonal() byte { return s.Rank() + s.File() }

// Board returns a Board in which only the bit corresponding to the input Square is set.
func (s Square) Board() Board { return 1 << s }

//go:generate stringer -type=Square
const (
	a1 Square = iota
	b1
	c1
	d1
	e1
	f1
	g1
	h1
	a2
	b2
	c2
	d2
	e2
	f2
	g2
	h2
	a3
	b3
	c3
	d3
	e3
	f3
	g3
	h3
	a4
	b4
	c4
	d4
	e4
	f4
	g4
	h4
	a5
	b5
	c5
	d5
	e5
	f5
	g5
	h5
	a6
	b6
	c6
	d6
	e6
	f6
	g6
	h6
	a7
	b7
	c7
	d7
	e7
	f7
	g7
	h7
	a8
	b8
	c8
	d8
	e8
	f8
	g8
	h8
)

// A Board represents a bitboard that describes some aspect of a chess board or position.
// Every bit corresponds to one square on the board.
type Board uint64

const (
	AFile Board = 0x0101010101010101 << iota
	BFile
	CFile
	DFile
	EFile
	FFile
	GFile
	HFile
)

const (
	Rank1 Board = 0xff << (8 * iota)
	Rank2
	Rank3
	Rank4
	Rank5
	Rank6
	Rank7
	Rank8
)

const (
	LongDiagonal     Board = 0x8040201008040201 // a1 to h8
	LongAntiDiagonal Board = 0x0102040810204080 // h1 to a8
)

var (
	Files       = []Board{AFile, BFile, CFile, DFile, EFile, FFile, GFile, HFile}
	Ranks       = []Board{Rank1, Rank2, Rank3, Rank4, Rank5, Rank6, Rank7, Rank8}
	fileLetters = []string{"a", "b", "c", "d", "e", "f", "g", "h"}
	rankNumbers = []string{"1", "2", "3", "4", "5", "6", "7", "8"}

	// The squares that must be empty before castling
	QSCastleEmptySquares = []Board{
		(BFile | CFile | DFile) & Rank1,
		(BFile | CFile | DFile) & Rank8,
	}
	KSCastleEmptySquares = []Board{
		(FFile | GFile) & Rank1,
		(FFile | GFile) & Rank8,
	}
	// The squares that the king occupies during castling
	QSCastleKingSquares = []Board{
		(CFile | DFile | EFile) & Rank1,
		(CFile | DFile | EFile) & Rank8,
	}
	KSCastleKingSquares = []Board{
		(EFile | FFile | GFile) & Rank1,
		(EFile | FFile | GFile) & Rank8,
	}
)

// The two Colors of chess pieces are White and Black. A piece's color determines when it can move and whether it can move to an occupied Square.
type Color byte

//go:generate stringer -type=Color
const (
	White Color = iota
	Black
)

// A Piece is one of the six types of chess pieces, or an auxiliary value corresponding to none or all of them.
type Piece byte

//go:generate stringer -type=Piece
const (
	None Piece = iota
	Pawn
	Knight
	Bishop
	Rook
	Queen
	King
	All
)

var pieceLetter = []string{"", "P", "N", "B", "R", "Q", "K"}

// A Position contains all information necessary to specify the current state of a game.
type Position struct {
	// Castling rights: a value of true indicates that the specified Color has the option of castling to the specified side, if it is legal to do so.
	QSCastle [2]bool
	KSCastle [2]bool

	// The unique square, if any, to which an en passant capture can be played by the side to move.
	// Valid values are in the ranges [16, 24) (the 3rd rank, with Black to move following a White pawn push)
	// and [40, 48) (the 6th rank, with White to move following a Black pawn push).
	// A value of 0 indicates that there is no en passant opportunity. Behavior is undefined for any other value.
	ep Square

	// The side to move in the current position.
	ToMove Color

	// The number of half-moves (plies) since the most recent capture or pawn move,
	// for use in determining eligibility for a draw under the fifty-move rule.
	HalfMove int

	// The number of the current move for the side to play.
	// This begins at 1 and increments after each Black move.
	FullMove int

	// The Square of each king.
	KingSquare [2]Square

	// Boards corresponding to the positions of all White and Black pieces,
	// indexed in the order specified by the Piece constants:
	// pawns, knights, bishops, rooks, queens, and the king,
	// with an additional Board representing their union.
	b [2][8]Board

	// The position's Zobrist bitstring.
	z Zobrist
}

var InitialPositionFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"

// InitialPosition represents the position at the beginning of a game of chess.
var InitialPosition, _ = ParseFEN(InitialPositionFEN)

// Opp returns the Color of the player who does not have the move.
func (pos Position) Opp() Color { return pos.ToMove ^ 1 }

// PieceOn returns the Color and Piece type of the piece, if any, on the specified Square.
func (pos Position) PieceOn(s Square) (c Color, p Piece, ok bool) {
	b := s.Board()
	switch {
	case pos.b[White][All]&b != 0:
		c = White
	case pos.b[Black][All]&b != 0:
		c = Black
	default:
		return
	}
	for _, p = range []Piece{Pawn, Knight, Bishop, Rook, Queen, King} {
		if pos.b[c][p]&b != 0 {
			ok = true
			return
		}
	}
	// Error if neither return statement above is utilized
	panic(fmt.Sprintf("PieceOn: nonexistent %v piece on square %v in position %+v", c, s, pos))
	return
}

// deBruijn is a sequence of bits each consecutive six-bit subsequence of which corresponds to a different number in [0, 64).
// It is used with dbIndex to provide quick lookup of the position of a single set bit.
const deBruijn = 0x022c98fdaf386e95 // = 0b0000001000101100100110001111110110101111001110000110111010010101

// The positions of the consecutive six-bit numbers appearing as subsequences of the deBruijn sequence,
// in little-endian encoding but counted from the left.
// Left-shifting the deBruijn constant by i bits yields the number dbIndex[i] in the most significant six bits.
var dbIndex = []Square{
	0, 1, 2, 45, 3, 7, 46, 21,
	4, 14, 57, 8, 17, 47, 40, 22,
	62, 5, 55, 15, 60, 58, 9, 33,
	18, 11, 30, 48, 41, 51, 35, 23,
	63, 44, 6, 20, 13, 56, 16, 39,
	61, 54, 59, 32, 10, 29, 50, 34,
	43, 19, 12, 38, 53, 31, 28, 49,
	42, 37, 52, 27, 36, 26, 25, 24,
}

// LS1B returns a Board consisting of only the least significant 1 bit of the input Board.
func LS1B(b Board) Board {
	if b == 0 {
		panic("LS1B: Board is empty")
	}
	return b & -b
}

// LS1BIndex returns the position of the least significant 1 bit of the input Board.
// It left-shifts the deBruijn constant by multiplying it by the least significant 1 bit
// and then uses the most significant six bits to look up the corresponding value in dbIndex.
func LS1BIndex(b Board) Square {
	return dbIndex[(deBruijn*LS1B(b))>>58]
}

// ResetLS1B returns a Board consisting of all set bits of the input Board except for the least significant one.
func ResetLS1B(b Board) Board {
	if b == 0 {
		panic("ResetLS1B: Board is empty")
	}
	return b & (b - 1)
}

// PopCount returns the number of 1 bits in the input Board.
func PopCount(b Board) int {
	var n int
	for b != 0 {
		n++
		b = ResetLS1B(b)
	}
	return n
}

func pieceChar(c Color, p Piece) string {
	s := pieceLetter[p]
	if c == Black {
		s = strings.ToLower(s)
	}
	return s
}

func (pos Position) Display() string {
	s := "\n"
	for r := 7; r >= 0; r-- {
		for f := 0; f < 8; f++ {
			if c, p, ok := pos.PieceOn(Square(8*r + f)); ok {
				s += pieceChar(c, p)
			} else {
				s += "."
			}
			s += " "
		}
		s += "\n"
	}
	return s
}
<commit_msg>upgrade to Go 1.9<commit_after>package main

import (
	"fmt"
	"math/bits"
	"strings"
)

// A Square represents a square on the board in little-endian rank-file order (a1 = 0, a2 = 1, h8 = 63).
// Behavior is undefined for values outside of [0, 64).
type Square byte

// Rank returns the rank of the input Square in the range [0, 7).
func (s Square) Rank() byte { return byte(s >> 3) }

// File returns the file of the input Square in the range [0, 7).
func (s Square) File() byte { return byte(s & 7) }

// Diagonal returns the number of the southwest-northeast diagonal on which the input Square lies, from 0 (h1) to 14 (a8).
func (s Square) Diagonal() byte { return 7 + s.Rank() - s.File() }

// AntiDiagonal returns the number of the northwest-southeast anti-diagonal on which the input Square lies, from 0 (a1) to 14 (h8).
func (s Square) AntiDiagonal() byte { return s.Rank() + s.File() }

// Board returns a Board in which only the bit corresponding to the input Square is set.
func (s Square) Board() Board { return 1 << s }

//go:generate stringer -type=Square
const (
	a1 Square = iota
	b1
	c1
	d1
	e1
	f1
	g1
	h1
	a2
	b2
	c2
	d2
	e2
	f2
	g2
	h2
	a3
	b3
	c3
	d3
	e3
	f3
	g3
	h3
	a4
	b4
	c4
	d4
	e4
	f4
	g4
	h4
	a5
	b5
	c5
	d5
	e5
	f5
	g5
	h5
	a6
	b6
	c6
	d6
	e6
	f6
	g6
	h6
	a7
	b7
	c7
	d7
	e7
	f7
	g7
	h7
	a8
	b8
	c8
	d8
	e8
	f8
	g8
	h8
)

// A Board represents a bitboard that describes some aspect of a chess board or position.
// Every bit corresponds to one square on the board.
type Board uint64

const (
	AFile Board = 0x0101010101010101 << iota
	BFile
	CFile
	DFile
	EFile
	FFile
	GFile
	HFile
)

const (
	Rank1 Board = 0xff << (8 * iota)
	Rank2
	Rank3
	Rank4
	Rank5
	Rank6
	Rank7
	Rank8
)

const (
	LongDiagonal     Board = 0x8040201008040201 // a1 to h8
	LongAntiDiagonal Board = 0x0102040810204080 // h1 to a8
)

var (
	Files       = []Board{AFile, BFile, CFile, DFile, EFile, FFile, GFile, HFile}
	Ranks       = []Board{Rank1, Rank2, Rank3, Rank4, Rank5, Rank6, Rank7, Rank8}
	fileLetters = []string{"a", "b", "c", "d", "e", "f", "g", "h"}
	rankNumbers = []string{"1", "2", "3", "4", "5", "6", "7", "8"}

	// The squares that must be empty before castling
	QSCastleEmptySquares = []Board{
		(BFile | CFile | DFile) & Rank1,
		(BFile | CFile | DFile) & Rank8,
	}
	KSCastleEmptySquares = []Board{
		(FFile | GFile) & Rank1,
		(FFile | GFile) & Rank8,
	}
	// The squares that the king occupies during castling
	QSCastleKingSquares = []Board{
		(CFile | DFile | EFile) & Rank1,
		(CFile | DFile | EFile) & Rank8,
	}
	KSCastleKingSquares = []Board{
		(EFile | FFile | GFile) & Rank1,
		(EFile | FFile | GFile) & Rank8,
	}
)

// The two Colors of chess pieces are White and Black. A piece's color determines when it can move and whether it can move to an occupied Square.
type Color byte

//go:generate stringer -type=Color
const (
	White Color = iota
	Black
)

// A Piece is one of the six types of chess pieces, or an auxiliary value corresponding to none or all of them.
type Piece byte

//go:generate stringer -type=Piece
const (
	None Piece = iota
	Pawn
	Knight
	Bishop
	Rook
	Queen
	King
	All
)

var pieceLetter = []string{"", "P", "N", "B", "R", "Q", "K"}

// A Position contains all information necessary to specify the current state of a game.
type Position struct {
	// Castling rights: a value of true indicates that the specified Color has the option of castling to the specified side, if it is legal to do so.
	QSCastle [2]bool
	KSCastle [2]bool

	// The unique square, if any, to which an en passant capture can be played by the side to move.
	// Valid values are in the ranges [16, 24) (the 3rd rank, with Black to move following a White pawn push)
	// and [40, 48) (the 6th rank, with White to move following a Black pawn push).
	// A value of 0 indicates that there is no en passant opportunity. Behavior is undefined for any other value.
	ep Square

	// The side to move in the current position.
	ToMove Color

	// The number of half-moves (plies) since the most recent capture or pawn move,
	// for use in determining eligibility for a draw under the fifty-move rule.
	HalfMove int

	// The number of the current move for the side to play.
	// This begins at 1 and increments after each Black move.
	FullMove int

	// The Square of each king.
	KingSquare [2]Square

	// Boards corresponding to the positions of all White and Black pieces,
	// indexed in the order specified by the Piece constants:
	// pawns, knights, bishops, rooks, queens, and the king,
	// with an additional Board representing their union.
	b [2][8]Board

	// The position's Zobrist bitstring.
	z Zobrist
}

var InitialPositionFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"

// InitialPosition represents the position at the beginning of a game of chess.
var InitialPosition, _ = ParseFEN(InitialPositionFEN)

// Opp returns the Color of the player who does not have the move.
func (pos Position) Opp() Color { return pos.ToMove ^ 1 }

// PieceOn returns the Color and Piece type of the piece, if any, on the specified Square.
func (pos Position) PieceOn(s Square) (c Color, p Piece, ok bool) {
	b := s.Board()
	switch {
	case pos.b[White][All]&b != 0:
		c = White
	case pos.b[Black][All]&b != 0:
		c = Black
	default:
		return
	}
	for _, p = range []Piece{Pawn, Knight, Bishop, Rook, Queen, King} {
		if pos.b[c][p]&b != 0 {
			ok = true
			return
		}
	}
	// Error if neither return statement above is utilized
	panic(fmt.Sprintf("PieceOn: nonexistent %v piece on square %v in position %+v", c, s, pos))
	return
}

// LS1B returns a Board consisting of only the least significant 1 bit of the input Board.
func LS1B(b Board) Board {
	if b == 0 {
		panic("LS1B: Board is empty")
	}
	return b & -b
}

// LS1BIndex returns the position of the least significant 1 bit of the input Board.
func LS1BIndex(b Board) Square {
	return Square(bits.TrailingZeros64(uint64(b)))
}

// ResetLS1B returns a Board consisting of all set bits of the input Board except for the least significant one.
func ResetLS1B(b Board) Board {
	if b == 0 {
		panic("ResetLS1B: Board is empty")
	}
	return b & (b - 1)
}

// PopCount returns the number of 1 bits in the input Board.
func PopCount(b Board) int {
	return bits.OnesCount64(uint64(b))
}

func pieceChar(c Color, p Piece) string {
	s := pieceLetter[p]
	if c == Black {
		s = strings.ToLower(s)
	}
	return s
}

func (pos Position) Display() string {
	s := "\n"
	for r := 7; r >= 0; r-- {
		for f := 0; f < 8; f++ {
			if c, p, ok := pos.PieceOn(Square(8*r + f)); ok {
				s += pieceChar(c, p)
			} else {
				s += "."
			}
			s += " "
		}
		s += "\n"
	}
	return s
}
<|endoftext|>


<commit_before>// Copyright 2015 CloudAwan 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 authorization

import (
	"errors"
	"github.com/cloudawan/cloudone_utility/rbac"
	jwt "github.com/dgrijalva/jwt-go"
	"time"
)

const (
	signingKey         = "userTokenKey"
	cacheCheckInterval = time.Minute
	cacheTTL           = cacheCheckInterval * 60
)

var SystemAdminToken string = ""

func init() {
	createDefaultUser()
	createSystemUserInMemory()
	periodicallyCleanCache()
}

func createDefaultUser() {
	user, _ := GetStorage().LoadUser("admin")
	if user == nil {
		permission := &rbac.Permission{"all", "*", "*", "*"}
		permissionSlice := make([]*rbac.Permission, 0)
		permissionSlice = append(permissionSlice, permission)
		role := &rbac.Role{"admin", permissionSlice, "admin"}
		roleSlice := make([]*rbac.Role, 0)
		roleSlice = append(roleSlice, role)
		resource := &rbac.Resource{"all", "*", "*"}
		resourceSlice := make([]*rbac.Resource, 0)
		resourceSlice = append(resourceSlice, resource)
		metaDataMap := make(map[string]string)
		user := rbac.CreateUser("admin", "password", roleSlice, resourceSlice, "admin", metaDataMap, nil, false)

		if err := GetStorage().SaveRole(role); err != nil {
			log.Critical(err)
		}

		if err := GetStorage().SaveUser(user); err != nil {
			log.Critical(err)
		}
	}
}

func createSystemUserInMemory() {
	permission := &rbac.Permission{"system-all", "*", "*", "*"}
	permissionSlice := make([]*rbac.Permission, 0)
	permissionSlice = append(permissionSlice, permission)
	role := &rbac.Role{"system-admin", permissionSlice, "system-admin"}
	roleSlice := make([]*rbac.Role, 0)
	roleSlice = append(roleSlice, role)
	resource := &rbac.Resource{"system-all", "*", "*"}
	resourceSlice := make([]*rbac.Resource, 0)
	resourceSlice = append(resourceSlice, resource)
	metaDataMap := make(map[string]string)
	// Use time as password and have it encrypted so no one other than system could use
	user := rbac.CreateUser("system", time.Now().String(), roleSlice, resourceSlice, "system-admin", metaDataMap, nil, false)

	token, err := generateToken(user)
	if err != nil {
		log.Critical(err)
		return
	}

	// Set the maximum duration
	rbac.SetCache(token, user, time.Duration(1<<63-1))
	SystemAdminToken = token
}

var closed bool = false

func Close() {
	closed = true
}

func periodicallyCleanCache() {
	go func() {
		for {
			if closed {
				break
			}

			rbac.CheckCacheTimeout()

			time.Sleep(cacheCheckInterval)
		}
	}()
}

func GetUserFromToken(token string) (*rbac.User, error) {
	_, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) {
		// Don't forget to validate the alg is what you expect:
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, errors.New("Unexpected signing method")
		}

		expiredText, _ := token.Claims["expired"].(string)

		expiredTime, err := time.Parse(time.RFC3339, expiredText)
		if err != nil {
			log.Error("Fail to parse expired time. Token %v error %s", token, err)
			return nil, err
		}

		if expiredTime.Before(time.Now()) {
			log.Debug("Token is expired. Token %v ", token)
			return nil, errors.New("Token is expired")
		}
		return []byte(signingKey), nil
	})

	if err != nil {
		return nil, err
	} else {
		user := rbac.GetCache(token)
		if user != nil {
			return user, nil
		} else {
			log.Error("User not in the cache. Token %v", token)
			return nil, errors.New("User not in the cache")
		}
	}
}

func CreateToken(name string, password string) (string, error) {
	user, err := GetStorage().LoadUser(name)
	if err != nil {
		log.Error(err)
		return "", err
	}

	if user.CheckPassword(password) == false {
		log.Error("Incorrect User %s or Password %s", name, password)
		return "", errors.New("Incorrect User or Password")
	}

	if user.ExpiredTime != nil && time.Now().After(*user.ExpiredTime) {
		log.Error("User %s is expired", name)
		return "", errors.New("User is expired")
	}

	if user.Disabled {
		log.Error("User %s is disabled", name)
		return "", errors.New("User is disabled")
	}

	return generateToken(user)
}

func generateToken(user *rbac.User) (string, error) {
	// Create the token
	token := jwt.New(jwt.SigningMethodHS512)
	// Set some claims
	token.Claims["username"] = user.Name
	token.Claims["expired"] = time.Now().Add(cacheTTL).Format(time.RFC3339)
	// Sign
	signedToken, err := token.SignedString([]byte(signingKey))
	if err != nil {
		log.Error(err)
		return "", err
	}

	rbac.SetCache(signedToken, user, cacheTTL)

	// Sign and get the complete encoded token as a string
	return signedToken, nil
}

func GetAllTokenExpiredTime() map[string]time.Time {
	return rbac.GetAllTokenExpiredTime()
}
<commit_msg>Fix system token<commit_after>// Copyright 2015 CloudAwan 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 authorization

import (
	"errors"
	"github.com/cloudawan/cloudone_utility/rbac"
	jwt "github.com/dgrijalva/jwt-go"
	"time"
)

const (
	signingKey         = "userTokenKey"
	cacheCheckInterval = time.Minute
	cacheTTL           = cacheCheckInterval * 60
)

var SystemAdminToken string = ""

func init() {
	createDefaultUser()
	createSystemUserInMemory()
	periodicallyCleanCache()
}

func createDefaultUser() {
	user, _ := GetStorage().LoadUser("admin")
	if user == nil {
		permission := &rbac.Permission{"all", "*", "*", "*"}
		permissionSlice := make([]*rbac.Permission, 0)
		permissionSlice = append(permissionSlice, permission)
		role := &rbac.Role{"admin", permissionSlice, "admin"}
		roleSlice := make([]*rbac.Role, 0)
		roleSlice = append(roleSlice, role)
		resource := &rbac.Resource{"all", "*", "*"}
		resourceSlice := make([]*rbac.Resource, 0)
		resourceSlice = append(resourceSlice, resource)
		metaDataMap := make(map[string]string)
		user := rbac.CreateUser("admin", "password", roleSlice, resourceSlice, "admin", metaDataMap, nil, false)

		if err := GetStorage().SaveRole(role); err != nil {
			log.Critical(err)
		}

		if err := GetStorage().SaveUser(user); err != nil {
			log.Critical(err)
		}
	}
}

func createSystemUserInMemory() {
	permission := &rbac.Permission{"system-all", "*", "*", "*"}
	permissionSlice := make([]*rbac.Permission, 0)
	permissionSlice = append(permissionSlice, permission)
	role := &rbac.Role{"system-admin", permissionSlice, "system-admin"}
	roleSlice := make([]*rbac.Role, 0)
	roleSlice = append(roleSlice, role)
	resource := &rbac.Resource{"system-all", "*", "*"}
	resourceSlice := make([]*rbac.Resource, 0)
	resourceSlice = append(resourceSlice, resource)
	metaDataMap := make(map[string]string)
	// Use time as password and have it encrypted so no one other than system could use
	user := rbac.CreateUser("system", time.Now().String(), roleSlice, resourceSlice, "system-admin", metaDataMap, nil, false)

	// Set the duration to 100 years
	duration := time.Duration(time.Hour * 24 * 365 * 100)

	token, err := generateToken(user, duration)
	if err != nil {
		log.Critical(err)
		return
	}

	rbac.SetCache(token, user, duration)
	SystemAdminToken = token
}

var closed bool = false

func Close() {
	closed = true
}

func periodicallyCleanCache() {
	go func() {
		for {
			if closed {
				break
			}

			rbac.CheckCacheTimeout()

			time.Sleep(cacheCheckInterval)
		}
	}()
}

func GetUserFromToken(token string) (*rbac.User, error) {
	_, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) {
		// Don't forget to validate the alg is what you expect:
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, errors.New("Unexpected signing method")
		}

		expiredText, _ := token.Claims["expired"].(string)

		expiredTime, err := time.Parse(time.RFC3339, expiredText)
		if err != nil {
			log.Error("Fail to parse expired time. Token %v error %s", token, err)
			return nil, err
		}

		if expiredTime.Before(time.Now()) {
			log.Debug("Token is expired. Token %v ", token)
			return nil, errors.New("Token is expired")
		}
		return []byte(signingKey), nil
	})

	if err != nil {
		return nil, err
	} else {
		user := rbac.GetCache(token)
		if user != nil {
			return user, nil
		} else {
			log.Error("User not in the cache. Token %v", token)
			return nil, errors.New("User not in the cache")
		}
	}
}

func CreateToken(name string, password string) (string, error) {
	user, err := GetStorage().LoadUser(name)
	if err != nil {
		log.Error(err)
		return "", err
	}

	if user.CheckPassword(password) == false {
		log.Error("Incorrect User %s or Password %s", name, password)
		return "", errors.New("Incorrect User or Password")
	}

	if user.ExpiredTime != nil && time.Now().After(*user.ExpiredTime) {
		log.Error("User %s is expired", name)
		return "", errors.New("User is expired")
	}

	if user.Disabled {
		log.Error("User %s is disabled", name)
		return "", errors.New("User is disabled")
	}

	return generateToken(user, cacheTTL)
}

func generateToken(user *rbac.User, duration time.Duration) (string, error) {
	// Create the token
	token := jwt.New(jwt.SigningMethodHS512)
	// Set some claims
	token.Claims["username"] = user.Name
	token.Claims["expired"] = time.Now().Add(duration).Format(time.RFC3339)
	// Sign
	signedToken, err := token.SignedString([]byte(signingKey))
	if err != nil {
		log.Error(err)
		return "", err
	}

	rbac.SetCache(signedToken, user, cacheTTL)

	// Sign and get the complete encoded token as a string
	return signedToken, nil
}

func GetAllTokenExpiredTime() map[string]time.Time {
	return rbac.GetAllTokenExpiredTime()
}
<|endoftext|>


<commit_before>package render

import (
	"github.com/weaveworks/scope/report"
)

// MapFunc is anything which can take an arbitrary Node and
// return a set of other Nodes.
//
// If the output is empty, the node shall be omitted from the rendered topology.
type MapFunc func(report.Node, report.Networks) report.Nodes

// Renderer is something that can render a report to a set of Nodes.
type Renderer interface {
	Render(report.Report, Decorator) report.Nodes
	Stats(report.Report, Decorator) Stats
}

// Stats is the type returned by Renderer.Stats
type Stats struct {
	FilteredNodes int
}

func (s Stats) merge(other Stats) Stats {
	return Stats{
		FilteredNodes: s.FilteredNodes + other.FilteredNodes,
	}
}

// Reduce renderer is a Renderer which merges together the output of several
// other renderers.
type Reduce []Renderer

// MakeReduce is the only sane way to produce a Reduce Renderer.
func MakeReduce(renderers ...Renderer) Renderer {
	r := Reduce(renderers)
	return Memoise(&r)
}

// Render produces a set of Nodes given a Report.
func (r *Reduce) Render(rpt report.Report, dct Decorator) report.Nodes {
	result := report.Nodes{}
	for _, renderer := range *r {
		result = result.Merge(renderer.Render(rpt, dct))
	}
	return result
}

// Stats implements Renderer
func (r *Reduce) Stats(rpt report.Report, dct Decorator) Stats {
	var result Stats
	for _, renderer := range *r {
		result = result.merge(renderer.Stats(rpt, dct))
	}
	return result
}

// Map is a Renderer which produces a set of Nodes from the set of
// Nodes produced by another Renderer.
type Map struct {
	MapFunc
	Renderer
}

// MakeMap makes a new Map
func MakeMap(f MapFunc, r Renderer) Renderer {
	return Memoise(&Map{f, r})
}

// Render transforms a set of Nodes produces by another Renderer.
// using a map function
func (m *Map) Render(rpt report.Report, dct Decorator) report.Nodes {
	var (
		input         = m.Renderer.Render(rpt, dct)
		output        = report.Nodes{}
		mapped        = map[string]report.IDList{} // input node ID -> output node IDs
		adjacencies   = map[string]report.IDList{} // output node ID -> input node Adjacencies
		localNetworks = LocalNetworks(rpt)
	)

	// Rewrite all the nodes according to the map function
	for _, inRenderable := range input {
		for _, outRenderable := range m.MapFunc(inRenderable, localNetworks) {
			existing, ok := output[outRenderable.ID]
			if ok {
				outRenderable = outRenderable.Merge(existing)
			}

			output[outRenderable.ID] = outRenderable
			mapped[inRenderable.ID] = mapped[inRenderable.ID].Add(outRenderable.ID)
			adjacencies[outRenderable.ID] = adjacencies[outRenderable.ID].Merge(inRenderable.Adjacency)
		}
	}

	// Rewrite Adjacency for new node IDs.
	for outNodeID, inAdjacency := range adjacencies {
		outAdjacency := report.MakeIDList()
		for _, inAdjacent := range inAdjacency {
			for _, outAdjacent := range mapped[inAdjacent] {
				outAdjacency = outAdjacency.Add(outAdjacent)
			}
		}
		outNode := output[outNodeID]
		outNode.Adjacency = outAdjacency
		output[outNodeID] = outNode
	}

	return output
}

// Stats implements Renderer
func (m *Map) Stats(_ report.Report, _ Decorator) Stats {
	// There doesn't seem to be an instance where we want stats to recurse
	// through Maps - for instance we don't want to see the number of filtered
	// processes in the container renderer.
	return Stats{}
}

// Decorator transforms one renderer to another. e.g. Filters.
type Decorator func(Renderer) Renderer

// ComposeDecorators composes decorators into one.
func ComposeDecorators(decorators ...Decorator) Decorator {
	return func(r Renderer) Renderer {
		for _, decorator := range decorators {
			r = decorator(r)
		}
		return r
	}
}

type applyDecorator struct {
	Renderer
}

func (ad applyDecorator) Render(rpt report.Report, dct Decorator) report.Nodes {
	if dct != nil {
		return dct(ad.Renderer).Render(rpt, nil)
	}
	return ad.Renderer.Render(rpt, nil)
}
func (ad applyDecorator) Stats(rpt report.Report, dct Decorator) Stats {
	if dct != nil {
		return dct(ad.Renderer).Stats(rpt, nil)
	}
	return ad.Renderer.Stats(rpt, nil)
}

// ApplyDecorators returns a renderer which will apply the given decorators
// to the child render.
func ApplyDecorators(renderer Renderer) Renderer {
	return applyDecorator{renderer}
}
<commit_msg>Don't recursively gets stats beyond an ApplyDecorators decorator<commit_after>package render

import (
	"github.com/weaveworks/scope/report"
)

// MapFunc is anything which can take an arbitrary Node and
// return a set of other Nodes.
//
// If the output is empty, the node shall be omitted from the rendered topology.
type MapFunc func(report.Node, report.Networks) report.Nodes

// Renderer is something that can render a report to a set of Nodes.
type Renderer interface {
	Render(report.Report, Decorator) report.Nodes
	Stats(report.Report, Decorator) Stats
}

// Stats is the type returned by Renderer.Stats
type Stats struct {
	FilteredNodes int
}

func (s Stats) merge(other Stats) Stats {
	return Stats{
		FilteredNodes: s.FilteredNodes + other.FilteredNodes,
	}
}

// Reduce renderer is a Renderer which merges together the output of several
// other renderers.
type Reduce []Renderer

// MakeReduce is the only sane way to produce a Reduce Renderer.
func MakeReduce(renderers ...Renderer) Renderer {
	r := Reduce(renderers)
	return Memoise(&r)
}

// Render produces a set of Nodes given a Report.
func (r *Reduce) Render(rpt report.Report, dct Decorator) report.Nodes {
	result := report.Nodes{}
	for _, renderer := range *r {
		result = result.Merge(renderer.Render(rpt, dct))
	}
	return result
}

// Stats implements Renderer
func (r *Reduce) Stats(rpt report.Report, dct Decorator) Stats {
	var result Stats
	for _, renderer := range *r {
		result = result.merge(renderer.Stats(rpt, dct))
	}
	return result
}

// Map is a Renderer which produces a set of Nodes from the set of
// Nodes produced by another Renderer.
type Map struct {
	MapFunc
	Renderer
}

// MakeMap makes a new Map
func MakeMap(f MapFunc, r Renderer) Renderer {
	return Memoise(&Map{f, r})
}

// Render transforms a set of Nodes produces by another Renderer.
// using a map function
func (m *Map) Render(rpt report.Report, dct Decorator) report.Nodes {
	var (
		input         = m.Renderer.Render(rpt, dct)
		output        = report.Nodes{}
		mapped        = map[string]report.IDList{} // input node ID -> output node IDs
		adjacencies   = map[string]report.IDList{} // output node ID -> input node Adjacencies
		localNetworks = LocalNetworks(rpt)
	)

	// Rewrite all the nodes according to the map function
	for _, inRenderable := range input {
		for _, outRenderable := range m.MapFunc(inRenderable, localNetworks) {
			existing, ok := output[outRenderable.ID]
			if ok {
				outRenderable = outRenderable.Merge(existing)
			}

			output[outRenderable.ID] = outRenderable
			mapped[inRenderable.ID] = mapped[inRenderable.ID].Add(outRenderable.ID)
			adjacencies[outRenderable.ID] = adjacencies[outRenderable.ID].Merge(inRenderable.Adjacency)
		}
	}

	// Rewrite Adjacency for new node IDs.
	for outNodeID, inAdjacency := range adjacencies {
		outAdjacency := report.MakeIDList()
		for _, inAdjacent := range inAdjacency {
			for _, outAdjacent := range mapped[inAdjacent] {
				outAdjacency = outAdjacency.Add(outAdjacent)
			}
		}
		outNode := output[outNodeID]
		outNode.Adjacency = outAdjacency
		output[outNodeID] = outNode
	}

	return output
}

// Stats implements Renderer
func (m *Map) Stats(_ report.Report, _ Decorator) Stats {
	// There doesn't seem to be an instance where we want stats to recurse
	// through Maps - for instance we don't want to see the number of filtered
	// processes in the container renderer.
	return Stats{}
}

// Decorator transforms one renderer to another. e.g. Filters.
type Decorator func(Renderer) Renderer

// ComposeDecorators composes decorators into one.
func ComposeDecorators(decorators ...Decorator) Decorator {
	return func(r Renderer) Renderer {
		for _, decorator := range decorators {
			r = decorator(r)
		}
		return r
	}
}

type applyDecorator struct {
	Renderer
}

func (ad applyDecorator) Render(rpt report.Report, dct Decorator) report.Nodes {
	if dct != nil {
		return dct(ad.Renderer).Render(rpt, nil)
	}
	return ad.Renderer.Render(rpt, nil)
}
func (ad applyDecorator) Stats(rpt report.Report, dct Decorator) Stats {
	if dct != nil {
		return dct(ad.Renderer).Stats(rpt, nil)
	}
	return Stats{}
}

// ApplyDecorators returns a renderer which will apply the given decorators
// to the child render.
func ApplyDecorators(renderer Renderer) Renderer {
	return applyDecorator{renderer}
}
<|endoftext|>


<commit_before>package renren

import (
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
	"time"
)

type APIError struct {
	ErrorMessage struct {
		ErrorCode string `json:"code"`
		Message   string `json:"message"`
	} `json:"error"`
}

func (err *APIError) Error() (str string) {
	return fmt.Sprintf("APIError ErrorMessage:%v ErrorCode %v", err.ErrorMessage.Message, err.ErrorMessage.ErrorCode)
}

type APIToken struct {
	AccessToken  string `json:"access_token"`
	RefreshToken string `json:"refresh_token"`
	TokenType    string `json:"token_type"`
	expires      int64  `json:"expires_in"`
}

/**
 * check ApiToken is Expired
 * @return bool
 */
func (api *APIToken) isExpired() bool {
	return api.AccessToken == "" || api.RefreshToken == "" || api.expires < time.Now().Unix()
}

/*
 * client
 */
type ApiClient struct {
	api *APIRenRen
}

/**
 * api client
 */
type APIRenRen struct {
	ApiKey         string
	ApiSecret      string
	RedirectURL    string
	ResponseType   string
	OAuth2URL      string
	AccessTokenURL string
	AccessToken    string
	Version        string
}

func NewAPI(appkey string, secret string, redirect_url string, responseType string) (api *APIRenRen) {
	api = &APIRenRen{
		ApiKey:         appkey,
		ApiSecret:      secret,
		RedirectURL:    redirect_url,
		ResponseType:   responseType,
		Version:        VERSION,
		OAuth2URL:      AouthURL,
		AccessTokenURL: TokenURL,
	}
	return api
}

func (token *APIToken) SetAccessToken(atoken string, expires int64) {
	token.AccessToken = atoken
	token.expires = expires
}

/**
 * get the oathor url
 */
func (api *APIRenRen) OAuthorURL() (uri string, err error) {
	_url, err := url.Parse(api.OAuth2URL)
	if err != nil {
		fmt.Println(err.Error())
		return "", err
	}
	v := url.Values{
		"client_id":     {api.ApiKey},
		"redirect_uri":  {api.RedirectURL},
		"response_type": {"code"},
	}
	q := v.Encode()
	fmt.Println("qcode ", q)
	if _url.RawQuery == "" {
		_url.RawQuery = q
	} else {
		_url.RawQuery = _url.RawQuery + "&" + q
	}
	fmt.Println("url =", _url.String())
	return _url.String(), nil
}

func (api *APIRenRen) SetAccessToken(token string) {
	api.AccessToken = token
}

/**
 * renren client
 */
func (api *APIRenRen) GetAccessToken(code string) (result interface{}, err error) {
	_url, err := url.Parse(TokenURL)
	if err != nil {
		return nil, err
	}
	q := url.Values{
		"grant_type":    {"authorization_code"},
		"client_id":     {api.ApiKey},
		"client_secret": {api.ApiSecret},
		"redirect_uri":  {api.RedirectURL},
		"code":          {code},
	}
	ret, err := api.sendRequest(_url, GET, q)
	if err != nil {
		return nil, err
	}
	token := APIToken{}
	err = json.Unmarshal([]byte(ret), &token)
	if err != nil {
		fmt.Println(err.Error())
		return nil, err
	}

	return token, nil
}

/**
 * send net request
 */
func (api *APIRenRen) sendRequest(_url *url.URL, method string, param url.Values) (result string, err error) {
	var body io.Reader
	switch method {
	case GET:
		if _url.RawQuery == "" {
			_url.RawQuery = param.Encode()
		} else {
			_url.RawQuery = _url.RawQuery + "&" + param.Encode()
		}
		body = nil
	case POST:
		body = strings.NewReader(param.Encode())
	}
	client := new(http.Client)
	fmt.Println(_url.String())
	request, err := http.NewRequest(method, _url.String(), body)
	if err != nil {
		return "", err
	}
	request.Header.Add("User-Agent", "renren/"+VERSION)
	if strings.EqualFold(api.AccessToken, "") == false {
		request.Header.Add("Authorization", "Bearer "+api.AccessToken)
	}
	response, err := client.Do(request)
	if err != nil {
		return "", err
	}
	defer response.Body.Close()
	switch response.Header.Get("Conent-Encoding") {
	case "gzip":
		fmt.Println("gzip")
		// need unzip
	default:
		conent, err := ioutil.ReadAll(response.Body)
		if err != nil {
			return "", err
		}
		return string(conent), nil
	}
	return "", nil
}

/**
 * api get request
 */
func (api *APIRenRen) ApiGet(path string, parameters map[string]string) (data string, err error) {
	upath := fmt.Sprintf("%v%v", DefaultBaseURL, path)
	_url, err := url.Parse(upath)
	if err != nil {
		return "", err
	}
	param := url.Values{}
	for k, v := range parameters {
		param.Set(k, v)
	}
	return api.sendRequest(_url, GET, param)
}

/**
 * api post request
 */
func (api *APIRenRen) ApiPost(path string, parameters map[string]string) (data string, err error) {
	upath := fmt.Sprintf("%v%v", DefaultBaseURL, path)
	_url, err := url.Parse(upath)
	if err != nil {
		return "", err
	}
	param := url.Values{}
	for k, v := range parameters {
		param.Set(k, v)
	}
	return api.sendRequest(_url, POST, param)
}
<commit_msg>添加评论模块两个接口<commit_after>package renren

import (
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
	"time"
)

type APIError struct {
	ErrorMessage struct {
		ErrorCode string `json:"code"`
		Message   string `json:"message"`
	} `json:"error"`
}

func (err *APIError) Error() (str string) {
	return fmt.Sprintf("APIError ErrorMessage:%v ErrorCode %v", err.ErrorMessage.Message, err.ErrorMessage.ErrorCode)
}

type APIToken struct {
	AccessToken  string `json:"access_token"`
	RefreshToken string `json:"refresh_token"`
	TokenType    string `json:"token_type"`
	expires      int64  `json:"expires_in"`
}

/**
 * check ApiToken is Expired
 * @return bool
 */
func (api *APIToken) isExpired() bool {
	return api.AccessToken == "" || api.RefreshToken == "" || api.expires < time.Now().Unix()
}

/*
 * client
 */
type ApiClient struct {
	api *APIRenRen
}

/**
 * api client
 */
type APIRenRen struct {
	ApiKey         string
	ApiSecret      string
	RedirectURL    string
	ResponseType   string
	OAuth2URL      string
	AccessTokenURL string
	AccessToken    string
	Version        string
}

func NewAPI(appkey string, secret string, redirect_url string, responseType string) (api *APIRenRen) {
	api = &APIRenRen{
		ApiKey:         appkey,
		ApiSecret:      secret,
		RedirectURL:    redirect_url,
		ResponseType:   responseType,
		Version:        VERSION,
		OAuth2URL:      AouthURL,
		AccessTokenURL: TokenURL,
	}
	return api
}

func (token *APIToken) SetAccessToken(atoken string, expires int64) {
	token.AccessToken = atoken
	token.expires = expires
}

/**
 * get the oathor url
 */
func (api *APIRenRen) OAuthorURL() (uri string, err error) {
	_url, err := url.Parse(api.OAuth2URL)
	if err != nil {
		fmt.Println(err.Error())
		return "", err
	}
	v := url.Values{
		"client_id":     {api.ApiKey},
		"redirect_uri":  {api.RedirectURL},
		"response_type": {"code"},
	}
	q := v.Encode()
	fmt.Println("qcode ", q)
	if _url.RawQuery == "" {
		_url.RawQuery = q
	} else {
		_url.RawQuery = _url.RawQuery + "&" + q
	}
	fmt.Println("url =", _url.String())
	return _url.String(), nil
}

func (api *APIRenRen) SetAccessToken(token string) {
	api.AccessToken = token
}

/**
 * renren client
 */
func (api *APIRenRen) GetAccessToken(code string) (result interface{}, err error) {
	_url, err := url.Parse(TokenURL)
	if err != nil {
		return nil, err
	}
	q := url.Values{
		"grant_type":    {"authorization_code"},
		"client_id":     {api.ApiKey},
		"client_secret": {api.ApiSecret},
		"redirect_uri":  {api.RedirectURL},
		"code":          {code},
	}
	ret, err := api.sendRequest(_url, GET, q)
	if err != nil {
		return nil, err
	}
	token := APIToken{}
	err = json.Unmarshal([]byte(ret), &token)
	if err != nil {
		fmt.Println(err.Error())
		return nil, err
	}

	return token, nil
}

/**
 * send net request
 */
func (api *APIRenRen) sendRequest(_url *url.URL, method string, param url.Values) (result string, err error) {
	var body io.Reader
	switch method {
	case GET:
		if _url.RawQuery == "" {
			_url.RawQuery = param.Encode()
		} else {
			_url.RawQuery = _url.RawQuery + "&" + param.Encode()
		}
		body = nil
	case POST:
		fmt.Println(param.Encode())
		body = strings.NewReader(param.Encode())
	}
	client := new(http.Client)
	// fmt.Println(_url.String())
	request, err := http.NewRequest(method, _url.String(), body)
	if err != nil {
		return "", err
	}
	switch method {
	case POST:
		request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	}
	request.Header.Add("User-Agent", "renren/"+VERSION)
	if strings.EqualFold(api.AccessToken, "") == false {
		request.Header.Add("Authorization", "Bearer "+api.AccessToken)
	}
	response, err := client.Do(request)
	if err != nil {
		return "", err
	}
	defer response.Body.Close()
	switch response.Header.Get("Conent-Encoding") {
	case "gzip":
		fmt.Println("gzip")
		// need unzip
	default:
		conent, err := ioutil.ReadAll(response.Body)
		if err != nil {
			return "", err
		}
		return string(conent), nil
	}
	return "", nil
}

/**
 * api get request
 */
func (api *APIRenRen) ApiGet(path string, parameters map[string]string) (data string, err error) {
	upath := fmt.Sprintf("%v%v", DefaultBaseURL, path)
	_url, err := url.Parse(upath)
	if err != nil {
		return "", err
	}
	param := url.Values{}
	for k, v := range parameters {
		param.Set(k, v)
	}
	return api.sendRequest(_url, GET, param)
}

/**
 * api post request
 */
func (api *APIRenRen) ApiPost(path string, parameters map[string]string) (data string, err error) {
	upath := fmt.Sprintf("%v%v", DefaultBaseURL, path)
	_url, err := url.Parse(upath)
	if err != nil {
		return "", err
	}
	param := url.Values{}
	for k, v := range parameters {
		param.Set(k, v)
	}
	return api.sendRequest(_url, POST, param)
}
<|endoftext|>


<commit_before><commit_msg>QA: Simplify code inside start()<commit_after><|endoftext|>


<commit_before>package gogs

type Branch struct {
	name      string         `json:"name"`
	commit    *PayloadCommit `json:"commit"`
}

func (c *Client) ListRepoBranches(user, repo string) ([]*Branch, error) {
	branches := make([]*Branch, 0, 10)
	return branches, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branches", user, repo), nil, nil, &branches)
}

func (c *Client) GetRepoBranch(user, repo, branch string) (*Branch, error) {
	b := new(Branch)
	return b, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branches/%s", user, repo, branch), nil, nil, &b)
}
<commit_msg>Use uppercase for first letter<commit_after>package gogs

type Branch struct {
	Name      string         `json:"name"`
	Commit    *PayloadCommit `json:"commit"`
}

func (c *Client) ListRepoBranches(user, repo string) ([]*Branch, error) {
	branches := make([]*Branch, 0, 10)
	return branches, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branches", user, repo), nil, nil, &branches)
}

func (c *Client) GetRepoBranch(user, repo, branch string) (*Branch, error) {
	b := new(Branch)
	return b, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branches/%s", user, repo, branch), nil, nil, &b)
}
<|endoftext|>


<commit_before><commit_msg>Start with the default port of 9010. Because 6000 is private<commit_after><|endoftext|>


<commit_before>package main

import (
	"html/template"
	"log"
	"net/http"
	"time"

	"github.com/andrewslotin/doppelganger/git"
)

var (
	reposTemplate = template.Must(template.ParseFiles("templates/layout.html.template", "templates/repos/index.html.template"))
)

type ReposHandler struct {
	repositories git.RepositoryService
}

func NewReposHandler(repositoryService git.RepositoryService) *ReposHandler {
	return &ReposHandler{
		repositories: repositoryService,
	}
}

func (handler *ReposHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	startTime := time.Now()

	if repoName := req.FormValue("repo"); repoName != "" {
		NewRepoClient(handler.repositories).ServeHTTP(w, req)
		return
	}

	repos, err := handler.repositories.All()
	if err != nil {
		log.Printf("failed to get repos (%s) %s", err, req)
		http.Error(w, "Internal server error", http.StatusInternalServerError)
		return
	}

	if err := reposTemplate.Execute(w, repos); err != nil {
		log.Printf("failed to render repos/index with %d entries (%s)", len(repos), err)
	} else {
		log.Printf("rendered repos/index with %d entries [%s]", len(repos), time.Since(startTime))
	}
}
<commit_msg>Fix request logging in repos handler<commit_after>package main

import (
	"html/template"
	"log"
	"net/http"
	"time"

	"github.com/andrewslotin/doppelganger/git"
)

var (
	reposTemplate = template.Must(template.ParseFiles("templates/layout.html.template", "templates/repos/index.html.template"))
)

type ReposHandler struct {
	repositories git.RepositoryService
}

func NewReposHandler(repositoryService git.RepositoryService) *ReposHandler {
	return &ReposHandler{
		repositories: repositoryService,
	}
}

func (handler *ReposHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	startTime := time.Now()

	if repoName := req.FormValue("repo"); repoName != "" {
		NewRepoClient(handler.repositories).ServeHTTP(w, req)
		return
	}

	repos, err := handler.repositories.All()
	if err != nil {
		log.Printf("failed to get repos (%s) %v", err, req)
		http.Error(w, "Internal server error", http.StatusInternalServerError)
		return
	}

	if err := reposTemplate.Execute(w, repos); err != nil {
		log.Printf("failed to render repos/index with %d entries (%s)", len(repos), err)
	} else {
		log.Printf("rendered repos/index with %d entries [%s]", len(repos), time.Since(startTime))
	}
}
<|endoftext|>


<commit_before><commit_msg>flatten bug fix remove elliding of nested frames.<commit_after><|endoftext|>


<commit_before>package main

import (
	"fmt"
	"sync"
	"time"

	"github.com/hashicorp/memberlist"
	"github.com/newrelic/bosun/services_state"
)

var (
	broadcasts chan [][]byte
)

func updateMetaData(list *memberlist.Memberlist, metaUpdates chan []byte) {
	for ;; {
		list.LocalNode().Meta = <-metaUpdates // Blocking
		fmt.Printf("Got update: %s\n", string(list.LocalNode().Meta))
		err := list.UpdateNode(10 * time.Second)
		if err != nil {
			fmt.Printf("Error pushing node update!")
		}
	}
}

func announceMembers(list *memberlist.Memberlist, state *services_state.ServicesState) {
	for ;; {
		// Ask for members of the cluster
		for _, member := range list.Members() {
		    fmt.Printf("Member: %s %s\n", member.Name, member.Addr)
			fmt.Printf("  Meta:\n    %s\n", string(member.Meta))
		}

		state.Print(list);

		time.Sleep(2 * time.Second)
	}
}

func main() {
	opts     := parseCommandLine()
	state    := services_state.NewServicesState()
	delegate := servicesDelegate{state: state}

	broadcasts = make(chan [][]byte)

	// Use a LAN config but add our delegate
	config := memberlist.DefaultLANConfig()
	config.Delegate = &delegate

	list, err := memberlist.Create(config)
	exitWithError(err, "Failed to create memberlist")

	// Join an existing cluster by specifying at least one known member.
	_, err = list.Join([]string{ opts.ClusterIP })
	exitWithError(err, "Failed to join cluster")

	metaUpdates := make(chan []byte)
	var wg sync.WaitGroup
	wg.Add(1)

	go announceMembers(list, state)
	go state.StayCurrent(broadcasts, containers)
	go updateMetaData(list, metaUpdates)

	serveHttp(list, state)

	time.Sleep(4 * time.Second)
	metaUpdates <-[]byte("A message!")

	wg.Wait() // forever... nothing will decrement the wg
}
<commit_msg>Use the WAN config by default.<commit_after>package main

import (
	"fmt"
	"sync"
	"time"

	"github.com/hashicorp/memberlist"
	"github.com/newrelic/bosun/services_state"
)

var (
	broadcasts chan [][]byte
)

func updateMetaData(list *memberlist.Memberlist, metaUpdates chan []byte) {
	for ;; {
		list.LocalNode().Meta = <-metaUpdates // Blocking
		fmt.Printf("Got update: %s\n", string(list.LocalNode().Meta))
		err := list.UpdateNode(10 * time.Second)
		if err != nil {
			fmt.Printf("Error pushing node update!")
		}
	}
}

func announceMembers(list *memberlist.Memberlist, state *services_state.ServicesState) {
	for ;; {
		// Ask for members of the cluster
		for _, member := range list.Members() {
		    fmt.Printf("Member: %s %s\n", member.Name, member.Addr)
			fmt.Printf("  Meta:\n    %s\n", string(member.Meta))
		}

		state.Print(list);

		time.Sleep(2 * time.Second)
	}
}

func main() {
	opts     := parseCommandLine()
	state    := services_state.NewServicesState()
	delegate := servicesDelegate{state: state}

	broadcasts = make(chan [][]byte)

	// Use a LAN config but add our delegate
	config := memberlist.DefaultWANConfig()
	config.Delegate = &delegate

	list, err := memberlist.Create(config)
	exitWithError(err, "Failed to create memberlist")

	// Join an existing cluster by specifying at least one known member.
	_, err = list.Join([]string{ opts.ClusterIP })
	exitWithError(err, "Failed to join cluster")

	metaUpdates := make(chan []byte)
	var wg sync.WaitGroup
	wg.Add(1)

	go announceMembers(list, state)
	go state.StayCurrent(broadcasts, containers)
	go updateMetaData(list, metaUpdates)

	serveHttp(list, state)

	time.Sleep(4 * time.Second)
	metaUpdates <-[]byte("A message!")

	wg.Wait() // forever... nothing will decrement the wg
}
<|endoftext|>


<commit_before>package main

import (
	"time"
)

type Memory struct {
	Id        int       `json:"id"`
	Text      string    `json:"text"`
	CreatedAt time.Time `json:"created_at"`
	Active    bool      `json:"active"`
}

type Brain struct {
	Memories []Memory `json:"memories"`
}

// Load a brain
func (brain *Brain) Load() {
	var memories []Memory
	var memory Memory
	memory.Id = 0
	memory.Text = "Some circus subculture shit"
	memory.Active = true

	var memory2 Memory
	memory2.Id = 1
	memory2.Text = "cetacean junk"
	memory2.Active = true

	memories = append(memories, memory)
	memories = append(memories, memory2)

	brain.Memories = memories
}

// Persist a brain
func (brain *Brain) Save() {

}

// Return the current brain
func getBrain() Brain {
	return brain
}
<commit_msg>Continuing work on adding memories<commit_after>package main

import (
	"time"
)

type Memory struct {
	Id        int       `json:"id"`
	Text      string    `json:"text"`
	CreatedAt time.Time `json:"created_at"`
	Active    bool      `json:"active"`
}

type Brain struct {
	Memories []Memory `json:"memories"`
}

// Load a brain
func (brain *Brain) Load() {
	var memories []Memory
	var memory Memory
	memory.Id = 0
	memory.Text = "Some circus subculture shit"
	memory.Active = true

	var memory2 Memory
	memory2.Id = 1
	memory2.Text = "cetacean junk"
	memory2.Active = true

	memories = append(memories, memory)
	memories = append(memories, memory2)

	brain.Memories = memories
}

// Persist a brain
func (brain *Brain) Save() {

}

// Add a memory
func (brain *Brain) Add(m Memory) Memory {
	m.Id = brain.GetNextId()
	m.Active = true
	m.CreatedAt = time.Now()

	brain.Memories = append(brain.Memories, m)

	// Return the memory since it's been given an Id and a CreatedAt
	return m
}

// Return the current brain
func getBrain() Brain {
	return brain
}

// Get the next Id for the brain
func (brain *Brain) GetNextId() int {
	i := 0
	for _, v := range brain.Memories {
		if v.Id > i {
			i = v.Id
		}
	}

	return i
}
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package admission

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

	"github.com/ghodss/yaml"
	"github.com/golang/glog"

	"bytes"

	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apimachinery/pkg/runtime/serializer"
	"k8s.io/apimachinery/pkg/util/sets"
	"k8s.io/apiserver/pkg/apis/apiserver"
	apiserverv1alpha1 "k8s.io/apiserver/pkg/apis/apiserver/v1alpha1"
)

func makeAbs(path, base string) (string, error) {
	if filepath.IsAbs(path) {
		return path, nil
	}
	if len(base) == 0 || base == "." {
		cwd, err := os.Getwd()
		if err != nil {
			return "", err
		}
		base = cwd
	}
	return filepath.Join(base, path), nil
}

// ReadAdmissionConfiguration reads the admission configuration at the specified path.
// It returns the loaded admission configuration if the input file aligns with the required syntax.
// If it does not align with the provided syntax, it returns a default configuration for the enumerated
// set of pluginNames whose config location references the specified configFilePath.
// It does this to preserve backward compatibility when admission control files were opaque.
// It returns an error if the file did not exist.
func ReadAdmissionConfiguration(pluginNames []string, configFilePath string, configScheme *runtime.Scheme) (ConfigProvider, error) {
	if configFilePath == "" {
		return configProvider{config: &apiserver.AdmissionConfiguration{}}, nil
	}
	// a file was provided, so we just read it.
	data, err := ioutil.ReadFile(configFilePath)
	if err != nil {
		return nil, fmt.Errorf("unable to read admission control configuration from %q [%v]", configFilePath, err)
	}
	codecs := serializer.NewCodecFactory(configScheme)
	decoder := codecs.UniversalDecoder()
	decodedObj, err := runtime.Decode(decoder, data)
	// we were able to decode the file successfully
	if err == nil {
		decodedConfig, ok := decodedObj.(*apiserver.AdmissionConfiguration)
		if !ok {
			return nil, fmt.Errorf("unexpected type: %T", decodedObj)
		}
		baseDir := path.Dir(configFilePath)
		for i := range decodedConfig.Plugins {
			if decodedConfig.Plugins[i].Path == "" {
				continue
			}
			// we update relative file paths to absolute paths
			absPath, err := makeAbs(decodedConfig.Plugins[i].Path, baseDir)
			if err != nil {
				return nil, err
			}
			decodedConfig.Plugins[i].Path = absPath
		}
		return configProvider{
			config: decodedConfig,
			scheme: configScheme,
		}, nil
	}
	// we got an error where the decode wasn't related to a missing type
	if !(runtime.IsMissingVersion(err) || runtime.IsMissingKind(err) || runtime.IsNotRegisteredError(err)) {
		return nil, err
	}
	// convert the legacy format to the new admission control format
	// in order to preserve backwards compatibility, we set plugins that
	// previously read input from a non-versioned file configuration to the
	// current input file.
	legacyPluginsWithUnversionedConfig := sets.NewString("ImagePolicyWebhook", "PodNodeSelector")
	externalConfig := &apiserverv1alpha1.AdmissionConfiguration{}
	for _, pluginName := range pluginNames {
		if legacyPluginsWithUnversionedConfig.Has(pluginName) {
			externalConfig.Plugins = append(externalConfig.Plugins,
				apiserverv1alpha1.AdmissionPluginConfiguration{
					Name: pluginName,
					Path: configFilePath})
		}
	}
	configScheme.Default(externalConfig)
	internalConfig := &apiserver.AdmissionConfiguration{}
	if err := configScheme.Convert(externalConfig, internalConfig, nil); err != nil {
		return nil, err
	}
	return configProvider{
		config: internalConfig,
		scheme: configScheme,
	}, nil
}

type configProvider struct {
	config *apiserver.AdmissionConfiguration
	scheme *runtime.Scheme
}

// GetAdmissionPluginConfigurationFor returns a reader that holds the admission plugin configuration.
func GetAdmissionPluginConfigurationFor(pluginCfg apiserver.AdmissionPluginConfiguration, scheme *runtime.Scheme) (io.Reader, error) {
	// if there is nothing nested in the object, we return the named location
	obj := pluginCfg.Configuration
	if obj != nil {
		// serialize the configuration and build a reader for it
		content, err := writeYAML(obj, scheme)
		if err != nil {
			return nil, err
		}
		return bytes.NewBuffer(content), nil
	}
	// there is nothing nested, so we delegate to path
	if pluginCfg.Path != "" {
		content, err := ioutil.ReadFile(pluginCfg.Path)
		if err != nil {
			glog.Fatalf("Couldn't open admission plugin configuration %s: %#v", pluginCfg.Path, err)
			return nil, err
		}
		return bytes.NewBuffer(content), nil
	}
	// there is no special config at all
	return nil, nil
}

// GetAdmissionPluginConfiguration takes the admission configuration and returns a reader
// for the specified plugin.  If no specific configuration is present, we return a nil reader.
func (p configProvider) ConfigFor(pluginName string) (io.Reader, error) {
	// there is no config, so there is no potential config
	if p.config == nil {
		return nil, nil
	}
	// look for matching plugin and get configuration
	for _, pluginCfg := range p.config.Plugins {
		if pluginName != pluginCfg.Name {
			continue
		}
		pluginConfig, err := GetAdmissionPluginConfigurationFor(pluginCfg, p.scheme)
		if err != nil {
			return nil, err
		}
		return pluginConfig, nil
	}
	// there is no registered config that matches on plugin name.
	return nil, nil
}

// writeYAML writes the specified object to a byte array as yaml.
func writeYAML(obj runtime.Object, scheme *runtime.Scheme) ([]byte, error) {
	gvks, _, err := scheme.ObjectKinds(obj)
	if err != nil {
		return nil, err
	}
	gvs := []schema.GroupVersion{}
	for _, gvk := range gvks {
		gvs = append(gvs, gvk.GroupVersion())
	}
	codecs := serializer.NewCodecFactory(scheme)
	json, err := runtime.Encode(codecs.LegacyCodec(gvs...), obj)
	if err != nil {
		return nil, err
	}

	content, err := yaml.JSONToYAML(json)
	if err != nil {
		return nil, err
	}
	return content, err
}
<commit_msg>fix typo and adjust import sequence<commit_after>/*
Copyright 2017 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package admission

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

	"github.com/ghodss/yaml"
	"github.com/golang/glog"

	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apimachinery/pkg/runtime/serializer"
	"k8s.io/apimachinery/pkg/util/sets"
	"k8s.io/apiserver/pkg/apis/apiserver"
	apiserverv1alpha1 "k8s.io/apiserver/pkg/apis/apiserver/v1alpha1"
)

func makeAbs(path, base string) (string, error) {
	if filepath.IsAbs(path) {
		return path, nil
	}
	if len(base) == 0 || base == "." {
		cwd, err := os.Getwd()
		if err != nil {
			return "", err
		}
		base = cwd
	}
	return filepath.Join(base, path), nil
}

// ReadAdmissionConfiguration reads the admission configuration at the specified path.
// It returns the loaded admission configuration if the input file aligns with the required syntax.
// If it does not align with the provided syntax, it returns a default configuration for the enumerated
// set of pluginNames whose config location references the specified configFilePath.
// It does this to preserve backward compatibility when admission control files were opaque.
// It returns an error if the file did not exist.
func ReadAdmissionConfiguration(pluginNames []string, configFilePath string, configScheme *runtime.Scheme) (ConfigProvider, error) {
	if configFilePath == "" {
		return configProvider{config: &apiserver.AdmissionConfiguration{}}, nil
	}
	// a file was provided, so we just read it.
	data, err := ioutil.ReadFile(configFilePath)
	if err != nil {
		return nil, fmt.Errorf("unable to read admission control configuration from %q [%v]", configFilePath, err)
	}
	codecs := serializer.NewCodecFactory(configScheme)
	decoder := codecs.UniversalDecoder()
	decodedObj, err := runtime.Decode(decoder, data)
	// we were able to decode the file successfully
	if err == nil {
		decodedConfig, ok := decodedObj.(*apiserver.AdmissionConfiguration)
		if !ok {
			return nil, fmt.Errorf("unexpected type: %T", decodedObj)
		}
		baseDir := path.Dir(configFilePath)
		for i := range decodedConfig.Plugins {
			if decodedConfig.Plugins[i].Path == "" {
				continue
			}
			// we update relative file paths to absolute paths
			absPath, err := makeAbs(decodedConfig.Plugins[i].Path, baseDir)
			if err != nil {
				return nil, err
			}
			decodedConfig.Plugins[i].Path = absPath
		}
		return configProvider{
			config: decodedConfig,
			scheme: configScheme,
		}, nil
	}
	// we got an error where the decode wasn't related to a missing type
	if !(runtime.IsMissingVersion(err) || runtime.IsMissingKind(err) || runtime.IsNotRegisteredError(err)) {
		return nil, err
	}
	// convert the legacy format to the new admission control format
	// in order to preserve backwards compatibility, we set plugins that
	// previously read input from a non-versioned file configuration to the
	// current input file.
	legacyPluginsWithUnversionedConfig := sets.NewString("ImagePolicyWebhook", "PodNodeSelector")
	externalConfig := &apiserverv1alpha1.AdmissionConfiguration{}
	for _, pluginName := range pluginNames {
		if legacyPluginsWithUnversionedConfig.Has(pluginName) {
			externalConfig.Plugins = append(externalConfig.Plugins,
				apiserverv1alpha1.AdmissionPluginConfiguration{
					Name: pluginName,
					Path: configFilePath})
		}
	}
	configScheme.Default(externalConfig)
	internalConfig := &apiserver.AdmissionConfiguration{}
	if err := configScheme.Convert(externalConfig, internalConfig, nil); err != nil {
		return nil, err
	}
	return configProvider{
		config: internalConfig,
		scheme: configScheme,
	}, nil
}

type configProvider struct {
	config *apiserver.AdmissionConfiguration
	scheme *runtime.Scheme
}

// GetAdmissionPluginConfigurationFor returns a reader that holds the admission plugin configuration.
func GetAdmissionPluginConfigurationFor(pluginCfg apiserver.AdmissionPluginConfiguration, scheme *runtime.Scheme) (io.Reader, error) {
	// if there is nothing nested in the object, we return the named location
	obj := pluginCfg.Configuration
	if obj != nil {
		// serialize the configuration and build a reader for it
		content, err := writeYAML(obj, scheme)
		if err != nil {
			return nil, err
		}
		return bytes.NewBuffer(content), nil
	}
	// there is nothing nested, so we delegate to path
	if pluginCfg.Path != "" {
		content, err := ioutil.ReadFile(pluginCfg.Path)
		if err != nil {
			glog.Fatalf("Couldn't open admission plugin configuration %s: %#v", pluginCfg.Path, err)
			return nil, err
		}
		return bytes.NewBuffer(content), nil
	}
	// there is no special config at all
	return nil, nil
}

// ConfigFor returns a reader for the specified plugin.
// If no specific configuration is present, we return a nil reader.
func (p configProvider) ConfigFor(pluginName string) (io.Reader, error) {
	// there is no config, so there is no potential config
	if p.config == nil {
		return nil, nil
	}
	// look for matching plugin and get configuration
	for _, pluginCfg := range p.config.Plugins {
		if pluginName != pluginCfg.Name {
			continue
		}
		pluginConfig, err := GetAdmissionPluginConfigurationFor(pluginCfg, p.scheme)
		if err != nil {
			return nil, err
		}
		return pluginConfig, nil
	}
	// there is no registered config that matches on plugin name.
	return nil, nil
}

// writeYAML writes the specified object to a byte array as yaml.
func writeYAML(obj runtime.Object, scheme *runtime.Scheme) ([]byte, error) {
	gvks, _, err := scheme.ObjectKinds(obj)
	if err != nil {
		return nil, err
	}
	gvs := []schema.GroupVersion{}
	for _, gvk := range gvks {
		gvs = append(gvs, gvk.GroupVersion())
	}
	codecs := serializer.NewCodecFactory(scheme)
	json, err := runtime.Encode(codecs.LegacyCodec(gvs...), obj)
	if err != nil {
		return nil, err
	}

	content, err := yaml.JSONToYAML(json)
	if err != nil {
		return nil, err
	}
	return content, err
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors All rights reserved.

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 chartutil

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

	"k8s.io/helm/pkg/proto/hapi/chart"
)

const (
	// ChartfileName is the default Chart file name.
	ChartfileName = "Chart.yaml"
	// ValuesfileName is the default values file name.
	ValuesfileName = "values.yaml"
	// TemplatesDir is the relative directory name for templates.
	TemplatesDir = "templates"
	// ChartsDir is the relative directory name for charts dependencies.
	ChartsDir = "charts"
	// IgnorefileName is the name of the Helm ignore file.
	IgnorefileName = ".helmignore"
	// IngressFileName is the name of the example ingress file.
	IngressFileName = "ingress.yaml"
	// DeploymentName is the name of the example deployment file.
	DeploymentName = "deployment.yaml"
	// ServiceName is the name of the example service file.
	ServiceName = "service.yaml"
	// NotesName is the name of the example NOTES.txt file.
	NotesName = "NOTES.txt"
	// HelpersName is the name of the example NOTES.txt file.
	HelpersName = "_helpers.tpl"
)

const defaultValues = `# Default values for %s.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
image:
  repository: nginx
  tag: stable
  pullPolicy: IfNotPresent
service:
  name: nginx
  type: ClusterIP
  externalPort: 80
  internalPort: 80
ingress:
  enabled: false
  # Used to create an Ingress record.
  hosts:
    - chart-example.local
  annotations:
    # kubernetes.io/ingress.class: nginx
    # kubernetes.io/tls-acme: "true"
  tls:
    # Secrets must be manually created in the namespace.
    # - secretName: chart-example-tls
    #   hosts:
    #     - chart-example.local
resources: {}
  # We usually recommend not to specify default resources and to leave this as a conscious
  # choice for the user. This also increases chances charts run on environments with little
  # resources, such as Minikube. If you do want to specify resources, uncomment the following
  # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
  # limits:
  #  cpu: 100m
  #  memory: 128Mi
  # requests:
  #  cpu: 100m
  #  memory: 128Mi
`

const defaultIgnore = `# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*~
# Various IDEs
.project
.idea/
*.tmproj
`

const defaultIngress = `{{- if .Values.ingress.enabled -}}
{{- $serviceName := include "<CHARTNAME>.fullname" . -}}
{{- $servicePort := .Values.service.externalPort -}}
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: {{ template "<CHARTNAME>.fullname" . }}
  labels:
    app: {{ template "<CHARTNAME>.name" . }}
    chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
  annotations:
    {{- range $key, $value := .Values.ingress.annotations }}
      {{ $key }}: {{ $value | quote }}
    {{- end }}
spec:
  rules:
    {{- range $host := .Values.ingress.hosts }}
    - host: {{ $host }}
      http:
        paths:
          - path: /
            backend:
              serviceName: {{ $serviceName }}
              servicePort: {{ $servicePort }}
    {{- end -}}
  {{- if .Values.ingress.tls }}
  tls:
{{ toYaml .Values.ingress.tls | indent 4 }}
  {{- end -}}
{{- end -}}
`

const defaultDeployment = `apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: {{ template "<CHARTNAME>.fullname" . }}
  labels:
    app: {{ template "<CHARTNAME>.name" . }}
    chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
spec:
  replicas: {{ .Values.replicaCount }}
  template:
    metadata:
      labels:
        app: {{ template "<CHARTNAME>.name" . }}
        release: {{ .Release.Name }}
    spec:
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          ports:
            - containerPort: {{ .Values.service.internalPort }}
          livenessProbe:
            httpGet:
              path: /
              port: {{ .Values.service.internalPort }}
          readinessProbe:
            httpGet:
              path: /
              port: {{ .Values.service.internalPort }}
          resources:
{{ toYaml .Values.resources | indent 12 }}
    {{- if .Values.nodeSelector }}
      nodeSelector:
{{ toYaml .Values.nodeSelector | indent 8 }}
    {{- end }}
`

const defaultService = `apiVersion: v1
kind: Service
metadata:
  name: {{ template "<CHARTNAME>.fullname" . }}
  labels:
    app: {{ template "<CHARTNAME>.name" . }}
    chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
spec:
  type: {{ .Values.service.type }}
  ports:
    - port: {{ .Values.service.externalPort }}
      targetPort: {{ .Values.service.internalPort }}
      protocol: TCP
      name: {{ .Values.service.name }}
  selector:
    app: {{ template "<CHARTNAME>.name" . }}
    release: {{ .Release.Name }}
`

const defaultNotes = `1. Get the application URL by running these commands:
{{- if .Values.ingress.enabled }}
{{- range .Values.ingress.hosts }}
  http://{{ . }}
{{- end }}
{{- else if contains "NodePort" .Values.service.type }}
  export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "<CHARTNAME>.fullname" . }})
  export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
  echo http://$NODE_IP:$NODE_PORT
{{- else if contains "LoadBalancer" .Values.service.type }}
     NOTE: It may take a few minutes for the LoadBalancer IP to be available.
           You can watch the status of by running 'kubectl get svc -w {{ template "<CHARTNAME>.fullname" . }}'
  export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "<CHARTNAME>.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
  echo http://$SERVICE_IP:{{ .Values.service.externalPort }}
{{- else if contains "ClusterIP" .Values.service.type }}
  export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "<CHARTNAME>.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
  echo "Visit http://127.0.0.1:8080 to use your application"
  kubectl port-forward $POD_NAME 8080:{{ .Values.service.internalPort }}
{{- end }}
`

const defaultHelpers = `{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "<CHARTNAME>.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}

{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
*/}}
{{- define "<CHARTNAME>.fullname" -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
`

// CreateFrom creates a new chart, but scaffolds it from the src chart.
func CreateFrom(chartfile *chart.Metadata, dest string, src string) error {
	schart, err := Load(src)
	if err != nil {
		return fmt.Errorf("could not load %s: %s", src, err)
	}

	schart.Metadata = chartfile
	return SaveDir(schart, dest)
}

// Create creates a new chart in a directory.
//
// Inside of dir, this will create a directory based on the name of
// chartfile.Name. It will then write the Chart.yaml into this directory and
// create the (empty) appropriate directories.
//
// The returned string will point to the newly created directory. It will be
// an absolute path, even if the provided base directory was relative.
//
// If dir does not exist, this will return an error.
// If Chart.yaml or any directories cannot be created, this will return an
// error. In such a case, this will attempt to clean up by removing the
// new chart directory.
func Create(chartfile *chart.Metadata, dir string) (string, error) {
	path, err := filepath.Abs(dir)
	if err != nil {
		return path, err
	}

	if fi, err := os.Stat(path); err != nil {
		return path, err
	} else if !fi.IsDir() {
		return path, fmt.Errorf("no such directory %s", path)
	}

	n := chartfile.Name
	cdir := filepath.Join(path, n)
	if fi, err := os.Stat(cdir); err == nil && !fi.IsDir() {
		return cdir, fmt.Errorf("file %s already exists and is not a directory", cdir)
	}
	if err := os.MkdirAll(cdir, 0755); err != nil {
		return cdir, err
	}

	cf := filepath.Join(cdir, ChartfileName)
	if _, err := os.Stat(cf); err != nil {
		if err := SaveChartfile(cf, chartfile); err != nil {
			return cdir, err
		}
	}

	for _, d := range []string{TemplatesDir, ChartsDir} {
		if err := os.MkdirAll(filepath.Join(cdir, d), 0755); err != nil {
			return cdir, err
		}
	}

	files := []struct {
		path    string
		content []byte
	}{
		{
			// values.yaml
			path:    filepath.Join(cdir, ValuesfileName),
			content: []byte(fmt.Sprintf(defaultValues, chartfile.Name)),
		},
		{
			// .helmignore
			path:    filepath.Join(cdir, IgnorefileName),
			content: []byte(defaultIgnore),
		},
		{
			// ingress.yaml
			path:    filepath.Join(cdir, TemplatesDir, IngressFileName),
			content: []byte(strings.Replace(defaultIngress, "<CHARTNAME>", chartfile.Name, -1)),
		},
		{
			// deployment.yaml
			path:    filepath.Join(cdir, TemplatesDir, DeploymentName),
			content: []byte(strings.Replace(defaultDeployment, "<CHARTNAME>", chartfile.Name, -1)),
		},
		{
			// service.yaml
			path:    filepath.Join(cdir, TemplatesDir, ServiceName),
			content: []byte(strings.Replace(defaultService, "<CHARTNAME>", chartfile.Name, -1)),
		},
		{
			// NOTES.txt
			path:    filepath.Join(cdir, TemplatesDir, NotesName),
			content: []byte(strings.Replace(defaultNotes, "<CHARTNAME>", chartfile.Name, -1)),
		},
		{
			// _helpers.tpl
			path:    filepath.Join(cdir, TemplatesDir, HelpersName),
			content: []byte(strings.Replace(defaultHelpers, "<CHARTNAME>", chartfile.Name, -1)),
		},
	}

	for _, file := range files {
		if _, err := os.Stat(file.path); err == nil {
			// File exists and is okay. Skip it.
			continue
		}
		if err := ioutil.WriteFile(file.path, file.content, 0644); err != nil {
			return cdir, err
		}
	}
	return cdir, nil
}
<commit_msg>Add fullnameOverride<commit_after>/*
Copyright 2016 The Kubernetes Authors All rights reserved.

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 chartutil

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

	"k8s.io/helm/pkg/proto/hapi/chart"
)

const (
	// ChartfileName is the default Chart file name.
	ChartfileName = "Chart.yaml"
	// ValuesfileName is the default values file name.
	ValuesfileName = "values.yaml"
	// TemplatesDir is the relative directory name for templates.
	TemplatesDir = "templates"
	// ChartsDir is the relative directory name for charts dependencies.
	ChartsDir = "charts"
	// IgnorefileName is the name of the Helm ignore file.
	IgnorefileName = ".helmignore"
	// IngressFileName is the name of the example ingress file.
	IngressFileName = "ingress.yaml"
	// DeploymentName is the name of the example deployment file.
	DeploymentName = "deployment.yaml"
	// ServiceName is the name of the example service file.
	ServiceName = "service.yaml"
	// NotesName is the name of the example NOTES.txt file.
	NotesName = "NOTES.txt"
	// HelpersName is the name of the example NOTES.txt file.
	HelpersName = "_helpers.tpl"
)

const defaultValues = `# Default values for %s.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
image:
  repository: nginx
  tag: stable
  pullPolicy: IfNotPresent
service:
  name: nginx
  type: ClusterIP
  externalPort: 80
  internalPort: 80
ingress:
  enabled: false
  # Used to create an Ingress record.
  hosts:
    - chart-example.local
  annotations:
    # kubernetes.io/ingress.class: nginx
    # kubernetes.io/tls-acme: "true"
  tls:
    # Secrets must be manually created in the namespace.
    # - secretName: chart-example-tls
    #   hosts:
    #     - chart-example.local
resources: {}
  # We usually recommend not to specify default resources and to leave this as a conscious
  # choice for the user. This also increases chances charts run on environments with little
  # resources, such as Minikube. If you do want to specify resources, uncomment the following
  # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
  # limits:
  #  cpu: 100m
  #  memory: 128Mi
  # requests:
  #  cpu: 100m
  #  memory: 128Mi
`

const defaultIgnore = `# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*~
# Various IDEs
.project
.idea/
*.tmproj
`

const defaultIngress = `{{- if .Values.ingress.enabled -}}
{{- $serviceName := include "<CHARTNAME>.fullname" . -}}
{{- $servicePort := .Values.service.externalPort -}}
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: {{ template "<CHARTNAME>.fullname" . }}
  labels:
    app: {{ template "<CHARTNAME>.name" . }}
    chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
  annotations:
    {{- range $key, $value := .Values.ingress.annotations }}
      {{ $key }}: {{ $value | quote }}
    {{- end }}
spec:
  rules:
    {{- range $host := .Values.ingress.hosts }}
    - host: {{ $host }}
      http:
        paths:
          - path: /
            backend:
              serviceName: {{ $serviceName }}
              servicePort: {{ $servicePort }}
    {{- end -}}
  {{- if .Values.ingress.tls }}
  tls:
{{ toYaml .Values.ingress.tls | indent 4 }}
  {{- end -}}
{{- end -}}
`

const defaultDeployment = `apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: {{ template "<CHARTNAME>.fullname" . }}
  labels:
    app: {{ template "<CHARTNAME>.name" . }}
    chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
spec:
  replicas: {{ .Values.replicaCount }}
  template:
    metadata:
      labels:
        app: {{ template "<CHARTNAME>.name" . }}
        release: {{ .Release.Name }}
    spec:
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          ports:
            - containerPort: {{ .Values.service.internalPort }}
          livenessProbe:
            httpGet:
              path: /
              port: {{ .Values.service.internalPort }}
          readinessProbe:
            httpGet:
              path: /
              port: {{ .Values.service.internalPort }}
          resources:
{{ toYaml .Values.resources | indent 12 }}
    {{- if .Values.nodeSelector }}
      nodeSelector:
{{ toYaml .Values.nodeSelector | indent 8 }}
    {{- end }}
`

const defaultService = `apiVersion: v1
kind: Service
metadata:
  name: {{ template "<CHARTNAME>.fullname" . }}
  labels:
    app: {{ template "<CHARTNAME>.name" . }}
    chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
spec:
  type: {{ .Values.service.type }}
  ports:
    - port: {{ .Values.service.externalPort }}
      targetPort: {{ .Values.service.internalPort }}
      protocol: TCP
      name: {{ .Values.service.name }}
  selector:
    app: {{ template "<CHARTNAME>.name" . }}
    release: {{ .Release.Name }}
`

const defaultNotes = `1. Get the application URL by running these commands:
{{- if .Values.ingress.enabled }}
{{- range .Values.ingress.hosts }}
  http://{{ . }}
{{- end }}
{{- else if contains "NodePort" .Values.service.type }}
  export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "<CHARTNAME>.fullname" . }})
  export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
  echo http://$NODE_IP:$NODE_PORT
{{- else if contains "LoadBalancer" .Values.service.type }}
     NOTE: It may take a few minutes for the LoadBalancer IP to be available.
           You can watch the status of by running 'kubectl get svc -w {{ template "<CHARTNAME>.fullname" . }}'
  export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "<CHARTNAME>.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
  echo http://$SERVICE_IP:{{ .Values.service.externalPort }}
{{- else if contains "ClusterIP" .Values.service.type }}
  export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "<CHARTNAME>.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
  echo "Visit http://127.0.0.1:8080 to use your application"
  kubectl port-forward $POD_NAME 8080:{{ .Values.service.internalPort }}
{{- end }}
`

const defaultHelpers = `{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "<CHARTNAME>.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}

{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
*/}}
{{- define "<CHARTNAME>.fullname" -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- $default := printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- default $default .Values.fullnameOverride -}}
{{- end -}}
`

// CreateFrom creates a new chart, but scaffolds it from the src chart.
func CreateFrom(chartfile *chart.Metadata, dest string, src string) error {
	schart, err := Load(src)
	if err != nil {
		return fmt.Errorf("could not load %s: %s", src, err)
	}

	schart.Metadata = chartfile
	return SaveDir(schart, dest)
}

// Create creates a new chart in a directory.
//
// Inside of dir, this will create a directory based on the name of
// chartfile.Name. It will then write the Chart.yaml into this directory and
// create the (empty) appropriate directories.
//
// The returned string will point to the newly created directory. It will be
// an absolute path, even if the provided base directory was relative.
//
// If dir does not exist, this will return an error.
// If Chart.yaml or any directories cannot be created, this will return an
// error. In such a case, this will attempt to clean up by removing the
// new chart directory.
func Create(chartfile *chart.Metadata, dir string) (string, error) {
	path, err := filepath.Abs(dir)
	if err != nil {
		return path, err
	}

	if fi, err := os.Stat(path); err != nil {
		return path, err
	} else if !fi.IsDir() {
		return path, fmt.Errorf("no such directory %s", path)
	}

	n := chartfile.Name
	cdir := filepath.Join(path, n)
	if fi, err := os.Stat(cdir); err == nil && !fi.IsDir() {
		return cdir, fmt.Errorf("file %s already exists and is not a directory", cdir)
	}
	if err := os.MkdirAll(cdir, 0755); err != nil {
		return cdir, err
	}

	cf := filepath.Join(cdir, ChartfileName)
	if _, err := os.Stat(cf); err != nil {
		if err := SaveChartfile(cf, chartfile); err != nil {
			return cdir, err
		}
	}

	for _, d := range []string{TemplatesDir, ChartsDir} {
		if err := os.MkdirAll(filepath.Join(cdir, d), 0755); err != nil {
			return cdir, err
		}
	}

	files := []struct {
		path    string
		content []byte
	}{
		{
			// values.yaml
			path:    filepath.Join(cdir, ValuesfileName),
			content: []byte(fmt.Sprintf(defaultValues, chartfile.Name)),
		},
		{
			// .helmignore
			path:    filepath.Join(cdir, IgnorefileName),
			content: []byte(defaultIgnore),
		},
		{
			// ingress.yaml
			path:    filepath.Join(cdir, TemplatesDir, IngressFileName),
			content: []byte(strings.Replace(defaultIngress, "<CHARTNAME>", chartfile.Name, -1)),
		},
		{
			// deployment.yaml
			path:    filepath.Join(cdir, TemplatesDir, DeploymentName),
			content: []byte(strings.Replace(defaultDeployment, "<CHARTNAME>", chartfile.Name, -1)),
		},
		{
			// service.yaml
			path:    filepath.Join(cdir, TemplatesDir, ServiceName),
			content: []byte(strings.Replace(defaultService, "<CHARTNAME>", chartfile.Name, -1)),
		},
		{
			// NOTES.txt
			path:    filepath.Join(cdir, TemplatesDir, NotesName),
			content: []byte(strings.Replace(defaultNotes, "<CHARTNAME>", chartfile.Name, -1)),
		},
		{
			// _helpers.tpl
			path:    filepath.Join(cdir, TemplatesDir, HelpersName),
			content: []byte(strings.Replace(defaultHelpers, "<CHARTNAME>", chartfile.Name, -1)),
		},
	}

	for _, file := range files {
		if _, err := os.Stat(file.path); err == nil {
			// File exists and is okay. Skip it.
			continue
		}
		if err := ioutil.WriteFile(file.path, file.content, 0644); err != nil {
			return cdir, err
		}
	}
	return cdir, nil
}
<|endoftext|>


<commit_before>package client

import (
	"context"
	"os"

	"github.com/sethvargo/go-envconfig"
)

type Env struct {
	// I'd like to set TELEPRESENCE_LOGIN_DOMAIN,default=auth.datawire.io, but
	// sethvargo/go-envconfig doesn't support filling in the default for our later references to
	// it in following settings, so we have to do the hack with maybeSetDefault below.  *sigh* I
	// guess I'm just spoiled by apro/cmd/amb-sidecar/types/internal/envconfig.
	LoginDomain        string `env:"TELEPRESENCE_LOGIN_DOMAIN,required"`
	LoginAuthURL       string `env:"TELEPRESENCE_LOGIN_AUTH_URL,default=https://${TELEPRESENCE_LOGIN_DOMAIN}/auth"`
	LoginTokenURL      string `env:"TELEPRESENCE_LOGIN_TOKEN_URL,default=https://${TELEPRESENCE_LOGIN_DOMAIN}/token"`
	LoginCompletionURL string `env:"TELEPRESENCE_LOGIN_COMPLETION_URL,default=https://${TELEPRESENCE_LOGIN_DOMAIN}/completion"`
	LoginClientID      string `env:"TELEPRESENCE_LOGIN_CLIENT_ID,default=telepresence-cli"`
	UserInfoURL        string `env:"TELEPRESENCE_USER_INFO_URL,default=https://${TELEPRESENCE_LOGIN_DOMAIN}/api/userinfo"`

	ManagerNamespace string `env:"TELEPRESENCE_MANAGER_NAMESPACE,default=ambassador"`

	// This environment variable becomes the default for the images.registry and images.webhookRegistry
	Registry string `env:"TELEPRESENCE_REGISTRY,default=docker.io/datawire"`

	// This environment variable becomes the default for the images.agentImage and images.webhookAgentImage
	AgentImage string `env:"TELEPRESENCE_AGENT_IMAGE,default="`
}

func (env Env) Get(key string) string {
	switch key {
	case "TELEPRESENCE_LOGIN_DOMAIN":
		return env.LoginDomain
	case "TELEPRESENCE_LOGIN_AUTH_URL":
		return env.LoginAuthURL
	case "TELEPRESENCE_LOGIN_TOKEN_URL":
		return env.LoginTokenURL
	case "TELEPRESENCE_LOGIN_COMPLETION_URL":
		return env.LoginCompletionURL
	case "TELEPRESENCE_LOGIN_CLIENT_ID":
		return env.LoginClientID
	case "TELEPRESENCE_USER_INFO_URL":
		return env.UserInfoURL

	case "TELEPRESENCE_MANAGER_NAMESPACE":
		return env.ManagerNamespace

	default:
		return os.Getenv(key)
	}
}

type envKey struct{}

// WithEnv returns a context with the given Env
func WithEnv(ctx context.Context, env *Env) context.Context {
	return context.WithValue(ctx, envKey{}, env)
}

func GetEnv(ctx context.Context) *Env {
	env, ok := ctx.Value(envKey{}).(*Env)
	if !ok {
		return nil
	}
	return env
}

func LoadEnv(ctx context.Context) (*Env, error) {
	if os.Getenv("TELEPRESENCE_LOGIN_DOMAIN") == "" {
		loginDomain := "auth.datawire.io"
		if os.Getenv("SYSTEMA_ENV") == "staging" {
			// XXX : This is hacky bc we really should move TELEPRESENCE_LOGIN_DOMAIN
			// to the config.yml and get rid of that env var and all the related ones.
			// But I (donnyyung) am about to be on vacation for a week so don't want
			// to make such a huge change and then leave, so I will take care of
			// cleaning this up once I'm back.
			loginDomain = "beta-auth.datawire.io"
		}
		os.Setenv("TELEPRESENCE_LOGIN_DOMAIN", loginDomain)
	}

	var env Env
	if err := envconfig.Process(ctx, &env); err != nil {
		return nil, err
	}
	return &env, nil
}
<commit_msg>if env.AgentImage is not set, default it<commit_after>package client

import (
	"context"
	"os"
	"strings"

	"github.com/sethvargo/go-envconfig"

	"github.com/telepresenceio/telepresence/v2/pkg/version"
)

type Env struct {
	// I'd like to set TELEPRESENCE_LOGIN_DOMAIN,default=auth.datawire.io, but
	// sethvargo/go-envconfig doesn't support filling in the default for our later references to
	// it in following settings, so we have to do the hack with maybeSetDefault below.  *sigh* I
	// guess I'm just spoiled by apro/cmd/amb-sidecar/types/internal/envconfig.
	LoginDomain        string `env:"TELEPRESENCE_LOGIN_DOMAIN,required"`
	LoginAuthURL       string `env:"TELEPRESENCE_LOGIN_AUTH_URL,default=https://${TELEPRESENCE_LOGIN_DOMAIN}/auth"`
	LoginTokenURL      string `env:"TELEPRESENCE_LOGIN_TOKEN_URL,default=https://${TELEPRESENCE_LOGIN_DOMAIN}/token"`
	LoginCompletionURL string `env:"TELEPRESENCE_LOGIN_COMPLETION_URL,default=https://${TELEPRESENCE_LOGIN_DOMAIN}/completion"`
	LoginClientID      string `env:"TELEPRESENCE_LOGIN_CLIENT_ID,default=telepresence-cli"`
	UserInfoURL        string `env:"TELEPRESENCE_USER_INFO_URL,default=https://${TELEPRESENCE_LOGIN_DOMAIN}/api/userinfo"`

	ManagerNamespace string `env:"TELEPRESENCE_MANAGER_NAMESPACE,default=ambassador"`

	// This environment variable becomes the default for the images.registry and images.webhookRegistry
	Registry string `env:"TELEPRESENCE_REGISTRY,default=docker.io/datawire"`

	// This environment variable becomes the default for the images.agentImage and images.webhookAgentImage
	AgentImage string `env:"TELEPRESENCE_AGENT_IMAGE,default="`
}

func (env Env) Get(key string) string {
	switch key {
	case "TELEPRESENCE_LOGIN_DOMAIN":
		return env.LoginDomain
	case "TELEPRESENCE_LOGIN_AUTH_URL":
		return env.LoginAuthURL
	case "TELEPRESENCE_LOGIN_TOKEN_URL":
		return env.LoginTokenURL
	case "TELEPRESENCE_LOGIN_COMPLETION_URL":
		return env.LoginCompletionURL
	case "TELEPRESENCE_LOGIN_CLIENT_ID":
		return env.LoginClientID
	case "TELEPRESENCE_USER_INFO_URL":
		return env.UserInfoURL

	case "TELEPRESENCE_MANAGER_NAMESPACE":
		return env.ManagerNamespace

	default:
		return os.Getenv(key)
	}
}

type envKey struct{}

// WithEnv returns a context with the given Env
func WithEnv(ctx context.Context, env *Env) context.Context {
	return context.WithValue(ctx, envKey{}, env)
}

func GetEnv(ctx context.Context) *Env {
	env, ok := ctx.Value(envKey{}).(*Env)
	if !ok {
		return nil
	}
	return env
}

func LoadEnv(ctx context.Context) (*Env, error) {
	if os.Getenv("TELEPRESENCE_LOGIN_DOMAIN") == "" {
		loginDomain := "auth.datawire.io"
		if os.Getenv("SYSTEMA_ENV") == "staging" {
			// XXX : This is hacky bc we really should move TELEPRESENCE_LOGIN_DOMAIN
			// to the config.yml and get rid of that env var and all the related ones.
			// But I (donnyyung) am about to be on vacation for a week so don't want
			// to make such a huge change and then leave, so I will take care of
			// cleaning this up once I'm back.
			loginDomain = "beta-auth.datawire.io"
		}
		os.Setenv("TELEPRESENCE_LOGIN_DOMAIN", loginDomain)
	}

	var env Env
	if err := envconfig.Process(ctx, &env); err != nil {
		return nil, err
	}
	if env.AgentImage == "" {
		env.AgentImage = "tel2:" + strings.TrimPrefix(version.Version, "v")
	}
	return &env, nil
}
<|endoftext|>


<commit_before>package chClient

import (
	"fmt"

	"git.containerum.net/ch/kube-client/pkg/rest"
	"github.com/containerum/chkit/pkg/chkitErrors"
	"github.com/containerum/chkit/pkg/model"
)

const (
	// ErrUnableToGetNamespace -- unable to get namespace
	ErrUnableToGetNamespace chkitErrors.Err = "unable to get namespace"
)

// GetNamespace -- returns info of namespace with given label
func (client *Client) GetNamespace(label string) (model.Namespace, error) {
	namespace, err := client.kubeAPIClient.GetNamespace(label)
	if err != nil {
		switch err := err.(type) {
		case *rest.UnexpectedHTTPstatusError:
			if err.Status == 404 {
				return model.Namespace{}, ErrUnableToGetNamespace.
					Wrap(fmt.Errorf("namespace %q doesn't exist", label))
			}
		}
		return model.Namespace{}, ErrUnableToGetNamespace.Wrap(err)
	}
	return model.NamespaceFromKube(namespace), nil
}
<commit_msg>fix error handling<commit_after>package chClient

import (
	"fmt"
	"net/http"

	"git.containerum.net/ch/kube-client/pkg/rest"
	"github.com/containerum/chkit/pkg/chkitErrors"
	"github.com/containerum/chkit/pkg/model"
)

const (
	// ErrUnableToGetNamespace -- unable to get namespace
	ErrUnableToGetNamespace chkitErrors.Err = "unable to get namespace"
)

// GetNamespace -- returns info of namespace with given label
func (client *Client) GetNamespace(label string) (model.Namespace, error) {
	namespace, err := client.kubeAPIClient.GetNamespace(label)
	switch err := err.(type) {
	case *rest.UnexpectedHTTPstatusError:
		if err.Status == http.StatusNotFound {
			return model.Namespace{}, ErrUnableToGetNamespace.
				Wrap(fmt.Errorf("namespace %q doesn't exist", label))
		}
	case nil:
		return model.NamespaceFromKube(namespace), nil
	default:
		return model.Namespace{}, ErrUnableToGetNamespace.Wrap(err)
	}
	return model.Namespace{}, nil
}
<|endoftext|>


<commit_before>package schema

import "time"

// A Service is a named service that has a set of templates associated with it.
type Service struct {
	ID      string    `gorethink:"id"`
	Name    string    `gorethink:"name"`
	Type    string    `gorethink:"_type"`   // The type of service.
	Current bool      `gorethink:"current"` // Is this the current service definition.
	CTime   time.Time `gorethink:"ctime"`
}

// Service2Template is a join table that maps a service to templates.
type Service2Template struct {
	ID         string `gorethink:"id"`
	ServiceID  string `gorethink:"service_id"`
	TemplateID string `gorethink:"template_id"`
}

// Template is a consul-template for service configuration/monitoring.
type Template struct {
	ID      string `gorethink:"id"`
	Name    string `gorethink:"name"`
	Path    string `gorethink:"path"`    // Path to template definition
	Body    string `gorethink:"body"`    // The body of the template (same as Path at point in time)
	Version int    `gorethink:"version"` // Version of template. A template can change over time.
}

// ChangeLog tracks the changes to service and template definitions. It allows
// a user to see the difference across definitions.
type ChangeLog struct {
	ID      string    `gorethink:"id"`
	OtherID string    `gorethink:"other_id"`
	Who     string    `gorethink:"who"`
	When    time.Time `gorethink:"when"`
}
<commit_msg>Update schema for storing KV versions.<commit_after>package schema

import "time"

// A Service is a named service that has a set of templates associated with it.
type Service struct {
	ID       string    `gorethink:"id"`
	Name     string    `gorethink:"name"`
	Type     string    `gorethink:"_type"`   // The type of service.
	Current  bool      `gorethink:"current"` // Is this the current service definition.
	CTime    time.Time `gorethink:"ctime"`
	Template Template  `gorethink:"template"`
}

// Template is a consul-template for service configuration/monitoring.
type Template struct {
	ID      string `gorethink:"id"`
	Name    string `gorethink:"name"`
	Path    string `gorethink:"path"`    // Path to template definition
	Body    string `gorethink:"body"`    // The body of the template (same as Path at point in time)
	Version int    `gorethink:"version"` // Version of template. A template can change over time.
}

// ChangeLog tracks the changes to service and template definitions. It allows
// a user to see the difference across definitions.
type ChangeLog struct {
	ID      string    `gorethink:"id"`
	OtherID string    `gorethink:"other_id"`
	Who     string    `gorethink:"who"`
	When    time.Time `gorethink:"when"`
}
<|endoftext|>


<commit_before><commit_msg>hash: Make sure we tidy up if there’s an error from io.Copy.<commit_after><|endoftext|>


<commit_before><commit_msg>set ResponseType to ArrayBuffer<commit_after><|endoftext|>