<commit_before>package data

import (
	"encoding/binary"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net"

	"strconv"

	"github.com/daMupfel/govpn/crypto"
)

type IPAddr uint32
type MACAddr uint64

type ClientHello struct {
	Name     string
	Password string
	MAC      MACAddr
}

type ServerHello struct {
	OK    bool
	Error string
}

type CreateGroupRequest struct {
	Name              string
	Password          string
	NetworkAddr       IPAddr
	NetworkSubnetMask IPAddr
}

type CreateGroupResponse struct {
	OK    bool
	Error string

	IP      IPAddr
	Netmask IPAddr
	Gateway IPAddr
}

type JoinGroupRequest struct {
	Name     string
	Password string
}

type JoinGroupResponseClient struct {
	UserName string
	IP       IPAddr
}

type JoinGroupResponse struct {
	OK    bool
	Error string

	IP      IPAddr
	Netmask IPAddr
	Gateway IPAddr
	Clients []*JoinGroupResponseClient
}
type ListGroupsRequest struct {
}
type ListGroupsResponse struct {
	Groups []string
}

type LeaveGroupRequest struct {
}
type LeaveGroupResponse struct {
	OK    bool
	Error string
}
type ClientJoinedGroupNotification struct {
	Name string
	IP   IPAddr
	MAC  MACAddr
}
type ClientLeftGroupNotification struct {
	Name string
	IP   IPAddr
	MAC  MACAddr
}

const (
	BroadcastMAC MACAddr = 0x0000ffffffffffff
)

func MACAddrToHWAddr(a MACAddr) net.HardwareAddr {
	b := make([]byte, 8)
	binary.LittleEndian.PutUint64(b, uint64(a))
	return net.HardwareAddr(b[0:6])
}

func HWAddrToMACAddr(a net.HardwareAddr) MACAddr {
	b := make([]byte, 8)
	copy(b[0:6], a)
	return MACAddr(binary.LittleEndian.Uint64(b))
}

func IntIPtoNetIP(v IPAddr) net.IP {
	b := make([]byte, 4)
	b[0] = byte(v)
	b[1] = byte(v >> 8)
	b[2] = byte(v >> 16)
	b[3] = byte(v >> 24)
	return b
}

func NetIPtoIntIP(b net.IP) IPAddr {
	return IPAddr(binary.LittleEndian.Uint32(b))
}

const (
	PacketTypeEthernetFrame uint8 = iota
	PacketTypeServerHello
	PacketTypeClientHello
	PacketTypeCreateGroupRequest
	PacketTypeCreateGroupResponse
	PacketTypeJoinGroupRequest
	PacketTypeJoinGroupResponse
	PacketTypeLeaveGroupRequest
	PacketTypeLeaveGroupResponse
	PacketTypeListGroupsRequest
	PacketTypeListGroupsResponse
	PacketTypeClientJoinedGroupNotification
	PacketTypeClientLeftGroupNotification
)

type PacketHeader struct {
	PacketSize     uint16
	PacketType     uint8
	EncryptionType uint8
}

func (v *ServerHello) Serialize() []byte {
	b, _ := json.Marshal(v)
	return b
}

func (v *ClientHello) Serialize() []byte {
	b, _ := json.Marshal(v)
	return b
}

func (v *JoinGroupRequest) Serialize() []byte {
	b, _ := json.Marshal(v)
	return b
}

func (v *JoinGroupResponse) Serialize() []byte {
	b, _ := json.Marshal(v)
	return b
}

func (v *CreateGroupRequest) Serialize() []byte {
	b, _ := json.Marshal(v)
	return b
}

func (v *CreateGroupResponse) Serialize() []byte {
	b, _ := json.Marshal(v)
	return b
}

func (v *ListGroupsRequest) Serialize() []byte {
	b, _ := json.Marshal(v)
	return b
}

func (v *ListGroupsResponse) Serialize() []byte {
	b, _ := json.Marshal(v)
	return b
}

func (v *LeaveGroupRequest) Serialize() []byte {
	b, _ := json.Marshal(v)
	return b
}

func (v *LeaveGroupResponse) Serialize() []byte {
	b, _ := json.Marshal(v)
	return b
}

func (v *ClientJoinedGroupNotification) Serialize() []byte {
	b, _ := json.Marshal(v)
	return b
}

func (v *ClientLeftGroupNotification) Serialize() []byte {
	b, _ := json.Marshal(v)
	return b
}

func DeserializeAndDecryptPacket(r io.Reader) (*PacketHeader, []byte, error) {
	b := make([]byte, 4)
	offset := 0
	for offset < 4 {
		n, err := r.Read(b)
		if err != nil {
			return nil, nil, err
		}
		offset += n
	}

	var pktHdr PacketHeader
	pktHdr.PacketSize = binary.BigEndian.Uint16(b)
	pktHdr.PacketType = b[2]
	pktHdr.EncryptionType = b[3]
	fmt.Println("Packet received with length", pktHdr.PacketSize, "and type", pktHdr.PacketType)

	b = make([]byte, pktHdr.PacketSize)
	offset = 0
	for offset < int(uint(pktHdr.PacketSize)) {
		n, err := r.Read(b[offset:])
		if err != nil {
			fmt.Println(err)
			return nil, nil, err
		}
		fmt.Println("Read", n, "bytes")
		offset += n
	}
	fmt.Println("Read complete packet")
	buf, err := crypto.Decrypt(pktHdr.EncryptionType, b, nil)
	if err != nil {
		return nil, nil, err
	}
	return &pktHdr, buf, nil
}

func EncryptAndSerializePacket(encryptionType, packetType uint8, buffer []byte, w io.Writer) error {
	b, err := crypto.Encrypt(encryptionType, buffer, nil)
	if err != nil {
		return err
	}
	l := len(b)
	if l >= 0x10000 {
		return errors.New("Packet overflow")
	}
	buf := make([]byte, l)
	binary.BigEndian.PutUint16(buf, uint16(l))
	buf[2] = packetType
	buf[3] = encryptionType

	fmt.Println("Packet with length", l)

	copy(buf[4:], b[:])

	offset := 0
	for offset < l {
		n, err := w.Write(buf[offset:])
		if err != nil {
			return err
		}
		offset += n
	}
	fmt.Println("Packet sent with length", l)
	return nil
}

func IPToString(i IPAddr) string {
	ip := IntIPtoNetIP(i)
	return strconv.FormatUint(uint64(ip[0]), 10) + "." +
		strconv.FormatUint(uint64(ip[1]), 10) + "." +
		strconv.FormatUint(uint64(ip[2]), 10) + "." +
		strconv.FormatUint(uint64(ip[3]), 10)
}
<commit_msg>Fixed bug<commit_after>package data

import (
	"encoding/binary"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net"

	"strconv"

	"github.com/daMupfel/govpn/crypto"
)

type IPAddr uint32
type MACAddr uint64

type ClientHello struct {
	Name     string
	Password string
	MAC      MACAddr
}

type ServerHello struct {
	OK    bool
	Error string
}

type CreateGroupRequest struct {
	Name              string
	Password          string
	NetworkAddr       IPAddr
	NetworkSubnetMask IPAddr
}

type CreateGroupResponse struct {
	OK    bool
	Error string

	IP      IPAddr
	Netmask IPAddr
	Gateway IPAddr
}

type JoinGroupRequest struct {
	Name     string
	Password string
}

type JoinGroupResponseClient struct {
	UserName string
	IP       IPAddr
}

type JoinGroupResponse struct {
	OK    bool
	Error string

	IP      IPAddr
	Netmask IPAddr
	Gateway IPAddr
	Clients []*JoinGroupResponseClient
}
type ListGroupsRequest struct {
}
type ListGroupsResponse struct {
	Groups []string
}

type LeaveGroupRequest struct {
}
type LeaveGroupResponse struct {
	OK    bool
	Error string
}
type ClientJoinedGroupNotification struct {
	Name string
	IP   IPAddr
	MAC  MACAddr
}
type ClientLeftGroupNotification struct {
	Name string
	IP   IPAddr
	MAC  MACAddr
}

const (
	BroadcastMAC MACAddr = 0x0000ffffffffffff
)

func MACAddrToHWAddr(a MACAddr) net.HardwareAddr {
	b := make([]byte, 8)
	binary.LittleEndian.PutUint64(b, uint64(a))
	return net.HardwareAddr(b[0:6])
}

func HWAddrToMACAddr(a net.HardwareAddr) MACAddr {
	b := make([]byte, 8)
	copy(b[0:6], a)
	return MACAddr(binary.LittleEndian.Uint64(b))
}

func IntIPtoNetIP(v IPAddr) net.IP {
	b := make([]byte, 4)
	b[0] = byte(v)
	b[1] = byte(v >> 8)
	b[2] = byte(v >> 16)
	b[3] = byte(v >> 24)
	return b
}

func NetIPtoIntIP(b net.IP) IPAddr {
	return IPAddr(binary.LittleEndian.Uint32(b))
}

const (
	PacketTypeEthernetFrame uint8 = iota
	PacketTypeServerHello
	PacketTypeClientHello
	PacketTypeCreateGroupRequest
	PacketTypeCreateGroupResponse
	PacketTypeJoinGroupRequest
	PacketTypeJoinGroupResponse
	PacketTypeLeaveGroupRequest
	PacketTypeLeaveGroupResponse
	PacketTypeListGroupsRequest
	PacketTypeListGroupsResponse
	PacketTypeClientJoinedGroupNotification
	PacketTypeClientLeftGroupNotification
)

type PacketHeader struct {
	PacketSize     uint16
	PacketType     uint8
	EncryptionType uint8
}

func (v *ServerHello) Serialize() []byte {
	b, _ := json.Marshal(v)
	return b
}

func (v *ClientHello) Serialize() []byte {
	b, _ := json.Marshal(v)
	return b
}

func (v *JoinGroupRequest) Serialize() []byte {
	b, _ := json.Marshal(v)
	return b
}

func (v *JoinGroupResponse) Serialize() []byte {
	b, _ := json.Marshal(v)
	return b
}

func (v *CreateGroupRequest) Serialize() []byte {
	b, _ := json.Marshal(v)
	return b
}

func (v *CreateGroupResponse) Serialize() []byte {
	b, _ := json.Marshal(v)
	return b
}

func (v *ListGroupsRequest) Serialize() []byte {
	b, _ := json.Marshal(v)
	return b
}

func (v *ListGroupsResponse) Serialize() []byte {
	b, _ := json.Marshal(v)
	return b
}

func (v *LeaveGroupRequest) Serialize() []byte {
	b, _ := json.Marshal(v)
	return b
}

func (v *LeaveGroupResponse) Serialize() []byte {
	b, _ := json.Marshal(v)
	return b
}

func (v *ClientJoinedGroupNotification) Serialize() []byte {
	b, _ := json.Marshal(v)
	return b
}

func (v *ClientLeftGroupNotification) Serialize() []byte {
	b, _ := json.Marshal(v)
	return b
}

func DeserializeAndDecryptPacket(r io.Reader) (*PacketHeader, []byte, error) {
	b := make([]byte, 4)
	offset := 0
	for offset < 4 {
		n, err := r.Read(b)
		if err != nil {
			return nil, nil, err
		}
		offset += n
	}

	var pktHdr PacketHeader
	pktHdr.PacketSize = binary.BigEndian.Uint16(b)
	pktHdr.PacketType = b[2]
	pktHdr.EncryptionType = b[3]
	fmt.Println("Packet received with length", pktHdr.PacketSize, "and type", pktHdr.PacketType)

	b = make([]byte, pktHdr.PacketSize)
	offset = 0
	for offset < int(uint(pktHdr.PacketSize)) {
		n, err := r.Read(b[offset:])
		if err != nil {
			fmt.Println(err)
			return nil, nil, err
		}
		fmt.Println("Read", n, "bytes")
		offset += n
	}
	fmt.Println("Read complete packet")
	buf, err := crypto.Decrypt(pktHdr.EncryptionType, b, nil)
	if err != nil {
		return nil, nil, err
	}
	return &pktHdr, buf, nil
}

func EncryptAndSerializePacket(encryptionType, packetType uint8, buffer []byte, w io.Writer) error {
	b, err := crypto.Encrypt(encryptionType, buffer, nil)
	if err != nil {
		return err
	}
	l := len(b)
	if l >= 0x10000 {
		return errors.New("Packet overflow")
	}
	buf := make([]byte, l+4)
	binary.BigEndian.PutUint16(buf, uint16(l))
	buf[2] = packetType
	buf[3] = encryptionType
	l += 4
	fmt.Println("Packet with length", l)

	copy(buf[4:], b[:])

	offset := 0
	for offset < l {
		n, err := w.Write(buf[offset:])
		if err != nil {
			return err
		}
		offset += n
	}
	fmt.Println("Packet sent with length", l)
	return nil
}

func IPToString(i IPAddr) string {
	ip := IntIPtoNetIP(i)
	return strconv.FormatUint(uint64(ip[0]), 10) + "." +
		strconv.FormatUint(uint64(ip[1]), 10) + "." +
		strconv.FormatUint(uint64(ip[2]), 10) + "." +
		strconv.FormatUint(uint64(ip[3]), 10)
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net/http"
	"regexp"

	"github.com/sironfoot/go-twitter-bot/data/api"
	"github.com/sironfoot/go-twitter-bot/data/db"
	"github.com/sironfoot/go-twitter-bot/lib/config"

	"goji.io"
	"goji.io/pat"
	"golang.org/x/net/context"
)

func main() {
	var configuration api.Config
	err := config.Load("config.json", "dev", &configuration)
	if err != nil {
		log.Fatal(err)
	}

	addr := flag.String("addr", configuration.AppSettings.ServerAddress, "Address to run server on")
	dbConn := flag.String("db", configuration.Database.ConnectionString, "Database connection string")
	flag.Parse()

	err = db.InitDB(*dbConn)
	if err != nil {
		log.Fatal(err)
	}

	router := goji.NewMux()

	router.UseC(func(next goji.Handler) goji.Handler {
		return goji.HandlerFunc(func(ctx context.Context, res http.ResponseWriter, req *http.Request) {
			appContext := api.AppContext{}
			appContext.Settings = configuration
			ctx = context.WithValue(ctx, "appContext", &appContext)

			next.ServeHTTPC(ctx, res, req)
		})
	})

	router.UseC(func(next goji.Handler) goji.Handler {
		isRootPathMissingTrailingSlash := regexp.MustCompile(`(?i)^/[a-z0-9]+$`)

		return goji.HandlerFunc(func(ctx context.Context, res http.ResponseWriter, req *http.Request) {
			if isRootPathMissingTrailingSlash.MatchString(req.URL.Path) {
				res.Header().Set("Location", req.URL.Path+"/")
				res.WriteHeader(http.StatusMovedPermanently)
			} else {
				next.ServeHTTPC(ctx, res, req)
			}
		})
	})

	router.UseC(func(next goji.Handler) goji.Handler {
		return goji.HandlerFunc(func(ctx context.Context, res http.ResponseWriter, req *http.Request) {
			next.ServeHTTPC(ctx, res, req)

			response := ctx.Value("appContext").(*api.AppContext).Response

			res.Header().Set("Content-Type", "application/json")

			if response == nil {
				response = struct {
					Message string `json:"message"`
				}{"Response message was missing."}
				res.WriteHeader(http.StatusInternalServerError)
			}

			data, jsonErr := json.MarshalIndent(response, "", "    ")
			if jsonErr != nil {
				panic(jsonErr)
			}
			res.Write(data)
		})
	})

	router.HandleFuncC(pat.Get("/"), func(ctx context.Context, res http.ResponseWriter, req *http.Request) {
		fmt.Fprintf(res, "Hello from GoBot Data server\n")
	})

	// Account
	account := goji.SubMux()
	router.HandleC(pat.New("/account/*"), account)

	account.HandleFuncC(pat.Put("/login"), api.AccountLogin)
	account.HandleFuncC(pat.Put("/logout"), api.AccountLogout)
	account.HandleFuncC(pat.Post("/signup"), api.AccountSignup)

	// Users
	users := goji.SubMux()
	router.HandleC(pat.New("/users/*"), users)

	users.HandleFuncC(pat.Get("/"), api.UsersAll)
	users.HandleFuncC(pat.Post("/"), api.UserCreate)
	users.HandleFuncC(pat.Get("/:userID"), api.UserGet)
	users.HandleFuncC(pat.Put("/:userID"), api.UserUpdate)
	users.HandleFuncC(pat.Delete("/:userID"), api.UserDelete)

	// TwitterAccounts
	twitterAccounts := goji.SubMux()
	router.HandleC(pat.New("/twitterAccounts/*"), twitterAccounts)

	twitterAccounts.HandleFuncC(pat.Get("/"), api.TwitterAccountsAll)
	twitterAccounts.HandleFuncC(pat.Get("/:twitterAccountID"), api.TwitterAccountGet)

	twitterAccounts.HandleFuncC(pat.Get("/:twitterAccountID/tweets"), api.TwitterAccountGetWithTweets)
	twitterAccounts.HandleFuncC(pat.Post("/:twitterAccountID/tweets"), api.TwitterAccountTweetCreate)
	twitterAccounts.HandleFuncC(pat.Put("/:twitterAccountID/tweets/:tweetID"), api.TwitterAccountTweetUpdate)
	twitterAccounts.HandleFuncC(pat.Delete("/:twitterAccountID/tweets/:tweetID"), api.TwitterAccountTweetDelete)

	server := http.Server{
		Addr:    *addr,
		Handler: router,
	}

	log.Printf("GoBot Data Server running on %s...\n", *addr)
	log.Fatal(server.ListenAndServe())
}
<commit_msg>fixed: no trailing slash for URLs needed.<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net/http"

	"github.com/sironfoot/go-twitter-bot/data/api"
	"github.com/sironfoot/go-twitter-bot/data/db"
	"github.com/sironfoot/go-twitter-bot/lib/config"

	"goji.io"
	"goji.io/pat"
	"golang.org/x/net/context"
)

func main() {
	var configuration api.Config
	err := config.Load("config.json", "dev", &configuration)
	if err != nil {
		log.Fatal(err)
	}

	addr := flag.String("addr", configuration.AppSettings.ServerAddress, "Address to run server on")
	dbConn := flag.String("db", configuration.Database.ConnectionString, "Database connection string")
	flag.Parse()

	err = db.InitDB(*dbConn)
	if err != nil {
		log.Fatal(err)
	}

	router := goji.NewMux()

	router.UseC(func(next goji.Handler) goji.Handler {
		return goji.HandlerFunc(func(ctx context.Context, res http.ResponseWriter, req *http.Request) {
			appContext := api.AppContext{}
			appContext.Settings = configuration
			ctx = context.WithValue(ctx, "appContext", &appContext)

			next.ServeHTTPC(ctx, res, req)
		})
	})

	router.UseC(func(next goji.Handler) goji.Handler {
		//isRootPathMissingTrailingSlash := regexp.MustCompile(`(?i)^/[a-z0-9]+$`)

		return goji.HandlerFunc(func(ctx context.Context, res http.ResponseWriter, req *http.Request) {
			// if isRootPathMissingTrailingSlash.MatchString(req.URL.Path) {
			// 	res.Header().Set("Location", req.URL.Path+"/")
			// 	res.WriteHeader(http.StatusMovedPermanently)
			// } else {
			next.ServeHTTPC(ctx, res, req)
			//}
		})
	})

	router.UseC(func(next goji.Handler) goji.Handler {
		return goji.HandlerFunc(func(ctx context.Context, res http.ResponseWriter, req *http.Request) {
			next.ServeHTTPC(ctx, res, req)

			response := ctx.Value("appContext").(*api.AppContext).Response

			res.Header().Set("Content-Type", "application/json")

			if response == nil {
				response = struct {
					Message string `json:"message"`
				}{"Response message was missing."}
				res.WriteHeader(http.StatusInternalServerError)
			}

			data, jsonErr := json.MarshalIndent(response, "", "    ")
			if jsonErr != nil {
				panic(jsonErr)
			}
			res.Write(data)
		})
	})

	router.HandleFuncC(pat.Get("/"), func(ctx context.Context, res http.ResponseWriter, req *http.Request) {
		fmt.Fprintf(res, "Hello from GoBot Data server\n")
	})

	// Account
	account := goji.SubMux()
	router.HandleC(pat.New("/account/*"), account)

	account.HandleFuncC(pat.Put("/login"), api.AccountLogin)
	account.HandleFuncC(pat.Put("/logout"), api.AccountLogout)
	account.HandleFuncC(pat.Post("/signup"), api.AccountSignup)

	// Users
	users := goji.SubMux()
	router.HandleC(pat.New("/users/*"), users)
	router.HandleC(pat.New("/users"), users)

	users.HandleFuncC(pat.Get(""), api.UsersAll)
	users.HandleFuncC(pat.Post(""), api.UserCreate)
	users.HandleFuncC(pat.Get("/:userID"), api.UserGet)
	users.HandleFuncC(pat.Put("/:userID"), api.UserUpdate)
	users.HandleFuncC(pat.Delete("/:userID"), api.UserDelete)

	// TwitterAccounts
	twitterAccounts := goji.SubMux()
	router.HandleC(pat.New("/twitterAccounts/*"), twitterAccounts)
	router.HandleC(pat.New("/twitterAccounts"), twitterAccounts)

	twitterAccounts.HandleFuncC(pat.Get(""), api.TwitterAccountsAll)
	twitterAccounts.HandleFuncC(pat.Get("/:twitterAccountID"), api.TwitterAccountGet)

	twitterAccounts.HandleFuncC(pat.Get("/:twitterAccountID/tweets"), api.TwitterAccountGetWithTweets)
	twitterAccounts.HandleFuncC(pat.Post("/:twitterAccountID/tweets"), api.TwitterAccountTweetCreate)
	twitterAccounts.HandleFuncC(pat.Put("/:twitterAccountID/tweets/:tweetID"), api.TwitterAccountTweetUpdate)
	twitterAccounts.HandleFuncC(pat.Delete("/:twitterAccountID/tweets/:tweetID"), api.TwitterAccountTweetDelete)

	server := http.Server{
		Addr:    *addr,
		Handler: router,
	}

	log.Printf("GoBot Data Server running on %s...\n", *addr)
	log.Fatal(server.ListenAndServe())
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"os"
	log "github.com/Sirupsen/logrus"
)

var etcdLocalURL *string
var backupPath *string

func main() {

	getParameters ()

	if err := restoreBackup(*etcdLocalURL, *backupPath); err != nil {
		log.Fatalf("ERROR: %s", err)
	}

}

func getParameters () {

	var defaultEtcdLocalURL string = "127.0.0.1"
	if u := os.Getenv("ETCD_URL"); u != "" {
		defaultEtcdLocalURL = u
	}

	etcdLocalURL = flag.String("etcd-url", defaultEtcdLocalURL,
		"URL of the etcd node. " +
			"Environment variable: ETCD_URL")

	var defaultBackupPath string = "/tmp/etcd-backup.gz"
	if p := os.Getenv("ETCD_BACKUP_PATH"); p != "" {
		defaultBackupPath = p
	}

	backupPath = flag.String("backup-path", defaultBackupPath,
		"The path to the backup file. " +
			"Environment variable: ETCD_BACKUP_PATH")

	flag.Parse()
}<commit_msg>renamed getParameters to magig method init<commit_after>package main

import (
	"flag"
	"os"
	log "github.com/Sirupsen/logrus"
)

var etcdLocalURL *string
var backupPath *string

func main() {

	if err := restoreBackup(*etcdLocalURL, *backupPath); err != nil {
		log.Fatalf("ERROR: %s", err)
	}

}

func init () {

	var defaultEtcdLocalURL string = "127.0.0.1"
	if u := os.Getenv("ETCD_URL"); u != "" {
		defaultEtcdLocalURL = u
	}

	etcdLocalURL = flag.String("etcd-url", defaultEtcdLocalURL,
		"URL of the etcd node. " +
			"Environment variable: ETCD_URL")

	var defaultBackupPath string = "/tmp/etcd-backup.gz"
	if p := os.Getenv("ETCD_BACKUP_PATH"); p != "" {
		defaultBackupPath = p
	}

	backupPath = flag.String("backup-path", defaultBackupPath,
		"The path to the backup file. " +
			"Environment variable: ETCD_BACKUP_PATH")

	flag.Parse()
}<|endoftext|>


<commit_before>// package cbreaker implements circuit breaker similar to  https://github.com/Netflix/Hystrix/wiki/How-it-Works
//
// Vulcan circuit breaker watches the error condtion to match
// after which it activates the fallback scenario, e.g. returns the response code
// or redirects the request to another location

// Circuit breakers start in the Standby state first, observing responses and watching location metrics.
//
// Once the Circuit breaker condition is met, it enters the "Tripped" state, where it activates fallback scenario
// for all requests during the FallbackDuration time period and reset the stats for the location.
//
// After FallbackDuration time period passes, Circuit breaker enters "Recovering" state, during that state it will
// start passing some traffic back to the endpoints, increasing the amount of passed requests using linear function:
//
//    allowedRequestsRatio = 0.5 * (Now() - StartRecovery())/RecoveryDuration
//
// Two scenarios are possible in the "Recovering" state:
// 1. Condition matches again, this will reset the state to "Tripped" and reset the timer.
// 2. Condition does not match, circuit breaker enters "Standby" state
//
// It is possible to define actions (e.g. webhooks) of transitions between states:
//
// * OnTripped action is called on transition (Standby -> Tripped)
// * OnStandby action is called on transition (Recovering -> Standby)
//
package cbreaker

import (
	"fmt"
	"net/http"
	"sync"
	"time"

	"github.com/vulcand/oxy/memmetrics"
	"github.com/vulcand/oxy/utils"
	"github.com/mailgun/timetools"
)

// CircuitBreaker is http.Handler that implements circuit breaker pattern
type CircuitBreaker struct {
	m       *sync.RWMutex
	metrics *memmetrics.RTMetrics

	condition hpredicate
	duration  time.Duration

	fallbackDuration time.Duration
	recoveryDuration time.Duration

	onTripped SideEffect
	onStandby SideEffect

	state cbState
	until time.Time

	rc *ratioController

	checkPeriod time.Duration
	lastCheck   time.Time

	fallback http.Handler
	next     http.Handler

	log   utils.Logger
	clock timetools.TimeProvider
}

// New creates a new CircuitBreaker middleware
func New(next http.Handler, expression string, options ...CircuitBreakerOption) (*CircuitBreaker, error) {
	cb := &CircuitBreaker{
		m:    &sync.RWMutex{},
		next: next,
		// Default values. Might be overwritten by options below.
		clock:            &timetools.RealTime{},
		checkPeriod:      defaultCheckPeriod,
		fallbackDuration: defaultFallbackDuration,
		recoveryDuration: defaultRecoveryDuration,
		fallback:         defaultFallback,
		log:              utils.NullLogger,
	}

	for _, s := range options {
		if err := s(cb); err != nil {
			return nil, err
		}
	}

	condition, err := parseExpression(expression)
	if err != nil {
		return nil, err
	}
	cb.condition = condition

	mt, err := memmetrics.NewRTMetrics()
	if err != nil {
		return nil, err
	}
	cb.metrics = mt

	return cb, nil
}

func (c *CircuitBreaker) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	if c.activateFallback(w, req) {
		c.fallback.ServeHTTP(w, req)
		return
	}
	c.serve(w, req)
}

func (c *CircuitBreaker) Wrap(next http.Handler) {
	c.next = next
}

// updateState updates internal state and returns true if fallback should be used and false otherwise
func (c *CircuitBreaker) activateFallback(w http.ResponseWriter, req *http.Request) bool {
	// Quick check with read locks optimized for normal operation use-case
	if c.isStandby() {
		return false
	}
	// Circuit breaker is in tripped or recovering state
	c.m.Lock()
	defer c.m.Unlock()

	c.log.Infof("%v is in error state", c)

	switch c.state {
	case stateStandby:
		// someone else has set it to standby just now
		return false
	case stateTripped:
		if c.clock.UtcNow().Before(c.until) {
			return true
		}
		// We have been in active state enough, enter recovering state
		c.setRecovering()
		fallthrough
	case stateRecovering:
		// We have been in recovering state enough, enter standby and allow request
		if c.clock.UtcNow().After(c.until) {
			c.setState(stateStandby, c.clock.UtcNow())
			return false
		}
		// ratio controller allows this request
		if c.rc.allowRequest() {
			return false
		}
		return true
	}
	return false
}

func (c *CircuitBreaker) serve(w http.ResponseWriter, req *http.Request) {
	start := c.clock.UtcNow()
	p := &utils.ProxyWriter{W: w}

	c.next.ServeHTTP(p, req)

	latency := c.clock.UtcNow().Sub(start)
	c.metrics.Record(p.Code, latency)

	// Note that this call is less expensive than it looks -- checkCondition only performs the real check
	// periodically. Because of that we can afford to call it here on every single response.
	c.checkAndSet()
}

func (c *CircuitBreaker) isStandby() bool {
	c.m.RLock()
	defer c.m.RUnlock()
	return c.state == stateStandby
}

// String returns log-friendly representation of the circuit breaker state
func (c *CircuitBreaker) String() string {
	switch c.state {
	case stateTripped, stateRecovering:
		return fmt.Sprintf("CircuitBreaker(state=%v, until=%v)", c.state, c.until)
	default:
		return fmt.Sprintf("CircuitBreaker(state=%v)", c.state)
	}
}

// exec executes side effect
func (c *CircuitBreaker) exec(s SideEffect) {
	if s == nil {
		return
	}
	go func() {
		if err := s.Exec(); err != nil {
			c.log.Errorf("%v side effect failure: %v", c, err)
		}
	}()
}

func (c *CircuitBreaker) setState(new cbState, until time.Time) {
	c.log.Infof("%v setting state to %v, until %v", c, new, until)
	c.state = new
	c.until = until
	switch new {
	case stateTripped:
		c.exec(c.onTripped)
	case stateStandby:
		c.exec(c.onStandby)
	}
}

func (c *CircuitBreaker) timeToCheck() bool {
	c.m.RLock()
	defer c.m.RUnlock()
	return c.clock.UtcNow().After(c.lastCheck)
}

// Checks if tripping condition matches and sets circuit breaker to the tripped state
func (c *CircuitBreaker) checkAndSet() {
	if !c.timeToCheck() {
		return
	}

	c.m.Lock()
	defer c.m.Unlock()

	// Other goroutine could have updated the lastCheck variable before we grabbed mutex
	if !c.clock.UtcNow().After(c.lastCheck) {
		return
	}
	c.lastCheck = c.clock.UtcNow().Add(c.checkPeriod)

	if c.state == stateTripped {
		c.log.Infof("%v skip set tripped", c)
		return
	}

	if !c.condition(c) {
		return
	}

	c.setState(stateTripped, c.clock.UtcNow().Add(c.fallbackDuration))
	c.metrics.Reset()
}

func (c *CircuitBreaker) setRecovering() {
	c.setState(stateRecovering, c.clock.UtcNow().Add(c.recoveryDuration))
	c.rc = newRatioController(c.clock, c.recoveryDuration)
}

// CircuitBreakerOption represents an option you can pass to New.
// See the documentation for the individual options below.
type CircuitBreakerOption func(*CircuitBreaker) error

// Clock allows you to fake che CircuitBreaker's view of the current time.
// Intended for unit tests.
func Clock(clock timetools.TimeProvider) CircuitBreakerOption {
	return func(c *CircuitBreaker) error {
		c.clock = clock
		return nil
	}
}

// FallbackDuration is how long the CircuitBreaker will remain in the Tripped
// state before trying to recover.
func FallbackDuration(d time.Duration) CircuitBreakerOption {
	return func(c *CircuitBreaker) error {
		c.fallbackDuration = d
		return nil
	}
}

// RecoveryDuration is how long the CircuitBreaker will take to ramp up
// requests during the Recovering state.
func RecoveryDuration(d time.Duration) CircuitBreakerOption {
	return func(c *CircuitBreaker) error {
		c.recoveryDuration = d
		return nil
	}
}

// CheckPeriod is how long the CircuitBreaker will wait between successive
// checks of the breaker condition.
func CheckPeriod(d time.Duration) CircuitBreakerOption {
	return func(c *CircuitBreaker) error {
		c.checkPeriod = d
		return nil
	}
}

// OnTripped sets a SideEffect to run when entering the Tripped state.
// Only one SideEffect can be set for this hook.
func OnTripped(s SideEffect) CircuitBreakerOption {
	return func(c *CircuitBreaker) error {
		c.onTripped = s
		return nil
	}
}

// OnTripped sets a SideEffect to run when entering the Standby state.
// Only one SideEffect can be set for this hook.
func OnStandby(s SideEffect) CircuitBreakerOption {
	return func(c *CircuitBreaker) error {
		c.onStandby = s
		return nil
	}
}

// Fallback defines the http.Handler that the CircuitBreaker should route
// requests to when it prevents a request from taking its normal path.
func Fallback(h http.Handler) CircuitBreakerOption {
	return func(c *CircuitBreaker) error {
		c.fallback = h
		return nil
	}
}

// Logger adds logging for the CircuitBreaker.
func Logger(l utils.Logger) CircuitBreakerOption {
	return func(c *CircuitBreaker) error {
		c.log = l
		return nil
	}
}

// cbState is the state of the circuit breaker
type cbState int

func (s cbState) String() string {
	switch s {
	case stateStandby:
		return "standby"
	case stateTripped:
		return "tripped"
	case stateRecovering:
		return "recovering"
	}
	return "undefined"
}

const (
	// CircuitBreaker is passing all requests and watching stats
	stateStandby = iota
	// CircuitBreaker activates fallback scenario for all requests
	stateTripped
	// CircuitBreaker passes some requests to go through, rejecting others
	stateRecovering
)

const (
	defaultFallbackDuration = 10 * time.Second
	defaultRecoveryDuration = 10 * time.Second
	defaultCheckPeriod      = 100 * time.Millisecond
)

var defaultFallback = &fallback{}

type fallback struct {
}

func (f *fallback) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	w.WriteHeader(http.StatusServiceUnavailable)
	w.Write([]byte(http.StatusText(http.StatusServiceUnavailable)))
}
<commit_msg>remove the extra var duration(tim.duration)<commit_after>// package cbreaker implements circuit breaker similar to  https://github.com/Netflix/Hystrix/wiki/How-it-Works
//
// Vulcan circuit breaker watches the error condtion to match
// after which it activates the fallback scenario, e.g. returns the response code
// or redirects the request to another location

// Circuit breakers start in the Standby state first, observing responses and watching location metrics.
//
// Once the Circuit breaker condition is met, it enters the "Tripped" state, where it activates fallback scenario
// for all requests during the FallbackDuration time period and reset the stats for the location.
//
// After FallbackDuration time period passes, Circuit breaker enters "Recovering" state, during that state it will
// start passing some traffic back to the endpoints, increasing the amount of passed requests using linear function:
//
//    allowedRequestsRatio = 0.5 * (Now() - StartRecovery())/RecoveryDuration
//
// Two scenarios are possible in the "Recovering" state:
// 1. Condition matches again, this will reset the state to "Tripped" and reset the timer.
// 2. Condition does not match, circuit breaker enters "Standby" state
//
// It is possible to define actions (e.g. webhooks) of transitions between states:
//
// * OnTripped action is called on transition (Standby -> Tripped)
// * OnStandby action is called on transition (Recovering -> Standby)
//
package cbreaker

import (
	"fmt"
	"net/http"
	"sync"
	"time"

	"github.com/vulcand/oxy/memmetrics"
	"github.com/vulcand/oxy/utils"
	"github.com/mailgun/timetools"
)

// CircuitBreaker is http.Handler that implements circuit breaker pattern
type CircuitBreaker struct {
	m       *sync.RWMutex
	metrics *memmetrics.RTMetrics

	condition hpredicate

	fallbackDuration time.Duration
	recoveryDuration time.Duration

	onTripped SideEffect
	onStandby SideEffect

	state cbState
	until time.Time

	rc *ratioController

	checkPeriod time.Duration
	lastCheck   time.Time

	fallback http.Handler
	next     http.Handler

	log   utils.Logger
	clock timetools.TimeProvider
}

// New creates a new CircuitBreaker middleware
func New(next http.Handler, expression string, options ...CircuitBreakerOption) (*CircuitBreaker, error) {
	cb := &CircuitBreaker{
		m:    &sync.RWMutex{},
		next: next,
		// Default values. Might be overwritten by options below.
		clock:            &timetools.RealTime{},
		checkPeriod:      defaultCheckPeriod,
		fallbackDuration: defaultFallbackDuration,
		recoveryDuration: defaultRecoveryDuration,
		fallback:         defaultFallback,
		log:              utils.NullLogger,
	}

	for _, s := range options {
		if err := s(cb); err != nil {
			return nil, err
		}
	}

	condition, err := parseExpression(expression)
	if err != nil {
		return nil, err
	}
	cb.condition = condition

	mt, err := memmetrics.NewRTMetrics()
	if err != nil {
		return nil, err
	}
	cb.metrics = mt

	return cb, nil
}

func (c *CircuitBreaker) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	if c.activateFallback(w, req) {
		c.fallback.ServeHTTP(w, req)
		return
	}
	c.serve(w, req)
}

func (c *CircuitBreaker) Wrap(next http.Handler) {
	c.next = next
}

// updateState updates internal state and returns true if fallback should be used and false otherwise
func (c *CircuitBreaker) activateFallback(w http.ResponseWriter, req *http.Request) bool {
	// Quick check with read locks optimized for normal operation use-case
	if c.isStandby() {
		return false
	}
	// Circuit breaker is in tripped or recovering state
	c.m.Lock()
	defer c.m.Unlock()

	c.log.Infof("%v is in error state", c)

	switch c.state {
	case stateStandby:
		// someone else has set it to standby just now
		return false
	case stateTripped:
		if c.clock.UtcNow().Before(c.until) {
			return true
		}
		// We have been in active state enough, enter recovering state
		c.setRecovering()
		fallthrough
	case stateRecovering:
		// We have been in recovering state enough, enter standby and allow request
		if c.clock.UtcNow().After(c.until) {
			c.setState(stateStandby, c.clock.UtcNow())
			return false
		}
		// ratio controller allows this request
		if c.rc.allowRequest() {
			return false
		}
		return true
	}
	return false
}

func (c *CircuitBreaker) serve(w http.ResponseWriter, req *http.Request) {
	start := c.clock.UtcNow()
	p := &utils.ProxyWriter{W: w}

	c.next.ServeHTTP(p, req)

	latency := c.clock.UtcNow().Sub(start)
	c.metrics.Record(p.Code, latency)

	// Note that this call is less expensive than it looks -- checkCondition only performs the real check
	// periodically. Because of that we can afford to call it here on every single response.
	c.checkAndSet()
}

func (c *CircuitBreaker) isStandby() bool {
	c.m.RLock()
	defer c.m.RUnlock()
	return c.state == stateStandby
}

// String returns log-friendly representation of the circuit breaker state
func (c *CircuitBreaker) String() string {
	switch c.state {
	case stateTripped, stateRecovering:
		return fmt.Sprintf("CircuitBreaker(state=%v, until=%v)", c.state, c.until)
	default:
		return fmt.Sprintf("CircuitBreaker(state=%v)", c.state)
	}
}

// exec executes side effect
func (c *CircuitBreaker) exec(s SideEffect) {
	if s == nil {
		return
	}
	go func() {
		if err := s.Exec(); err != nil {
			c.log.Errorf("%v side effect failure: %v", c, err)
		}
	}()
}

func (c *CircuitBreaker) setState(new cbState, until time.Time) {
	c.log.Infof("%v setting state to %v, until %v", c, new, until)
	c.state = new
	c.until = until
	switch new {
	case stateTripped:
		c.exec(c.onTripped)
	case stateStandby:
		c.exec(c.onStandby)
	}
}

func (c *CircuitBreaker) timeToCheck() bool {
	c.m.RLock()
	defer c.m.RUnlock()
	return c.clock.UtcNow().After(c.lastCheck)
}

// Checks if tripping condition matches and sets circuit breaker to the tripped state
func (c *CircuitBreaker) checkAndSet() {
	if !c.timeToCheck() {
		return
	}

	c.m.Lock()
	defer c.m.Unlock()

	// Other goroutine could have updated the lastCheck variable before we grabbed mutex
	if !c.clock.UtcNow().After(c.lastCheck) {
		return
	}
	c.lastCheck = c.clock.UtcNow().Add(c.checkPeriod)

	if c.state == stateTripped {
		c.log.Infof("%v skip set tripped", c)
		return
	}

	if !c.condition(c) {
		return
	}

	c.setState(stateTripped, c.clock.UtcNow().Add(c.fallbackDuration))
	c.metrics.Reset()
}

func (c *CircuitBreaker) setRecovering() {
	c.setState(stateRecovering, c.clock.UtcNow().Add(c.recoveryDuration))
	c.rc = newRatioController(c.clock, c.recoveryDuration)
}

// CircuitBreakerOption represents an option you can pass to New.
// See the documentation for the individual options below.
type CircuitBreakerOption func(*CircuitBreaker) error

// Clock allows you to fake che CircuitBreaker's view of the current time.
// Intended for unit tests.
func Clock(clock timetools.TimeProvider) CircuitBreakerOption {
	return func(c *CircuitBreaker) error {
		c.clock = clock
		return nil
	}
}

// FallbackDuration is how long the CircuitBreaker will remain in the Tripped
// state before trying to recover.
func FallbackDuration(d time.Duration) CircuitBreakerOption {
	return func(c *CircuitBreaker) error {
		c.fallbackDuration = d
		return nil
	}
}

// RecoveryDuration is how long the CircuitBreaker will take to ramp up
// requests during the Recovering state.
func RecoveryDuration(d time.Duration) CircuitBreakerOption {
	return func(c *CircuitBreaker) error {
		c.recoveryDuration = d
		return nil
	}
}

// CheckPeriod is how long the CircuitBreaker will wait between successive
// checks of the breaker condition.
func CheckPeriod(d time.Duration) CircuitBreakerOption {
	return func(c *CircuitBreaker) error {
		c.checkPeriod = d
		return nil
	}
}

// OnTripped sets a SideEffect to run when entering the Tripped state.
// Only one SideEffect can be set for this hook.
func OnTripped(s SideEffect) CircuitBreakerOption {
	return func(c *CircuitBreaker) error {
		c.onTripped = s
		return nil
	}
}

// OnTripped sets a SideEffect to run when entering the Standby state.
// Only one SideEffect can be set for this hook.
func OnStandby(s SideEffect) CircuitBreakerOption {
	return func(c *CircuitBreaker) error {
		c.onStandby = s
		return nil
	}
}

// Fallback defines the http.Handler that the CircuitBreaker should route
// requests to when it prevents a request from taking its normal path.
func Fallback(h http.Handler) CircuitBreakerOption {
	return func(c *CircuitBreaker) error {
		c.fallback = h
		return nil
	}
}

// Logger adds logging for the CircuitBreaker.
func Logger(l utils.Logger) CircuitBreakerOption {
	return func(c *CircuitBreaker) error {
		c.log = l
		return nil
	}
}

// cbState is the state of the circuit breaker
type cbState int

func (s cbState) String() string {
	switch s {
	case stateStandby:
		return "standby"
	case stateTripped:
		return "tripped"
	case stateRecovering:
		return "recovering"
	}
	return "undefined"
}

const (
	// CircuitBreaker is passing all requests and watching stats
	stateStandby = iota
	// CircuitBreaker activates fallback scenario for all requests
	stateTripped
	// CircuitBreaker passes some requests to go through, rejecting others
	stateRecovering
)

const (
	defaultFallbackDuration = 10 * time.Second
	defaultRecoveryDuration = 10 * time.Second
	defaultCheckPeriod      = 100 * time.Millisecond
)

var defaultFallback = &fallback{}

type fallback struct {
}

func (f *fallback) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	w.WriteHeader(http.StatusServiceUnavailable)
	w.Write([]byte(http.StatusText(http.StatusServiceUnavailable)))
}
<|endoftext|>


<commit_before>/*
Copyright 2016 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 common

import (
	"fmt"

	"k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/uuid"
	"k8s.io/kubernetes/test/e2e/framework"
	e2elog "k8s.io/kubernetes/test/e2e/framework/log"
	imageutils "k8s.io/kubernetes/test/utils/image"

	"github.com/onsi/ginkgo"
)

var _ = ginkgo.Describe("[sig-node] ConfigMap", func() {
	f := framework.NewDefaultFramework("configmap")

	/*
		Release : v1.9
		Testname: ConfigMap, from environment field
		Description: Create a Pod with an environment variable value set using a value from ConfigMap. A ConfigMap value MUST be accessible in the container environment.
	*/
	framework.ConformanceIt("should be consumable via environment variable [NodeConformance]", func() {
		name := "configmap-test-" + string(uuid.NewUUID())
		configMap := newConfigMap(f, name)
		ginkgo.By(fmt.Sprintf("Creating configMap %v/%v", f.Namespace.Name, configMap.Name))
		var err error
		if configMap, err = f.ClientSet.CoreV1().ConfigMaps(f.Namespace.Name).Create(configMap); err != nil {
			e2elog.Failf("unable to create test configMap %s: %v", configMap.Name, err)
		}

		pod := &v1.Pod{
			ObjectMeta: metav1.ObjectMeta{
				Name: "pod-configmaps-" + string(uuid.NewUUID()),
			},
			Spec: v1.PodSpec{
				Containers: []v1.Container{
					{
						Name:    "env-test",
						Image:   imageutils.GetE2EImage(imageutils.BusyBox),
						Command: []string{"sh", "-c", "env"},
						Env: []v1.EnvVar{
							{
								Name: "CONFIG_DATA_1",
								ValueFrom: &v1.EnvVarSource{
									ConfigMapKeyRef: &v1.ConfigMapKeySelector{
										LocalObjectReference: v1.LocalObjectReference{
											Name: name,
										},
										Key: "data-1",
									},
								},
							},
						},
					},
				},
				RestartPolicy: v1.RestartPolicyNever,
			},
		}

		f.TestContainerOutput("consume configMaps", pod, 0, []string{
			"CONFIG_DATA_1=value-1",
		})
	})

	/*
		Release: v1.9
		Testname: ConfigMap, from environment variables
		Description: Create a Pod with a environment source from ConfigMap. All ConfigMap values MUST be available as environment variables in the container.
	*/
	framework.ConformanceIt("should be consumable via the environment [NodeConformance]", func() {
		name := "configmap-test-" + string(uuid.NewUUID())
		configMap := newEnvFromConfigMap(f, name)
		ginkgo.By(fmt.Sprintf("Creating configMap %v/%v", f.Namespace.Name, configMap.Name))
		var err error
		if configMap, err = f.ClientSet.CoreV1().ConfigMaps(f.Namespace.Name).Create(configMap); err != nil {
			e2elog.Failf("unable to create test configMap %s: %v", configMap.Name, err)
		}

		pod := &v1.Pod{
			ObjectMeta: metav1.ObjectMeta{
				Name: "pod-configmaps-" + string(uuid.NewUUID()),
			},
			Spec: v1.PodSpec{
				Containers: []v1.Container{
					{
						Name:    "env-test",
						Image:   imageutils.GetE2EImage(imageutils.BusyBox),
						Command: []string{"sh", "-c", "env"},
						EnvFrom: []v1.EnvFromSource{
							{
								ConfigMapRef: &v1.ConfigMapEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: name}},
							},
							{
								Prefix:       "p_",
								ConfigMapRef: &v1.ConfigMapEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: name}},
							},
						},
					},
				},
				RestartPolicy: v1.RestartPolicyNever,
			},
		}

		f.TestContainerOutput("consume configMaps", pod, 0, []string{
			"data_1=value-1", "data_2=value-2", "data_3=value-3",
			"p_data_1=value-1", "p_data_2=value-2", "p_data_3=value-3",
		})
	})

	/*
	   Release : v1.14
	   Testname: ConfigMap, with empty-key
	   Description: Attempt to create a ConfigMap with an empty key. The creation MUST fail.
	*/
	framework.ConformanceIt("should fail to create ConfigMap with empty key", func() {
		configMap, err := newConfigMapWithEmptyKey(f)
		framework.ExpectError(err, "created configMap %q with empty key in namespace %q", configMap.Name, f.Namespace.Name)
	})
})

func newEnvFromConfigMap(f *framework.Framework, name string) *v1.ConfigMap {
	return &v1.ConfigMap{
		ObjectMeta: metav1.ObjectMeta{
			Namespace: f.Namespace.Name,
			Name:      name,
		},
		Data: map[string]string{
			"data_1": "value-1",
			"data_2": "value-2",
			"data_3": "value-3",
		},
	}
}

func newConfigMapWithEmptyKey(f *framework.Framework) (*v1.ConfigMap, error) {
	name := "configmap-test-emptyKey-" + string(uuid.NewUUID())
	configMap := &v1.ConfigMap{
		ObjectMeta: metav1.ObjectMeta{
			Namespace: f.Namespace.Name,
			Name:      name,
		},
		Data: map[string]string{
			"": "value-1",
		},
	}

	ginkgo.By(fmt.Sprintf("Creating configMap that has name %s", configMap.Name))
	return f.ClientSet.CoreV1().ConfigMaps(f.Namespace.Name).Create(configMap)
}
<commit_msg>Add ConfigMap patch e2e test with validation step<commit_after>/*
Copyright 2016 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 common

import (
	"fmt"

	"k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/uuid"
	"k8s.io/kubernetes/test/e2e/framework"
	e2elog "k8s.io/kubernetes/test/e2e/framework/log"
	imageutils "k8s.io/kubernetes/test/utils/image"

	"github.com/onsi/ginkgo"
	"github.com/onsi/gomega"
)

var _ = ginkgo.Describe("[sig-node] ConfigMap", func() {
	f := framework.NewDefaultFramework("configmap")

	/*
		Release : v1.9
		Testname: ConfigMap, from environment field
		Description: Create a Pod with an environment variable value set using a value from ConfigMap. A ConfigMap value MUST be accessible in the container environment.
	*/
	framework.ConformanceIt("should be consumable via environment variable [NodeConformance]", func() {
		name := "configmap-test-" + string(uuid.NewUUID())
		configMap := newConfigMap(f, name)
		ginkgo.By(fmt.Sprintf("Creating configMap %v/%v", f.Namespace.Name, configMap.Name))
		var err error
		if configMap, err = f.ClientSet.CoreV1().ConfigMaps(f.Namespace.Name).Create(configMap); err != nil {
			e2elog.Failf("unable to create test configMap %s: %v", configMap.Name, err)
		}

		pod := &v1.Pod{
			ObjectMeta: metav1.ObjectMeta{
				Name: "pod-configmaps-" + string(uuid.NewUUID()),
			},
			Spec: v1.PodSpec{
				Containers: []v1.Container{
					{
						Name:    "env-test",
						Image:   imageutils.GetE2EImage(imageutils.BusyBox),
						Command: []string{"sh", "-c", "env"},
						Env: []v1.EnvVar{
							{
								Name: "CONFIG_DATA_1",
								ValueFrom: &v1.EnvVarSource{
									ConfigMapKeyRef: &v1.ConfigMapKeySelector{
										LocalObjectReference: v1.LocalObjectReference{
											Name: name,
										},
										Key: "data-1",
									},
								},
							},
						},
					},
				},
				RestartPolicy: v1.RestartPolicyNever,
			},
		}

		f.TestContainerOutput("consume configMaps", pod, 0, []string{
			"CONFIG_DATA_1=value-1",
		})
	})

	/*
		Release: v1.9
		Testname: ConfigMap, from environment variables
		Description: Create a Pod with a environment source from ConfigMap. All ConfigMap values MUST be available as environment variables in the container.
	*/
	framework.ConformanceIt("should be consumable via the environment [NodeConformance]", func() {
		name := "configmap-test-" + string(uuid.NewUUID())
		configMap := newEnvFromConfigMap(f, name)
		ginkgo.By(fmt.Sprintf("Creating configMap %v/%v", f.Namespace.Name, configMap.Name))
		var err error
		if configMap, err = f.ClientSet.CoreV1().ConfigMaps(f.Namespace.Name).Create(configMap); err != nil {
			e2elog.Failf("unable to create test configMap %s: %v", configMap.Name, err)
		}

		pod := &v1.Pod{
			ObjectMeta: metav1.ObjectMeta{
				Name: "pod-configmaps-" + string(uuid.NewUUID()),
			},
			Spec: v1.PodSpec{
				Containers: []v1.Container{
					{
						Name:    "env-test",
						Image:   imageutils.GetE2EImage(imageutils.BusyBox),
						Command: []string{"sh", "-c", "env"},
						EnvFrom: []v1.EnvFromSource{
							{
								ConfigMapRef: &v1.ConfigMapEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: name}},
							},
							{
								Prefix:       "p_",
								ConfigMapRef: &v1.ConfigMapEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: name}},
							},
						},
					},
				},
				RestartPolicy: v1.RestartPolicyNever,
			},
		}

		f.TestContainerOutput("consume configMaps", pod, 0, []string{
			"data_1=value-1", "data_2=value-2", "data_3=value-3",
			"p_data_1=value-1", "p_data_2=value-2", "p_data_3=value-3",
		})
	})

	/*
	   Release : v1.14
	   Testname: ConfigMap, with empty-key
	   Description: Attempt to create a ConfigMap with an empty key. The creation MUST fail.
	*/
	framework.ConformanceIt("should fail to create ConfigMap with empty key", func() {
		configMap, err := newConfigMapWithEmptyKey(f)
		framework.ExpectError(err, "created configMap %q with empty key in namespace %q", configMap.Name, f.Namespace.Name)
	})

	ginkgo.It("should patch ConfigMap successfully", func() {
		name := "configmap-test-" + string(uuid.NewUUID())
		configMap := newConfigMap(f, name)
		configMapOriginalState := *configMap
		ginkgo.By(fmt.Sprintf("Creating configMap %v/%v", f.Namespace.Name, configMap.Name))
		_, err := f.ClientSet.CoreV1().ConfigMaps(f.Namespace.Name).Create(configMap)
		framework.ExpectNoError(err)

		configMap.Data = map[string]string{
			"data": "value",
		}
		ginkgo.By(fmt.Sprintf("Updating configMap %v/%v", f.Namespace.Name, configMap.Name))
		_, err = f.ClientSet.CoreV1().ConfigMaps(f.Namespace.Name).Update(configMap)
		framework.ExpectNoError(err)

		configMapFromUpdate, err := f.ClientSet.CoreV1().ConfigMaps(f.Namespace.Name).Get(name, metav1.GetOptions{})
		framework.ExpectNoError(err)
		ginkgo.By(fmt.Sprintf("Verifying update of configMap %v/%v", f.Namespace.Name, configMap.Name))
		gomega.Expect(configMapFromUpdate.Data).NotTo(gomega.Equal(configMapOriginalState.Data))
	})
})

func newEnvFromConfigMap(f *framework.Framework, name string) *v1.ConfigMap {
	return &v1.ConfigMap{
		ObjectMeta: metav1.ObjectMeta{
			Namespace: f.Namespace.Name,
			Name:      name,
		},
		Data: map[string]string{
			"data_1": "value-1",
			"data_2": "value-2",
			"data_3": "value-3",
		},
	}
}

func newConfigMapWithEmptyKey(f *framework.Framework) (*v1.ConfigMap, error) {
	name := "configmap-test-emptyKey-" + string(uuid.NewUUID())
	configMap := &v1.ConfigMap{
		ObjectMeta: metav1.ObjectMeta{
			Namespace: f.Namespace.Name,
			Name:      name,
		},
		Data: map[string]string{
			"": "value-1",
		},
	}

	ginkgo.By(fmt.Sprintf("Creating configMap that has name %s", configMap.Name))
	return f.ClientSet.CoreV1().ConfigMaps(f.Namespace.Name).Create(configMap)
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2014 The foocsim 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 caches

import (
	"fmt"
	"github.com/jmhodges/levigo"
	"github.com/lpabon/godbc"
	"os"
)

var leveldbvalset []byte
var leveldbunvalset []byte

func init() {
	leveldbvalset = make([]byte, 64)
	leveldbunvalset = make([]byte, 64)
	leveldbvalset[0] = 1
}

type LevelDBCache struct {
	stats        CacheStats
	db           *levigo.DB
	ro           *levigo.ReadOptions
	wo           *levigo.WriteOptions
	bloomf       *levigo.FilterPolicy
	cachesize    uint64
	keyn         uint64
	writethrough bool
}

func NewLevelDBCache(cachesize uint64, writethrough bool) *LevelDBCache {

	var err error

	db := &LevelDBCache{}
	db.writethrough = writethrough
	db.cachesize = cachesize

	os.RemoveAll("cache.leveldb")

	// Set bloom filter
	db.bloomf = levigo.NewBloomFilter(10)

	// Set Options
	opts := levigo.NewOptions()
	//opts.SetCache(levigo.NewLRUCache(3 << 30))
	opts.SetCreateIfMissing(true)
	//opts.SetFilterPolicy(db.bloomf)

	db.db, err = levigo.Open("cache.leveldb", opts)
	godbc.Check(err == nil)

	// Set read and write options
	db.ro = levigo.NewReadOptions()
	db.wo = levigo.NewWriteOptions()

	godbc.Ensure(db.ro != nil)
	godbc.Ensure(db.wo != nil)
	godbc.Ensure(db.cachesize > 0)

	return db
}

func (c *LevelDBCache) Close() {
	c.bloomf.Close()
	c.wo.Close()
	c.ro.Close()
	c.db.Close()
}

func (c *LevelDBCache) Invalidate(key string) {
	if val, _ := c.db.Get(c.ro, []byte(key)); val != nil {
		c.stats.writehits++
		c.stats.invalidations++
		c.keyn--
		c.db.Delete(c.wo, []byte(key))
	}
}

func (c *LevelDBCache) Evict() {
	c.stats.evictions++

	for evicted := false; !evicted; {
		it := c.db.NewIterator(c.ro)
		defer it.Close()

		for it.SeekToFirst(); it.Valid(); it.Next() {
			if it.Value()[0] == 1 {
				c.db.Put(c.wo, it.Key(), leveldbunvalset)
			} else {
				c.db.Delete(c.wo, it.Key())
				c.keyn--
				evicted = true
			}
		}
	}
}

func (c *LevelDBCache) Insert(key string) {
	c.stats.insertions++

	// Check for evictions
	if c.keyn >= c.cachesize {
		c.Evict()
	}

	// Insert new key in cache map
	c.db.Put(c.wo, []byte(key), leveldbvalset)
	c.keyn++
}

func (c *LevelDBCache) Write(obj string, chunk string) {
	c.stats.writes++

	key := obj + chunk

	// Invalidate
	c.Invalidate(key)

	// We would do back end IO here

	// Insert
	if c.writethrough {
		c.Insert(key)
	}
}

func (c *LevelDBCache) Read(obj, chunk string) {
	c.stats.reads++

	key := obj + chunk

	if val, _ := c.db.Get(c.ro, []byte(key)); val != nil {
		// Read Hit
		c.stats.readhits++

		// Clock Algorithm: Set that we looked
		// at it
		c.db.Put(c.wo, []byte(key), leveldbvalset)
	} else {
		// Read miss
		// We would do IO here
		c.Insert(key)
	}
}

func (c *LevelDBCache) Delete(obj string) {
	// Not supported
}

func (c *LevelDBCache) String() string {
	return fmt.Sprintf(
		"== Cache Information ==\n"+
			"Cache Utilization: %.2f %%\n",
		float64(c.keyn)/float64(c.cachesize)*100.0) +
		c.stats.String()
}

func (c *LevelDBCache) Stats() *CacheStats {
	return c.stats.Copy()
}
<commit_msg>Fixed eviction code in LevelDB.<commit_after>//
// Copyright (c) 2014 The foocsim 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 caches

import (
	"fmt"
	"github.com/jmhodges/levigo"
	"github.com/lpabon/godbc"
	"os"
)

var leveldbvalset []byte
var leveldbunvalset []byte

func init() {
	leveldbvalset = make([]byte, 64)
	leveldbunvalset = make([]byte, 64)
	leveldbvalset[0] = 1
}

type LevelDBCache struct {
	stats        CacheStats
	db           *levigo.DB
	ro           *levigo.ReadOptions
	wo           *levigo.WriteOptions
	bloomf       *levigo.FilterPolicy
	cachesize    uint64
	keyn         uint64
	writethrough bool
}

func NewLevelDBCache(cachesize uint64, writethrough bool) *LevelDBCache {

	var err error

	godbc.Require(cachesize > 0)

	db := &LevelDBCache{}
	db.writethrough = writethrough
	db.cachesize = cachesize

	os.RemoveAll("cache.leveldb")

	// Set bloom filter
	db.bloomf = levigo.NewBloomFilter(10)

	// Set Options
	opts := levigo.NewOptions()
	opts.SetCache(levigo.NewLRUCache(3 << 30))
	opts.SetCreateIfMissing(true)
	opts.SetFilterPolicy(db.bloomf)

	db.db, err = levigo.Open("cache.leveldb", opts)
	godbc.Check(err == nil)

	// Set read and write options
	db.ro = levigo.NewReadOptions()
	db.wo = levigo.NewWriteOptions()

	godbc.Ensure(db.ro != nil)
	godbc.Ensure(db.wo != nil)
	godbc.Ensure(db.cachesize > 0)

	return db
}

func (c *LevelDBCache) Close() {
	c.bloomf.Close()
	c.wo.Close()
	c.ro.Close()
	c.db.Close()
}

func (c *LevelDBCache) Invalidate(key string) {
	if val, _ := c.db.Get(c.ro, []byte(key)); val != nil {
		c.stats.writehits++
		c.stats.invalidations++
		c.keyn--
		c.db.Delete(c.wo, []byte(key))
	}
}

func (c *LevelDBCache) Evict() {
	c.stats.evictions++

	for evicted := false; !evicted; {
		it := c.db.NewIterator(c.ro)
		defer it.Close()

		for it.SeekToFirst(); it.Valid(); it.Next() {
			if it.Value()[0] == 1 {
				c.db.Put(c.wo, it.Key(), leveldbunvalset)
			} else {
				c.db.Delete(c.wo, it.Key())
				c.keyn--
				evicted = true
				break
			}
		}
	}
}

func (c *LevelDBCache) Insert(key string) {
	c.stats.insertions++

	// Check for evictions
	if c.keyn >= c.cachesize {
		c.Evict()
	}

	// Insert new key in cache map
	c.db.Put(c.wo, []byte(key), leveldbvalset)
	c.keyn++
}

func (c *LevelDBCache) Write(obj string, chunk string) {
	c.stats.writes++

	key := obj + chunk

	// Invalidate
	c.Invalidate(key)

	// We would do back end IO here

	// Insert
	if c.writethrough {
		c.Insert(key)
	}
}

func (c *LevelDBCache) Read(obj, chunk string) {
	c.stats.reads++

	key := obj + chunk

	if val, _ := c.db.Get(c.ro, []byte(key)); val != nil {
		// Read Hit
		c.stats.readhits++

		// Clock Algorithm: Set that we looked
		// at it
		c.db.Put(c.wo, []byte(key), leveldbvalset)
	} else {
		// Read miss
		// We would do IO here
		c.Insert(key)
	}
}

func (c *LevelDBCache) Delete(obj string) {
	// Not supported
}

func (c *LevelDBCache) String() string {
	return fmt.Sprintf(
		"== Cache Information ==\n"+
			"Cache Utilization: %.2f %%\n",
		float64(c.keyn)/float64(c.cachesize)*100.0) +
		c.stats.String()
}

func (c *LevelDBCache) Stats() *CacheStats {
	return c.stats.Copy()
}
<|endoftext|>


<commit_before>package gorm

import (
	"errors"
	"fmt"
	"reflect"
)

// Define callbacks for querying
func init() {
	DefaultCallback.Query().Register("gorm:query", queryCallback)
	DefaultCallback.Query().Register("gorm:preload", preloadCallback)
	DefaultCallback.Query().Register("gorm:after_query", afterQueryCallback)
}

// queryCallback used to query data from database
func queryCallback(scope *Scope) {
	defer scope.trace(NowFunc())

	var (
		isSlice, isPtr bool
		resultType     reflect.Type
		results        = scope.IndirectValue()
	)

	if orderBy, ok := scope.Get("gorm:order_by_primary_key"); ok {
		if primaryField := scope.PrimaryField(); primaryField != nil {
			scope.Search.Order(fmt.Sprintf("%v.%v %v", scope.QuotedTableName(), scope.Quote(primaryField.DBName), orderBy))
		}
	}

	if value, ok := scope.Get("gorm:query_destination"); ok {
		results = indirect(reflect.ValueOf(value))
	}

	if kind := results.Kind(); kind == reflect.Slice {
		isSlice = true
		resultType = results.Type().Elem()
		results.Set(reflect.MakeSlice(results.Type(), 0, 0))

		if resultType.Kind() == reflect.Ptr {
			isPtr = true
			resultType = resultType.Elem()
		}
	} else if kind != reflect.Struct {
		scope.Err(errors.New("unsupported destination, should be slice or struct"))
		return
	}

	scope.prepareQuerySQL()

	if !scope.HasError() {
		scope.db.RowsAffected = 0
		if str, ok := scope.Get("gorm:query_option"); ok {
			scope.SQL += addExtraSpaceIfExist(fmt.Sprint(str))
		}

		if rows, err := scope.SQLDB().Query(scope.SQL, scope.SQLVars...); scope.Err(err) == nil {
			defer rows.Close()

			columns, _ := rows.Columns()
			for rows.Next() {
				scope.db.RowsAffected++

				elem := results
				if isSlice {
					elem = reflect.New(resultType).Elem()
				}

				scope.scan(rows, columns, scope.New(elem.Addr().Interface()).Fields())

				if isSlice {
					if isPtr {
						results.Set(reflect.Append(results, elem.Addr()))
					} else {
						results.Set(reflect.Append(results, elem))
					}
				}
			}

			if err := rows.Err(); err != nil {
				scope.Err(err)
			}

			if scope.db.RowsAffected == 0 && !isSlice {
				scope.Err(ErrRecordNotFound)
			}
		}
	}
}

// afterQueryCallback will invoke `AfterFind` method after querying
func afterQueryCallback(scope *Scope) {
	if !scope.HasError() {
		scope.CallMethod("AfterFind")
	}
}
<commit_msg>DB errors over NotFound<commit_after>package gorm

import (
	"errors"
	"fmt"
	"reflect"
)

// Define callbacks for querying
func init() {
	DefaultCallback.Query().Register("gorm:query", queryCallback)
	DefaultCallback.Query().Register("gorm:preload", preloadCallback)
	DefaultCallback.Query().Register("gorm:after_query", afterQueryCallback)
}

// queryCallback used to query data from database
func queryCallback(scope *Scope) {
	defer scope.trace(NowFunc())

	var (
		isSlice, isPtr bool
		resultType     reflect.Type
		results        = scope.IndirectValue()
	)

	if orderBy, ok := scope.Get("gorm:order_by_primary_key"); ok {
		if primaryField := scope.PrimaryField(); primaryField != nil {
			scope.Search.Order(fmt.Sprintf("%v.%v %v", scope.QuotedTableName(), scope.Quote(primaryField.DBName), orderBy))
		}
	}

	if value, ok := scope.Get("gorm:query_destination"); ok {
		results = indirect(reflect.ValueOf(value))
	}

	if kind := results.Kind(); kind == reflect.Slice {
		isSlice = true
		resultType = results.Type().Elem()
		results.Set(reflect.MakeSlice(results.Type(), 0, 0))

		if resultType.Kind() == reflect.Ptr {
			isPtr = true
			resultType = resultType.Elem()
		}
	} else if kind != reflect.Struct {
		scope.Err(errors.New("unsupported destination, should be slice or struct"))
		return
	}

	scope.prepareQuerySQL()

	if !scope.HasError() {
		scope.db.RowsAffected = 0
		if str, ok := scope.Get("gorm:query_option"); ok {
			scope.SQL += addExtraSpaceIfExist(fmt.Sprint(str))
		}

		if rows, err := scope.SQLDB().Query(scope.SQL, scope.SQLVars...); scope.Err(err) == nil {
			defer rows.Close()

			columns, _ := rows.Columns()
			for rows.Next() {
				scope.db.RowsAffected++

				elem := results
				if isSlice {
					elem = reflect.New(resultType).Elem()
				}

				scope.scan(rows, columns, scope.New(elem.Addr().Interface()).Fields())

				if isSlice {
					if isPtr {
						results.Set(reflect.Append(results, elem.Addr()))
					} else {
						results.Set(reflect.Append(results, elem))
					}
				}
			}

			if err := rows.Err(); err != nil {
				scope.Err(err)
			} else if scope.db.RowsAffected == 0 && !isSlice {
				scope.Err(ErrRecordNotFound)
			}
		}
	}
}

// afterQueryCallback will invoke `AfterFind` method after querying
func afterQueryCallback(scope *Scope) {
	if !scope.HasError() {
		scope.CallMethod("AfterFind")
	}
}
<|endoftext|>


<commit_before>package cli

import (
	"fmt"
	"os"
	"strings"

	pluginmanager "github.com/docker/cli/cli-plugins/manager"
	"github.com/docker/cli/cli/command"
	cliconfig "github.com/docker/cli/cli/config"
	cliflags "github.com/docker/cli/cli/flags"
	"github.com/moby/term"
	"github.com/pkg/errors"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
)

// setupCommonRootCommand contains the setup common to
// SetupRootCommand and SetupPluginRootCommand.
func setupCommonRootCommand(rootCmd *cobra.Command) (*cliflags.ClientOptions, *pflag.FlagSet, *cobra.Command) {
	opts := cliflags.NewClientOptions()
	flags := rootCmd.Flags()

	flags.StringVar(&opts.ConfigDir, "config", cliconfig.Dir(), "Location of client config files")
	opts.Common.InstallFlags(flags)

	cobra.AddTemplateFunc("add", func(a, b int) int { return a + b })
	cobra.AddTemplateFunc("hasSubCommands", hasSubCommands)
	cobra.AddTemplateFunc("hasManagementSubCommands", hasManagementSubCommands)
	cobra.AddTemplateFunc("hasInvalidPlugins", hasInvalidPlugins)
	cobra.AddTemplateFunc("operationSubCommands", operationSubCommands)
	cobra.AddTemplateFunc("managementSubCommands", managementSubCommands)
	cobra.AddTemplateFunc("invalidPlugins", invalidPlugins)
	cobra.AddTemplateFunc("wrappedFlagUsages", wrappedFlagUsages)
	cobra.AddTemplateFunc("vendorAndVersion", vendorAndVersion)
	cobra.AddTemplateFunc("invalidPluginReason", invalidPluginReason)
	cobra.AddTemplateFunc("isPlugin", isPlugin)
	cobra.AddTemplateFunc("decoratedName", decoratedName)

	rootCmd.SetUsageTemplate(usageTemplate)
	rootCmd.SetHelpTemplate(helpTemplate)
	rootCmd.SetFlagErrorFunc(FlagErrorFunc)
	rootCmd.SetHelpCommand(helpCommand)

	rootCmd.PersistentFlags().BoolP("help", "h", false, "Print usage")
	rootCmd.PersistentFlags().MarkShorthandDeprecated("help", "please use --help")
	rootCmd.PersistentFlags().Lookup("help").Hidden = true

	return opts, flags, helpCommand
}

// SetupRootCommand sets default usage, help, and error handling for the
// root command.
func SetupRootCommand(rootCmd *cobra.Command) (*cliflags.ClientOptions, *pflag.FlagSet, *cobra.Command) {
	opts, flags, helpCmd := setupCommonRootCommand(rootCmd)

	rootCmd.SetVersionTemplate("Docker version {{.Version}}\n")

	return opts, flags, helpCmd
}

// SetupPluginRootCommand sets default usage, help and error handling for a plugin root command.
func SetupPluginRootCommand(rootCmd *cobra.Command) (*cliflags.ClientOptions, *pflag.FlagSet) {
	opts, flags, _ := setupCommonRootCommand(rootCmd)
	return opts, flags
}

// FlagErrorFunc prints an error message which matches the format of the
// docker/cli/cli error messages
func FlagErrorFunc(cmd *cobra.Command, err error) error {
	if err == nil {
		return nil
	}

	usage := ""
	if cmd.HasSubCommands() {
		usage = "\n\n" + cmd.UsageString()
	}
	return StatusError{
		Status:     fmt.Sprintf("%s\nSee '%s --help'.%s", err, cmd.CommandPath(), usage),
		StatusCode: 125,
	}
}

// TopLevelCommand encapsulates a top-level cobra command (either
// docker CLI or a plugin) and global flag handling logic necessary
// for plugins.
type TopLevelCommand struct {
	cmd       *cobra.Command
	dockerCli *command.DockerCli
	opts      *cliflags.ClientOptions
	flags     *pflag.FlagSet
	args      []string
}

// NewTopLevelCommand returns a new TopLevelCommand object
func NewTopLevelCommand(cmd *cobra.Command, dockerCli *command.DockerCli, opts *cliflags.ClientOptions, flags *pflag.FlagSet) *TopLevelCommand {
	return &TopLevelCommand{cmd, dockerCli, opts, flags, os.Args[1:]}
}

// SetArgs sets the args (default os.Args[:1] used to invoke the command
func (tcmd *TopLevelCommand) SetArgs(args []string) {
	tcmd.args = args
	tcmd.cmd.SetArgs(args)
}

// SetFlag sets a flag in the local flag set of the top-level command
func (tcmd *TopLevelCommand) SetFlag(name, value string) {
	tcmd.cmd.Flags().Set(name, value)
}

// HandleGlobalFlags takes care of parsing global flags defined on the
// command, it returns the underlying cobra command and the args it
// will be called with (or an error).
//
// On success the caller is responsible for calling Initialize()
// before calling `Execute` on the returned command.
func (tcmd *TopLevelCommand) HandleGlobalFlags() (*cobra.Command, []string, error) {
	cmd := tcmd.cmd

	// We manually parse the global arguments and find the
	// subcommand in order to properly deal with plugins. We rely
	// on the root command never having any non-flag arguments. We
	// create our own FlagSet so that we can configure it
	// (e.g. `SetInterspersed` below) in an idempotent way.
	flags := pflag.NewFlagSet(cmd.Name(), pflag.ContinueOnError)

	// We need !interspersed to ensure we stop at the first
	// potential command instead of accumulating it into
	// flags.Args() and then continuing on and finding other
	// arguments which we try and treat as globals (when they are
	// actually arguments to the subcommand).
	flags.SetInterspersed(false)

	// We need the single parse to see both sets of flags.
	flags.AddFlagSet(cmd.Flags())
	flags.AddFlagSet(cmd.PersistentFlags())
	// Now parse the global flags, up to (but not including) the
	// first command. The result will be that all the remaining
	// arguments are in `flags.Args()`.
	if err := flags.Parse(tcmd.args); err != nil {
		// Our FlagErrorFunc uses the cli, make sure it is initialized
		if err := tcmd.Initialize(); err != nil {
			return nil, nil, err
		}
		return nil, nil, cmd.FlagErrorFunc()(cmd, err)
	}

	return cmd, flags.Args(), nil
}

// Initialize finalises global option parsing and initializes the docker client.
func (tcmd *TopLevelCommand) Initialize(ops ...command.InitializeOpt) error {
	tcmd.opts.Common.SetDefaultOptions(tcmd.flags)
	return tcmd.dockerCli.Initialize(tcmd.opts, ops...)
}

// VisitAll will traverse all commands from the root.
// This is different from the VisitAll of cobra.Command where only parents
// are checked.
func VisitAll(root *cobra.Command, fn func(*cobra.Command)) {
	for _, cmd := range root.Commands() {
		VisitAll(cmd, fn)
	}
	fn(root)
}

// DisableFlagsInUseLine sets the DisableFlagsInUseLine flag on all
// commands within the tree rooted at cmd.
func DisableFlagsInUseLine(cmd *cobra.Command) {
	VisitAll(cmd, func(ccmd *cobra.Command) {
		// do not add a `[flags]` to the end of the usage line.
		ccmd.DisableFlagsInUseLine = true
	})
}

var helpCommand = &cobra.Command{
	Use:               "help [command]",
	Short:             "Help about the command",
	PersistentPreRun:  func(cmd *cobra.Command, args []string) {},
	PersistentPostRun: func(cmd *cobra.Command, args []string) {},
	RunE: func(c *cobra.Command, args []string) error {
		cmd, args, e := c.Root().Find(args)
		if cmd == nil || e != nil || len(args) > 0 {
			return errors.Errorf("unknown help topic: %v", strings.Join(args, " "))
		}

		helpFunc := cmd.HelpFunc()
		helpFunc(cmd, args)
		return nil
	},
}

func isPlugin(cmd *cobra.Command) bool {
	return cmd.Annotations[pluginmanager.CommandAnnotationPlugin] == "true"
}

func hasSubCommands(cmd *cobra.Command) bool {
	return len(operationSubCommands(cmd)) > 0
}

func hasManagementSubCommands(cmd *cobra.Command) bool {
	return len(managementSubCommands(cmd)) > 0
}

func hasInvalidPlugins(cmd *cobra.Command) bool {
	return len(invalidPlugins(cmd)) > 0
}

func operationSubCommands(cmd *cobra.Command) []*cobra.Command {
	cmds := []*cobra.Command{}
	for _, sub := range cmd.Commands() {
		if isPlugin(sub) {
			continue
		}
		if sub.IsAvailableCommand() && !sub.HasSubCommands() {
			cmds = append(cmds, sub)
		}
	}
	return cmds
}

func wrappedFlagUsages(cmd *cobra.Command) string {
	width := 80
	if ws, err := term.GetWinsize(0); err == nil {
		width = int(ws.Width)
	}
	return cmd.Flags().FlagUsagesWrapped(width - 1)
}

func decoratedName(cmd *cobra.Command) string {
	decoration := " "
	if isPlugin(cmd) {
		decoration = "*"
	}
	return cmd.Name() + decoration
}

func vendorAndVersion(cmd *cobra.Command) string {
	if vendor, ok := cmd.Annotations[pluginmanager.CommandAnnotationPluginVendor]; ok && isPlugin(cmd) {
		version := ""
		if v, ok := cmd.Annotations[pluginmanager.CommandAnnotationPluginVersion]; ok && v != "" {
			version = ", " + v
		}
		return fmt.Sprintf("(%s%s)", vendor, version)
	}
	return ""
}

func managementSubCommands(cmd *cobra.Command) []*cobra.Command {
	cmds := []*cobra.Command{}
	for _, sub := range cmd.Commands() {
		if isPlugin(sub) {
			if invalidPluginReason(sub) == "" {
				cmds = append(cmds, sub)
			}
			continue
		}
		if sub.IsAvailableCommand() && sub.HasSubCommands() {
			cmds = append(cmds, sub)
		}
	}
	return cmds
}

func invalidPlugins(cmd *cobra.Command) []*cobra.Command {
	cmds := []*cobra.Command{}
	for _, sub := range cmd.Commands() {
		if !isPlugin(sub) {
			continue
		}
		if invalidPluginReason(sub) != "" {
			cmds = append(cmds, sub)
		}
	}
	return cmds
}

func invalidPluginReason(cmd *cobra.Command) string {
	return cmd.Annotations[pluginmanager.CommandAnnotationPluginInvalid]
}

var usageTemplate = `Usage:

{{- if not .HasSubCommands}}	{{.UseLine}}{{end}}
{{- if .HasSubCommands}}	{{ .CommandPath}}{{- if .HasAvailableFlags}} [OPTIONS]{{end}} COMMAND{{end}}

{{if ne .Long ""}}{{ .Long | trim }}{{ else }}{{ .Short | trim }}{{end}}

{{- if gt .Aliases 0}}

Aliases:
  {{.NameAndAliases}}

{{- end}}
{{- if .HasExample}}

Examples:
{{ .Example }}

{{- end}}
{{- if .HasAvailableFlags}}

Options:
{{ wrappedFlagUsages . | trimRightSpace}}

{{- end}}
{{- if hasManagementSubCommands . }}

Management Commands:

{{- range managementSubCommands . }}
  {{rpad (decoratedName .) (add .NamePadding 1)}}{{.Short}}{{ if isPlugin .}} {{vendorAndVersion .}}{{ end}}
{{- end}}

{{- end}}
{{- if hasSubCommands .}}

Commands:

{{- range operationSubCommands . }}
  {{rpad .Name .NamePadding }} {{.Short}}
{{- end}}
{{- end}}

{{- if hasInvalidPlugins . }}

Invalid Plugins:

{{- range invalidPlugins . }}
  {{rpad .Name .NamePadding }} {{invalidPluginReason .}}
{{- end}}

{{- end}}

{{- if .HasSubCommands }}

Run '{{.CommandPath}} COMMAND --help' for more information on a command.
{{- end}}
`

var helpTemplate = `
{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`
<commit_msg>cli: print experimental message in usage output<commit_after>package cli

import (
	"fmt"
	"os"
	"strings"

	pluginmanager "github.com/docker/cli/cli-plugins/manager"
	"github.com/docker/cli/cli/command"
	cliconfig "github.com/docker/cli/cli/config"
	cliflags "github.com/docker/cli/cli/flags"
	"github.com/moby/term"
	"github.com/pkg/errors"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
)

// setupCommonRootCommand contains the setup common to
// SetupRootCommand and SetupPluginRootCommand.
func setupCommonRootCommand(rootCmd *cobra.Command) (*cliflags.ClientOptions, *pflag.FlagSet, *cobra.Command) {
	opts := cliflags.NewClientOptions()
	flags := rootCmd.Flags()

	flags.StringVar(&opts.ConfigDir, "config", cliconfig.Dir(), "Location of client config files")
	opts.Common.InstallFlags(flags)

	cobra.AddTemplateFunc("add", func(a, b int) int { return a + b })
	cobra.AddTemplateFunc("hasSubCommands", hasSubCommands)
	cobra.AddTemplateFunc("hasManagementSubCommands", hasManagementSubCommands)
	cobra.AddTemplateFunc("hasInvalidPlugins", hasInvalidPlugins)
	cobra.AddTemplateFunc("operationSubCommands", operationSubCommands)
	cobra.AddTemplateFunc("managementSubCommands", managementSubCommands)
	cobra.AddTemplateFunc("invalidPlugins", invalidPlugins)
	cobra.AddTemplateFunc("wrappedFlagUsages", wrappedFlagUsages)
	cobra.AddTemplateFunc("vendorAndVersion", vendorAndVersion)
	cobra.AddTemplateFunc("invalidPluginReason", invalidPluginReason)
	cobra.AddTemplateFunc("isPlugin", isPlugin)
	cobra.AddTemplateFunc("isExperimental", isExperimental)
	cobra.AddTemplateFunc("decoratedName", decoratedName)

	rootCmd.SetUsageTemplate(usageTemplate)
	rootCmd.SetHelpTemplate(helpTemplate)
	rootCmd.SetFlagErrorFunc(FlagErrorFunc)
	rootCmd.SetHelpCommand(helpCommand)

	rootCmd.PersistentFlags().BoolP("help", "h", false, "Print usage")
	rootCmd.PersistentFlags().MarkShorthandDeprecated("help", "please use --help")
	rootCmd.PersistentFlags().Lookup("help").Hidden = true

	return opts, flags, helpCommand
}

// SetupRootCommand sets default usage, help, and error handling for the
// root command.
func SetupRootCommand(rootCmd *cobra.Command) (*cliflags.ClientOptions, *pflag.FlagSet, *cobra.Command) {
	opts, flags, helpCmd := setupCommonRootCommand(rootCmd)

	rootCmd.SetVersionTemplate("Docker version {{.Version}}\n")

	return opts, flags, helpCmd
}

// SetupPluginRootCommand sets default usage, help and error handling for a plugin root command.
func SetupPluginRootCommand(rootCmd *cobra.Command) (*cliflags.ClientOptions, *pflag.FlagSet) {
	opts, flags, _ := setupCommonRootCommand(rootCmd)
	return opts, flags
}

// FlagErrorFunc prints an error message which matches the format of the
// docker/cli/cli error messages
func FlagErrorFunc(cmd *cobra.Command, err error) error {
	if err == nil {
		return nil
	}

	usage := ""
	if cmd.HasSubCommands() {
		usage = "\n\n" + cmd.UsageString()
	}
	return StatusError{
		Status:     fmt.Sprintf("%s\nSee '%s --help'.%s", err, cmd.CommandPath(), usage),
		StatusCode: 125,
	}
}

// TopLevelCommand encapsulates a top-level cobra command (either
// docker CLI or a plugin) and global flag handling logic necessary
// for plugins.
type TopLevelCommand struct {
	cmd       *cobra.Command
	dockerCli *command.DockerCli
	opts      *cliflags.ClientOptions
	flags     *pflag.FlagSet
	args      []string
}

// NewTopLevelCommand returns a new TopLevelCommand object
func NewTopLevelCommand(cmd *cobra.Command, dockerCli *command.DockerCli, opts *cliflags.ClientOptions, flags *pflag.FlagSet) *TopLevelCommand {
	return &TopLevelCommand{cmd, dockerCli, opts, flags, os.Args[1:]}
}

// SetArgs sets the args (default os.Args[:1] used to invoke the command
func (tcmd *TopLevelCommand) SetArgs(args []string) {
	tcmd.args = args
	tcmd.cmd.SetArgs(args)
}

// SetFlag sets a flag in the local flag set of the top-level command
func (tcmd *TopLevelCommand) SetFlag(name, value string) {
	tcmd.cmd.Flags().Set(name, value)
}

// HandleGlobalFlags takes care of parsing global flags defined on the
// command, it returns the underlying cobra command and the args it
// will be called with (or an error).
//
// On success the caller is responsible for calling Initialize()
// before calling `Execute` on the returned command.
func (tcmd *TopLevelCommand) HandleGlobalFlags() (*cobra.Command, []string, error) {
	cmd := tcmd.cmd

	// We manually parse the global arguments and find the
	// subcommand in order to properly deal with plugins. We rely
	// on the root command never having any non-flag arguments. We
	// create our own FlagSet so that we can configure it
	// (e.g. `SetInterspersed` below) in an idempotent way.
	flags := pflag.NewFlagSet(cmd.Name(), pflag.ContinueOnError)

	// We need !interspersed to ensure we stop at the first
	// potential command instead of accumulating it into
	// flags.Args() and then continuing on and finding other
	// arguments which we try and treat as globals (when they are
	// actually arguments to the subcommand).
	flags.SetInterspersed(false)

	// We need the single parse to see both sets of flags.
	flags.AddFlagSet(cmd.Flags())
	flags.AddFlagSet(cmd.PersistentFlags())
	// Now parse the global flags, up to (but not including) the
	// first command. The result will be that all the remaining
	// arguments are in `flags.Args()`.
	if err := flags.Parse(tcmd.args); err != nil {
		// Our FlagErrorFunc uses the cli, make sure it is initialized
		if err := tcmd.Initialize(); err != nil {
			return nil, nil, err
		}
		return nil, nil, cmd.FlagErrorFunc()(cmd, err)
	}

	return cmd, flags.Args(), nil
}

// Initialize finalises global option parsing and initializes the docker client.
func (tcmd *TopLevelCommand) Initialize(ops ...command.InitializeOpt) error {
	tcmd.opts.Common.SetDefaultOptions(tcmd.flags)
	return tcmd.dockerCli.Initialize(tcmd.opts, ops...)
}

// VisitAll will traverse all commands from the root.
// This is different from the VisitAll of cobra.Command where only parents
// are checked.
func VisitAll(root *cobra.Command, fn func(*cobra.Command)) {
	for _, cmd := range root.Commands() {
		VisitAll(cmd, fn)
	}
	fn(root)
}

// DisableFlagsInUseLine sets the DisableFlagsInUseLine flag on all
// commands within the tree rooted at cmd.
func DisableFlagsInUseLine(cmd *cobra.Command) {
	VisitAll(cmd, func(ccmd *cobra.Command) {
		// do not add a `[flags]` to the end of the usage line.
		ccmd.DisableFlagsInUseLine = true
	})
}

var helpCommand = &cobra.Command{
	Use:               "help [command]",
	Short:             "Help about the command",
	PersistentPreRun:  func(cmd *cobra.Command, args []string) {},
	PersistentPostRun: func(cmd *cobra.Command, args []string) {},
	RunE: func(c *cobra.Command, args []string) error {
		cmd, args, e := c.Root().Find(args)
		if cmd == nil || e != nil || len(args) > 0 {
			return errors.Errorf("unknown help topic: %v", strings.Join(args, " "))
		}

		helpFunc := cmd.HelpFunc()
		helpFunc(cmd, args)
		return nil
	},
}

func isExperimental(cmd *cobra.Command) bool {
	if _, ok := cmd.Annotations["experimentalCLI"]; ok {
		return true
	}
	var experimental bool
	cmd.VisitParents(func(cmd *cobra.Command) {
		if _, ok := cmd.Annotations["experimentalCLI"]; ok {
			experimental = true
		}
	})
	return experimental
}

func isPlugin(cmd *cobra.Command) bool {
	return cmd.Annotations[pluginmanager.CommandAnnotationPlugin] == "true"
}

func hasSubCommands(cmd *cobra.Command) bool {
	return len(operationSubCommands(cmd)) > 0
}

func hasManagementSubCommands(cmd *cobra.Command) bool {
	return len(managementSubCommands(cmd)) > 0
}

func hasInvalidPlugins(cmd *cobra.Command) bool {
	return len(invalidPlugins(cmd)) > 0
}

func operationSubCommands(cmd *cobra.Command) []*cobra.Command {
	cmds := []*cobra.Command{}
	for _, sub := range cmd.Commands() {
		if isPlugin(sub) {
			continue
		}
		if sub.IsAvailableCommand() && !sub.HasSubCommands() {
			cmds = append(cmds, sub)
		}
	}
	return cmds
}

func wrappedFlagUsages(cmd *cobra.Command) string {
	width := 80
	if ws, err := term.GetWinsize(0); err == nil {
		width = int(ws.Width)
	}
	return cmd.Flags().FlagUsagesWrapped(width - 1)
}

func decoratedName(cmd *cobra.Command) string {
	decoration := " "
	if isPlugin(cmd) {
		decoration = "*"
	}
	return cmd.Name() + decoration
}

func vendorAndVersion(cmd *cobra.Command) string {
	if vendor, ok := cmd.Annotations[pluginmanager.CommandAnnotationPluginVendor]; ok && isPlugin(cmd) {
		version := ""
		if v, ok := cmd.Annotations[pluginmanager.CommandAnnotationPluginVersion]; ok && v != "" {
			version = ", " + v
		}
		return fmt.Sprintf("(%s%s)", vendor, version)
	}
	return ""
}

func managementSubCommands(cmd *cobra.Command) []*cobra.Command {
	cmds := []*cobra.Command{}
	for _, sub := range cmd.Commands() {
		if isPlugin(sub) {
			if invalidPluginReason(sub) == "" {
				cmds = append(cmds, sub)
			}
			continue
		}
		if sub.IsAvailableCommand() && sub.HasSubCommands() {
			cmds = append(cmds, sub)
		}
	}
	return cmds
}

func invalidPlugins(cmd *cobra.Command) []*cobra.Command {
	cmds := []*cobra.Command{}
	for _, sub := range cmd.Commands() {
		if !isPlugin(sub) {
			continue
		}
		if invalidPluginReason(sub) != "" {
			cmds = append(cmds, sub)
		}
	}
	return cmds
}

func invalidPluginReason(cmd *cobra.Command) string {
	return cmd.Annotations[pluginmanager.CommandAnnotationPluginInvalid]
}

var usageTemplate = `Usage:

{{- if not .HasSubCommands}}	{{.UseLine}}{{end}}
{{- if .HasSubCommands}}	{{ .CommandPath}}{{- if .HasAvailableFlags}} [OPTIONS]{{end}} COMMAND{{end}}

{{if ne .Long ""}}{{ .Long | trim }}{{ else }}{{ .Short | trim }}{{end}}
{{- if isExperimental .}}

EXPERIMENTAL:
  {{.CommandPath}} is an experimental feature.
  Experimental features provide early access to product functionality. These
  features may change between releases without warning, or can be removed from a
  future release. Learn more about experimental features in our documentation:
  https://docs.docker.com/go/experimental/

{{- end}}
{{- if gt .Aliases 0}}

Aliases:
  {{.NameAndAliases}}

{{- end}}
{{- if .HasExample}}

Examples:
{{ .Example }}

{{- end}}
{{- if .HasAvailableFlags}}

Options:
{{ wrappedFlagUsages . | trimRightSpace}}

{{- end}}
{{- if hasManagementSubCommands . }}

Management Commands:

{{- range managementSubCommands . }}
  {{rpad (decoratedName .) (add .NamePadding 1)}}{{.Short}}{{ if isPlugin .}} {{vendorAndVersion .}}{{ end}}
{{- end}}

{{- end}}
{{- if hasSubCommands .}}

Commands:

{{- range operationSubCommands . }}
  {{rpad .Name .NamePadding }} {{.Short}}
{{- end}}
{{- end}}

{{- if hasInvalidPlugins . }}

Invalid Plugins:

{{- range invalidPlugins . }}
  {{rpad .Name .NamePadding }} {{invalidPluginReason .}}
{{- end}}

{{- end}}

{{- if .HasSubCommands }}

Run '{{.CommandPath}} COMMAND --help' for more information on a command.
{{- end}}
`

var helpTemplate = `
{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`
<|endoftext|>


<commit_before><commit_msg>Pass nil filters to avoid allocation<commit_after><|endoftext|>