<commit_before>package orcraft

import (
	"encoding/json"
	"fmt"
	"net"
	"os"
	"strings"
	"time"

	"github.com/openark/golib/log"

	"github.com/hashicorp/raft"
)

const (
	retainSnapshotCount = 2
	raftTimeout         = 10 * time.Second
)

type Store struct {
	raftDir  string
	raftBind string

	raft *raft.Raft // The consensus mechanism

	applier CommandApplier
}

type storeCommand struct {
	Op    string `json:"op,omitempty"`
	Value []byte `json:"value,omitempty"`
}

// NewStore inits and returns a new store
func NewStore(raftDir string, raftBind string, applier CommandApplier) *Store {
	return &Store{
		raftDir:  raftDir,
		raftBind: raftBind,
		applier:  applier,
	}
}

// Open opens the store. If enableSingle is set, and there are no existing peers,
// then this node becomes the first node, and therefore leader, of the cluster.
func (store *Store) Open(peerNodes []string) error {
	// Setup Raft configuration.
	config := raft.DefaultConfig()
	config.SnapshotThreshold = 1
	config.SnapshotInterval = time.Minute

	// Setup Raft communication.
	addr, err := net.ResolveTCPAddr("tcp", store.raftBind)
	if err != nil {
		return err
	}
	log.Debugf("raft: addr=%+v", addr)
	transport, err := raft.NewTCPTransport(store.raftBind, addr, 3, 10*time.Second, os.Stderr)
	if err != nil {
		return err
	}
	log.Debugf("raft: transport=%+v", transport)

	peers := make([]string, 0, 10)
	for _, peerNode := range peerNodes {
		peerNode = strings.TrimSpace(peerNode)
		peers = raft.AddUniquePeer(peers, peerNode)
	}
	log.Debugf("raft: peers=%+v", peers)

	// Create peer storage.
	peerStore := &raft.StaticPeers{}
	if err := peerStore.SetPeers(peers); err != nil {
		return err
	}

	// Allow the node to enter single-mode, potentially electing itself, if
	// explicitly enabled and there is only 1 node in the cluster already.
	if len(peerNodes) == 0 && len(peers) <= 1 {
		log.Infof("enabling single-node mode")
		config.EnableSingleNode = true
		config.DisableBootstrapAfterElect = false
	}

	// Create the snapshot store. This allows the Raft to truncate the log.
	snapshots, err := raft.NewFileSnapshotStore(store.raftDir, retainSnapshotCount, os.Stderr)
	if err != nil {
		return log.Errorf("file snapshot store: %s", err)
	}

	// Create the log store and stable store.
	logStore := NewRelationalStore()
	log.Debugf("raft: logStore=%+v", logStore)

	// Instantiate the Raft systems.
	if store.raft, err = raft.NewRaft(config, (*fsm)(store), logStore, logStore, snapshots, peerStore, transport); err != nil {
		return fmt.Errorf("error creating new raft: %s", err)
	}
	log.Infof("new raft created")

	return nil
}

// Join joins a node, located at addr, to this store. The node must be ready to
// respond to Raft communications at that address.
func (store *Store) Join(addr string) error {
	log.Infof("received join request for remote node as %s", addr)

	f := store.raft.AddPeer(addr)
	if f.Error() != nil {
		return f.Error()
	}
	log.Infof("node at %s joined successfully", addr)
	return nil
}

// genericCommand requests consensus for applying a single command.
// This is an internal orchestrator implementation
func (store *Store) genericCommand(op string, b []byte) error {
	if store.raft.State() != raft.Leader {
		return fmt.Errorf("not leader")
	}

	b, err := json.Marshal(&storeCommand{Op: op, Value: b})
	if err != nil {
		return err
	}

	f := store.raft.Apply(b, raftTimeout)
	if err = f.Error(); err != nil {
		return err
	}
	r := f.Response()
	log.Debugf("=====response: %+v", r)
	return nil
}
<commit_msg>not checking response<commit_after>package orcraft

import (
	"encoding/json"
	"fmt"
	"net"
	"os"
	"strings"
	"time"

	"github.com/openark/golib/log"

	"github.com/hashicorp/raft"
)

const (
	retainSnapshotCount = 2
	raftTimeout         = 10 * time.Second
)

type Store struct {
	raftDir  string
	raftBind string

	raft *raft.Raft // The consensus mechanism

	applier CommandApplier
}

type storeCommand struct {
	Op    string `json:"op,omitempty"`
	Value []byte `json:"value,omitempty"`
}

// NewStore inits and returns a new store
func NewStore(raftDir string, raftBind string, applier CommandApplier) *Store {
	return &Store{
		raftDir:  raftDir,
		raftBind: raftBind,
		applier:  applier,
	}
}

// Open opens the store. If enableSingle is set, and there are no existing peers,
// then this node becomes the first node, and therefore leader, of the cluster.
func (store *Store) Open(peerNodes []string) error {
	// Setup Raft configuration.
	config := raft.DefaultConfig()
	config.SnapshotThreshold = 1
	config.SnapshotInterval = time.Minute

	// Setup Raft communication.
	addr, err := net.ResolveTCPAddr("tcp", store.raftBind)
	if err != nil {
		return err
	}
	log.Debugf("raft: addr=%+v", addr)
	transport, err := raft.NewTCPTransport(store.raftBind, addr, 3, 10*time.Second, os.Stderr)
	if err != nil {
		return err
	}
	log.Debugf("raft: transport=%+v", transport)

	peers := make([]string, 0, 10)
	for _, peerNode := range peerNodes {
		peerNode = strings.TrimSpace(peerNode)
		peers = raft.AddUniquePeer(peers, peerNode)
	}
	log.Debugf("raft: peers=%+v", peers)

	// Create peer storage.
	peerStore := &raft.StaticPeers{}
	if err := peerStore.SetPeers(peers); err != nil {
		return err
	}

	// Allow the node to enter single-mode, potentially electing itself, if
	// explicitly enabled and there is only 1 node in the cluster already.
	if len(peerNodes) == 0 && len(peers) <= 1 {
		log.Infof("enabling single-node mode")
		config.EnableSingleNode = true
		config.DisableBootstrapAfterElect = false
	}

	// Create the snapshot store. This allows the Raft to truncate the log.
	snapshots, err := raft.NewFileSnapshotStore(store.raftDir, retainSnapshotCount, os.Stderr)
	if err != nil {
		return log.Errorf("file snapshot store: %s", err)
	}

	// Create the log store and stable store.
	logStore := NewRelationalStore()
	log.Debugf("raft: logStore=%+v", logStore)

	// Instantiate the Raft systems.
	if store.raft, err = raft.NewRaft(config, (*fsm)(store), logStore, logStore, snapshots, peerStore, transport); err != nil {
		return fmt.Errorf("error creating new raft: %s", err)
	}
	log.Infof("new raft created")

	return nil
}

// Join joins a node, located at addr, to this store. The node must be ready to
// respond to Raft communications at that address.
func (store *Store) Join(addr string) error {
	log.Infof("received join request for remote node as %s", addr)

	f := store.raft.AddPeer(addr)
	if f.Error() != nil {
		return f.Error()
	}
	log.Infof("node at %s joined successfully", addr)
	return nil
}

// genericCommand requests consensus for applying a single command.
// This is an internal orchestrator implementation
func (store *Store) genericCommand(op string, b []byte) error {
	if store.raft.State() != raft.Leader {
		return fmt.Errorf("not leader")
	}

	b, err := json.Marshal(&storeCommand{Op: op, Value: b})
	if err != nil {
		return err
	}

	f := store.raft.Apply(b, raftTimeout)
	if err = f.Error(); err != nil {
		return err
	}
	// optionally read response here, e.g.:
	// r := f.Response()
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2010  The "goheader" Authors
//
// Use of this source code is governed by the Simplified BSD License
// that can be found in the LICENSE file.
//
// This software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
// OR CONDITIONS OF ANY KIND, either express or implied. See the License
// for more details.

package main

import (
	"bufio"
	//"bytes"
	"flag"
	"fmt"
	"os"
	"path"
	"regexp"
	"strings"
)

const C_LINE_COMMENT = "//!!! "

var header = `// {cmd}
// MACHINE GENERATED BY THE ABOVE COMMAND

package {pkg}
`

var (
	fOS      = flag.String("s", "", "The operating system")
	fPackage = flag.String("p", "", "The name of the package")
	fListOS  = flag.Bool("ls", false, "List of valid systems")
)

func usage() {
	fmt.Fprintf(os.Stderr, "Usage: goheader -s system -g package [defs.h...]\n")
	flag.PrintDefaults()
	os.Exit(1)
}

func turn(fname string) os.Error {
	reSkipLine := regexp.MustCompile(`^#(ifndef|endif|include|define)[ \t\n]`)
	reDefine := regexp.MustCompile(`^(#[ \t]*define)[ \t]+([^ \t]+)[ \t]+(.+)`)
	reMacroInDefine := regexp.MustCompile(`^.*(\(.*\))`)

	reSingleComment := regexp.MustCompile(`^(.+)?/\*[ \t]*(.+)[ \t]*\*/`)
	reStartMultipleComment := regexp.MustCompile(`^/\*(.+)?`)
	reMiddleMultipleComment := regexp.MustCompile(`^[ \t*]*(.+)`)
	reEndMultipleComment := regexp.MustCompile(`^(.+)?\*/`)

	file, err := os.Open(fname, os.O_RDONLY, 0)
	if err != nil {
		return err
	}
	defer file.Close()

	r := bufio.NewReader(file)

	fmt.Println(header)
	var isMultipleComment, isDefine bool

	for {
		line, err := r.ReadString('\n')
		if err == os.EOF {
			break
		}
		line = strings.TrimSpace(line) + "\n"
		isSingleComment := false

		// === Convert comment of single line.
		if !isMultipleComment {
			if fields := reSingleComment.FindStringSubmatch(line); fields != nil {
				isSingleComment = true
				line = "// " + fields[2] + "\n"

				if fields[1] != "" {
					line = fields[1] + line
				}
			}
		}

		if !isSingleComment && !isMultipleComment && strings.HasPrefix(line, "/*") {
			isMultipleComment = true
		}

		// === Convert comments of multiple line.
		if isMultipleComment {
			if fields := reStartMultipleComment.FindStringSubmatch(line); fields != nil {
				if fields[1] != "\n" {
					line = "// " + fields[1]
					fmt.Print(line)
				}
				continue
			}

			if fields := reEndMultipleComment.FindStringSubmatch(line); fields != nil {
				if fields[1] != "" {
					line = "// " + fields[1] + "\n"
					fmt.Print(line)
				}
				isMultipleComment = false
				continue
			}

			if fields := reMiddleMultipleComment.FindStringSubmatch(line); fields != nil {
				line = "// " + fields[1]
				fmt.Print(line)
				continue
			}
		}

		// === Turn defines.
		if fields := reDefine.FindStringSubmatch(line); fields != nil {
			if !isDefine {
				isDefine = true
				fmt.Print("const (\n")
			}
			line = fmt.Sprintf("%s = %s", fields[2], fields[3])

			// Removes comment (if any) to ckeck if it is a macro.
			lastField := strings.Split(fields[3], "//", -1)[0]
			if reMacroInDefine.MatchString(lastField) {
				line = C_LINE_COMMENT + line
			}

			fmt.Print(line)
			continue
		}

		if isDefine && line == "\n" {
			fmt.Print(")\n\n")
			isDefine = false
			continue
		}

		// === Comment another lines.
		if reSkipLine.MatchString(line) {
			line = C_LINE_COMMENT + line
			fmt.Print(line)
			continue
		}

		fmt.Print(line)
	}

	return nil
}

func main() {
	var isValidOS bool
	validOS := []string{"darwin", "freebsd", "linux", "windows"}

	// === Parse the flags
	flag.Usage = usage
	flag.Parse()

	if *fListOS {
		fmt.Print("  = Systems\n\n  ")
		fmt.Println(validOS)
		os.Exit(0)
	}

	if len(os.Args) == 1 || *fOS == "" || *fPackage == "" {
		usage()
	}

	*fOS = strings.ToLower(*fOS)

	for _, v := range validOS {
		if v == *fOS {
			isValidOS = true
			break
		}
	}

	if !isValidOS {
		fmt.Fprintf(os.Stderr, "ERROR: System passed in flag 's' is invalid\n")
		os.Exit(1)
	}

	// === Update header
	cmd := strings.Join(os.Args, " ")
	header = strings.Replace(header, "{cmd}", path.Base(cmd), 1)
	header = strings.Replace(header, "{pkg}", *fPackage, 1)

var File = "/usr/include/asm-generic/ioctls.h"
	if err := turn(File); err != nil {
		fmt.Fprintf(os.Stderr, err.String())
		os.Exit(1)
	}
}

<commit_msg>Add more C lines to comment.<commit_after>// Copyright 2010  The "goheader" Authors
//
// Use of this source code is governed by the Simplified BSD License
// that can be found in the LICENSE file.
//
// This software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
// OR CONDITIONS OF ANY KIND, either express or implied. See the License
// for more details.

package main

import (
	"bufio"
	//"bytes"
	"flag"
	"fmt"
	"os"
	"path"
	"regexp"
	"strings"
)

const C_LINE_COMMENT = "//!!! "

var header = `// {cmd}
// MACHINE GENERATED.

package {pkg}
`

var (
	fOS      = flag.String("s", "", "The operating system")
	fPackage = flag.String("p", "", "The name of the package")
	fListOS  = flag.Bool("ls", false, "List of valid systems")
)

func usage() {
	fmt.Fprintf(os.Stderr, "Usage: goheader -s system -g package [defs.h...]\n")
	flag.PrintDefaults()
	os.Exit(1)
}

func turn(fname string) os.Error {
	reSkipLine := regexp.MustCompile(`^#(ifdef|ifndef|else|undef|endif|include|define)[ \t\n]`)
	reDefine := regexp.MustCompile(`^(#[ \t]*define)[ \t]+([^ \t]+)[ \t]+(.+)`)
	reMacroInDefine := regexp.MustCompile(`^.*(\(.*\))`)

	reSingleComment := regexp.MustCompile(`^(.+)?/\*[ \t]*(.+)[ \t]*\*/`)
	reStartMultipleComment := regexp.MustCompile(`^/\*(.+)?`)
	reMiddleMultipleComment := regexp.MustCompile(`^[ \t*]*(.+)`)
	reEndMultipleComment := regexp.MustCompile(`^(.+)?\*/`)

	file, err := os.Open(fname, os.O_RDONLY, 0)
	if err != nil {
		return err
	}
	defer file.Close()

	r := bufio.NewReader(file)

	fmt.Println(header)
	var isMultipleComment, isDefine bool

	for {
		line, err := r.ReadString('\n')
		if err == os.EOF {
			break
		}
		line = strings.TrimSpace(line) + "\n"
		isSingleComment := false

		// === Convert comment of single line.
		if !isMultipleComment {
			if fields := reSingleComment.FindStringSubmatch(line); fields != nil {
				isSingleComment = true
				line = "// " + fields[2] + "\n"

				if fields[1] != "" {
					line = fields[1] + line
				}
			}
		}

		if !isSingleComment && !isMultipleComment && strings.HasPrefix(line, "/*") {
			isMultipleComment = true
		}

		// === Convert comments of multiple line.
		if isMultipleComment {
			if fields := reStartMultipleComment.FindStringSubmatch(line); fields != nil {
				if fields[1] != "\n" {
					line = "// " + fields[1]
					fmt.Print(line)
				}
				continue
			}

			if fields := reEndMultipleComment.FindStringSubmatch(line); fields != nil {
				if fields[1] != "" {
					line = "// " + fields[1] + "\n"
					fmt.Print(line)
				}
				isMultipleComment = false
				continue
			}

			if fields := reMiddleMultipleComment.FindStringSubmatch(line); fields != nil {
				line = "// " + fields[1]
				fmt.Print(line)
				continue
			}
		}

		// === Turn defines.
		if fields := reDefine.FindStringSubmatch(line); fields != nil {
			if !isDefine {
				isDefine = true
				fmt.Print("const (\n")
			}
			line = fmt.Sprintf("%s = %s", fields[2], fields[3])

			// Removes comment (if any) to ckeck if it is a macro.
			lastField := strings.Split(fields[3], "//", -1)[0]
			if reMacroInDefine.MatchString(lastField) {
				line = C_LINE_COMMENT + line
			}

			fmt.Print(line)
			continue
		}

		if isDefine && line == "\n" {
			fmt.Print(")\n\n")
			isDefine = false
			continue
		}

		// === Comment another lines.
		if reSkipLine.MatchString(line) {
			line = C_LINE_COMMENT + line
			fmt.Print(line)
			continue
		}

		fmt.Print(line)
	}

	return nil
}

func main() {
	var isValidOS bool
	validOS := []string{"darwin", "freebsd", "linux", "windows"}

	// === Parse the flags
	flag.Usage = usage
	flag.Parse()

	if *fListOS {
		fmt.Print("  = Systems\n\n  ")
		fmt.Println(validOS)
		os.Exit(0)
	}

	if len(os.Args) == 1 || *fOS == "" || *fPackage == "" {
		usage()
	}

	*fOS = strings.ToLower(*fOS)

	for _, v := range validOS {
		if v == *fOS {
			isValidOS = true
			break
		}
	}

	if !isValidOS {
		fmt.Fprintf(os.Stderr, "ERROR: System passed in flag 's' is invalid\n")
		os.Exit(1)
	}

	// === Update header
	cmd := strings.Join(os.Args, " ")
	header = strings.Replace(header, "{cmd}", path.Base(cmd), 1)
	header = strings.Replace(header, "{pkg}", *fPackage, 1)

//File := "/usr/include/asm-generic/ioctls.h"
File := "/usr/include/asm-generic/termbits.h"

	if err := turn(File); err != nil {
		fmt.Fprintf(os.Stderr, err.String())
		os.Exit(1)
	}
}

<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/codegangsta/cli"
	"github.com/mattbaird/gota-api/api"
	"os"
	//	"strings"
)

func main() {
	address := ""
	commands := []cli.Command{
		{
			Name:        "GetMatchHistory",
			ShortName:   "mh",
			Usage:       "./gota-api mh [options]",
			Description: "Request Match history",
			Flags: []cli.Flag{
				cli.IntFlag{"startAt", -1, "The match ID to start retrieval. Optional. Example 27110133"},
				// the following are optional
				cli.StringFlag{"playerName", "", ""},
				cli.IntFlag{"heroId", -1, ""},
				cli.StringFlag{"gameMode", "", ""},
				cli.StringFlag{"skill", "", ""},
				cli.StringFlag{"dateMin", "", ""},
				cli.StringFlag{"dateMax", "", ""},
				cli.IntFlag{"minPlayers", -1, ""},
				cli.IntFlag{"accountId", -1, ""},
				cli.StringFlag{"leagueId", "", ""},
				cli.IntFlag{"matchesRequested", -1, ""},
				cli.BoolFlag{"tournamentGamesOnly", "false"},
			},
			Action: func(c *cli.Context) {
				startAtMatchId := c.Int("startAt")
				playerName := c.String("playerName")
				heroId := c.Int("heroId")
				gameMode := c.String("gameMode")
				skill := c.String("skill")
				dateMin := c.String("dateMin")
				dateMax := c.String("dateMax")
				minPlayers := c.Int("minPlayers")
				accountId := c.Int("accountId")
				leagueId := c.String("leagueId")
				matchesRequested := c.Int("matchesRequested")
				tournamentGamesOnly := c.Bool("tournamentGamesOnly")
				gotaApi, err := api.NewGotaAPI("", "en_us")
				if err != nil {
					fmt.Printf("Problem: %v", err)
					os.Exit(1)
				}
				matchHistory, err := gotaApi.GetMatchHistory(playerName, heroId, gameMode, skill, dateMin, dateMax,
					minPlayers, accountId, leagueId, startAtMatchId, matchesRequested, tournamentGamesOnly)
				if err != nil {
					fmt.Printf("Error:%v", err)
					os.Exit(1)
				}
				fmt.Printf("Number of results: %v", matchHistory.NumberOfResults)
			},
		},
		{
			Name:        "GetMatchDetails",
			ShortName:   "md",
			Usage:       "./gota-api md matchId",
			Description: "Request Match Details",
			Flags: []cli.Flag{
				cli.IntFlag{"matchId", -1, "The match ID to get details for. Example 27110133"},
			},
			Action: func(c *cli.Context) {
				matchId := c.Int("matchId")
				gotaApi, err := api.NewGotaAPI("", "en_us")
				if err != nil {
					fmt.Printf("Problem: %v", err)
					os.Exit(1)
				}
				matchDetails, err := gotaApi.GetMatchDetails(matchId)
				if err != nil {
					fmt.Printf("Error:%v", err)
					os.Exit(1)
				}
				fmt.Printf("Duration: %v", matchDetails.Duration)
			},
		},
		{
			Name:        "GetMatchHistoryBySequenceNum",
			ShortName:   "mhs",
			Usage:       "./gota-api mhs [options]",
			Description: "Get heroes",
			Flags: []cli.Flag{
				cli.IntFlag{"startAtMatchSeqNum", 1, "The match ID to start at. Example 27110133"},
				cli.IntFlag{"matchesRequested", -1, "The number of matches to get"},
			},
			Action: func(c *cli.Context) {
				startAtMatchSeqNum := c.Int("startAtMatchSeqNum")
				matchesRequested := c.Int("matchesRequested")
				gotaApi, err := api.NewGotaAPI("", "en_us")
				if err != nil {
					fmt.Printf("Problem: %v", err)
					os.Exit(1)
				}
				matchHistory, err := gotaApi.GetMatchHistoryBySequenceNum(startAtMatchSeqNum, matchesRequested)
				if err != nil {
					fmt.Printf("Error:%v", err)
					os.Exit(1)
				}
				fmt.Printf("matchHistory: %v", matchHistory)
			},
		},
		{
			Name:        "GetHeroes",
			ShortName:   "h",
			Usage:       "./gota-api h",
			Description: "Get heroes",
			Flags:       []cli.Flag{},
			Action: func(c *cli.Context) {
				gotaApi, err := api.NewGotaAPI("", "en_us")
				if err != nil {
					fmt.Printf("Problem: %v", err)
					os.Exit(1)
				}
				heroes, err := gotaApi.GetHeroes()
				if err != nil {
					fmt.Printf("Error:%v", err)
					os.Exit(1)
				}
				fmt.Printf("# Heroes: %v", heroes.Count)
			},
		},
		{
			Name:        "GetLeagueListing",
			ShortName:   "ll",
			Usage:       "./gota-api ll",
			Description: "Get League Listings",
			Flags:       []cli.Flag{},
			Action: func(c *cli.Context) {
				gotaApi, err := api.NewGotaAPI("", "en_us")
				if err != nil {
					fmt.Printf("Problem: %v", err)
					os.Exit(1)
				}
				leagueListings, err := gotaApi.GetLeagueListing()
				if err != nil {
					fmt.Printf("Error:%v", err)
					os.Exit(1)
				}
				fmt.Printf("# leagueListings: %v", len(leagueListings.Leagues))
			},
		},
		{
			Name:        "GetLiveLeagueGames",
			ShortName:   "llg",
			Usage:       "./gota-api llg",
			Description: "Get live league games",
			Flags:       []cli.Flag{},
			Action: func(c *cli.Context) {
				gotaApi, err := api.NewGotaAPI("", "en_us")
				if err != nil {
					fmt.Printf("Problem: %v", err)
					os.Exit(1)
				}
				liveLeagueGames, err := gotaApi.GetLiveLeagueGames()
				if err != nil {
					fmt.Printf("Error:%v", err)
					os.Exit(1)
				}
				fmt.Printf("liveLeagueGames: %v", liveLeagueGames)
			},
		},
		{
			Name:        "GetTeamInfoByTeamID",
			ShortName:   "ti",
			Usage:       "./gota-api ti [options]",
			Description: "Get Team Information by ID",
			Flags: []cli.Flag{
				cli.IntFlag{"startAtTeamId", -1, "Which Team ID to start at."},
				cli.IntFlag{"teamsRequested", -1, "Number of teams to retrieve"},
			},
			Action: func(c *cli.Context) {
				startAtTeamId := c.Int("startAtTeamId")
				teamsRequested := c.Int("teamsRequested")
				gotaApi, err := api.NewGotaAPI("", "en_us")
				if err != nil {
					fmt.Printf("Problem: %v", err)
					os.Exit(1)
				}
				team, err := gotaApi.GetTeamInfoByTeamID(startAtTeamId, teamsRequested)
				if err != nil {
					fmt.Printf("Error:%v", err)
					os.Exit(1)
				}
				fmt.Printf("team: %v", team)
			},
		},
		{
			Name:        "GetPlayerSummaries",
			ShortName:   "ps",
			Usage:       "./gota-api ps [ids]",
			Description: "Get Play Summaries",
			Flags: []cli.Flag{
				cli.IntSliceFlag{"ids", nil, "Comma separated array of user ids"},
			},
			Action: func(c *cli.Context) {
				ids := c.IntSlice("ids")
				gotaApi, err := api.NewGotaAPI("", "en_us")
				if err != nil {
					fmt.Printf("Problem: %v", err)
					os.Exit(1)
				}
				playerSummaries, err := gotaApi.GetPlayerSummaries(ids...)
				if err != nil {
					fmt.Printf("Error:%v", err)
					os.Exit(1)
				}
				fmt.Printf("playerSummaries: %v", playerSummaries)
			},
		},
	}
	app := cli.NewApp()
	app.Commands = commands
	app.Name = "gota"
	app.Version = "0.0.3"

	app.Action = func(ctx *cli.Context) {
		if len(ctx.Args()) == 0 {
			cli.ShowAppHelp(ctx)
			os.Exit(1)
		}
		address = ctx.Args()[0]
		console := cli.NewApp()
		console.Commands = commands
		console.Action = func(c *cli.Context) {
			fmt.Println("Command not found. Type 'help' for a list of commands.")
		}
	}
	app.Run(os.Args)
	os.Exit(0)
}
<commit_msg>better flags for each command<commit_after>package main

import (
	"fmt"
	"github.com/codegangsta/cli"
	"github.com/mattbaird/gota-api/api"
	"os"
	//	"strings"
)

func main() {
	address := ""
	commands := []cli.Command{
		{
			Name:        "GetMatchHistory",
			ShortName:   "mh",
			Usage:       "./gota-api mh [playerName] [heroId] [gameMode] [skill] [dateMin] [dateMax] [minPlayers] [accountId] [leagueId] [matchesRequested] [tournamentGamesOnly]",
			Description: "Request Match history",
			Flags: []cli.Flag{
				cli.IntFlag{"startAt", -1, "The match ID to start retrieval. Optional. Example 27110133"},
				// the following are optional
				cli.StringFlag{"playerName", "", ""},
				cli.IntFlag{"heroId", -1, ""},
				cli.StringFlag{"gameMode", "", ""},
				cli.StringFlag{"skill", "", ""},
				cli.StringFlag{"dateMin", "", ""},
				cli.StringFlag{"dateMax", "", ""},
				cli.IntFlag{"minPlayers", -1, ""},
				cli.IntFlag{"accountId", -1, ""},
				cli.StringFlag{"leagueId", "", ""},
				cli.IntFlag{"matchesRequested", -1, ""},
				cli.BoolFlag{"tournamentGamesOnly", "false"},
			},
			Action: func(c *cli.Context) {
				startAtMatchId := c.Int("startAt")
				playerName := c.String("playerName")
				heroId := c.Int("heroId")
				gameMode := c.String("gameMode")
				skill := c.String("skill")
				dateMin := c.String("dateMin")
				dateMax := c.String("dateMax")
				minPlayers := c.Int("minPlayers")
				accountId := c.Int("accountId")
				leagueId := c.String("leagueId")
				matchesRequested := c.Int("matchesRequested")
				tournamentGamesOnly := c.Bool("tournamentGamesOnly")
				gotaApi, err := api.NewGotaAPI("", "en_us")
				if err != nil {
					fmt.Printf("Problem: %v", err)
					os.Exit(1)
				}
				matchHistory, err := gotaApi.GetMatchHistory(playerName, heroId, gameMode, skill, dateMin, dateMax,
					minPlayers, accountId, leagueId, startAtMatchId, matchesRequested, tournamentGamesOnly)
				if err != nil {
					fmt.Printf("Error:%v", err)
					os.Exit(1)
				}
				fmt.Printf("Number of results: %v", matchHistory.NumberOfResults)
			},
		},
		{
			Name:        "GetMatchDetails",
			ShortName:   "md",
			Usage:       "./gota-api md [matchId]",
			Description: "Request Match Details",
			Flags: []cli.Flag{
				cli.IntFlag{"matchId", -1, "The match ID to get details for. Example 27110133"},
			},
			Action: func(c *cli.Context) {
				matchId := c.Int("matchId")
				gotaApi, err := api.NewGotaAPI("", "en_us")
				if err != nil {
					fmt.Printf("Problem: %v", err)
					os.Exit(1)
				}
				matchDetails, err := gotaApi.GetMatchDetails(matchId)
				if err != nil {
					fmt.Printf("Error:%v", err)
					os.Exit(1)
				}
				fmt.Printf("Duration: %v", matchDetails.Duration)
			},
		},
		{
			Name:        "GetMatchHistoryBySequenceNum",
			ShortName:   "mhs",
			Usage:       "./gota-api mhs [startAtMatchSeqNum] [matchesRequested]",
			Description: "Get heroes",
			Flags: []cli.Flag{
				cli.IntFlag{"startAtMatchSeqNum", 1, "The match ID to start at. Example 27110133"},
				cli.IntFlag{"matchesRequested", -1, "The number of matches to get"},
			},
			Action: func(c *cli.Context) {
				startAtMatchSeqNum := c.Int("startAtMatchSeqNum")
				matchesRequested := c.Int("matchesRequested")
				gotaApi, err := api.NewGotaAPI("", "en_us")
				if err != nil {
					fmt.Printf("Problem: %v", err)
					os.Exit(1)
				}
				matchHistory, err := gotaApi.GetMatchHistoryBySequenceNum(startAtMatchSeqNum, matchesRequested)
				if err != nil {
					fmt.Printf("Error:%v", err)
					os.Exit(1)
				}
				fmt.Printf("matchHistory: %v", matchHistory)
			},
		},
		{
			Name:        "GetHeroes",
			ShortName:   "h",
			Usage:       "./gota-api h",
			Description: "Get heroes",
			Flags:       []cli.Flag{},
			Action: func(c *cli.Context) {
				gotaApi, err := api.NewGotaAPI("", "en_us")
				if err != nil {
					fmt.Printf("Problem: %v", err)
					os.Exit(1)
				}
				heroes, err := gotaApi.GetHeroes()
				if err != nil {
					fmt.Printf("Error:%v", err)
					os.Exit(1)
				}
				fmt.Printf("# Heroes: %v", heroes.Count)
			},
		},
		{
			Name:        "GetLeagueListing",
			ShortName:   "ll",
			Usage:       "./gota-api ll",
			Description: "Get League Listings",
			Flags:       []cli.Flag{},
			Action: func(c *cli.Context) {
				gotaApi, err := api.NewGotaAPI("", "en_us")
				if err != nil {
					fmt.Printf("Problem: %v", err)
					os.Exit(1)
				}
				leagueListings, err := gotaApi.GetLeagueListing()
				if err != nil {
					fmt.Printf("Error:%v", err)
					os.Exit(1)
				}
				fmt.Printf("# leagueListings: %v", len(leagueListings.Leagues))
			},
		},
		{
			Name:        "GetLiveLeagueGames",
			ShortName:   "llg",
			Usage:       "./gota-api llg",
			Description: "Get live league games",
			Flags:       []cli.Flag{},
			Action: func(c *cli.Context) {
				gotaApi, err := api.NewGotaAPI("", "en_us")
				if err != nil {
					fmt.Printf("Problem: %v", err)
					os.Exit(1)
				}
				liveLeagueGames, err := gotaApi.GetLiveLeagueGames()
				if err != nil {
					fmt.Printf("Error:%v", err)
					os.Exit(1)
				}
				fmt.Printf("liveLeagueGames: %v", liveLeagueGames)
			},
		},
		{
			Name:        "GetTeamInfoByTeamID",
			ShortName:   "ti",
			Usage:       "./gota-api ti [startAtTeamId] [teamsRequested]",
			Description: "Get Team Information by ID",
			Flags: []cli.Flag{
				cli.IntFlag{"startAtTeamId", -1, "Which Team ID to start at."},
				cli.IntFlag{"teamsRequested", -1, "Number of teams to retrieve"},
			},
			Action: func(c *cli.Context) {
				startAtTeamId := c.Int("startAtTeamId")
				teamsRequested := c.Int("teamsRequested")
				gotaApi, err := api.NewGotaAPI("", "en_us")
				if err != nil {
					fmt.Printf("Problem: %v", err)
					os.Exit(1)
				}
				team, err := gotaApi.GetTeamInfoByTeamID(startAtTeamId, teamsRequested)
				if err != nil {
					fmt.Printf("Error:%v", err)
					os.Exit(1)
				}
				fmt.Printf("team: %v", team)
			},
		},
		{
			Name:        "GetPlayerSummaries",
			ShortName:   "ps",
			Usage:       "./gota-api ps [ids]",
			Description: "Get Play Summaries",
			Flags: []cli.Flag{
				cli.IntSliceFlag{"ids", nil, "Comma separated array of user ids"},
			},
			Action: func(c *cli.Context) {
				ids := c.IntSlice("ids")
				gotaApi, err := api.NewGotaAPI("", "en_us")
				if err != nil {
					fmt.Printf("Problem: %v", err)
					os.Exit(1)
				}
				playerSummaries, err := gotaApi.GetPlayerSummaries(ids...)
				if err != nil {
					fmt.Printf("Error:%v", err)
					os.Exit(1)
				}
				fmt.Printf("playerSummaries: %v", playerSummaries)
			},
		},
	}
	app := cli.NewApp()
	app.Commands = commands
	app.Name = "gota"
	app.Version = "0.0.3"

	app.Action = func(ctx *cli.Context) {
		if len(ctx.Args()) == 0 {
			cli.ShowAppHelp(ctx)
			os.Exit(1)
		}
		address = ctx.Args()[0]
		console := cli.NewApp()
		console.Commands = commands
		console.Action = func(c *cli.Context) {
			fmt.Println("Command not found. Type 'help' for a list of commands.")
		}
	}
	app.Run(os.Args)
	os.Exit(0)
}
<|endoftext|>


<commit_before>/*
   Nging is a toolbox for webmasters
   Copyright (C) 2018-present  Wenhui Shen <swh@admpub.com>

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Affero General Public License as published
   by the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Affero General Public License for more details.

   You should have received a copy of the GNU Affero General Public License
   along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/

package cmd

import (
	"fmt"

	"github.com/admpub/nging/application/library/config"
	"github.com/spf13/cobra"
)

// Nging 版本信息

var versionCmd = &cobra.Command{
	Use:   "version",
	Short: "Version number",
	RunE:  versionRunE,
}

func versionRunE(cmd *cobra.Command, args []string) error {
	fmt.Println(config.Version.String())
	fmt.Println(`dbschema: `, fmt.Sprintf(`v%v`, config.Version.DBSchema))
	return nil
}

func init() {
	rootCmd.AddCommand(versionCmd)

	// Here you will define your flags and configuration settings.

	// Cobra supports Persistent Flags which will work for this command
	// and all subcommands, e.g.:
	// versionCmd.PersistentFlags().String("foo", "", "A help for foo")

	// Cobra supports local flags which will only run when this command
	// is called directly, e.g.:
	// versionCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
<commit_msg>update<commit_after>/*
   Nging is a toolbox for webmasters
   Copyright (C) 2018-present  Wenhui Shen <swh@admpub.com>

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Affero General Public License as published
   by the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Affero General Public License for more details.

   You should have received a copy of the GNU Affero General Public License
   along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/

package cmd

import (
	"fmt"

	"github.com/admpub/nging/application/library/config"
	"github.com/spf13/cobra"
)

// Nging 版本信息

var versionCmd = &cobra.Command{
	Use:   "version",
	Short: "Version number",
	RunE:  versionRunE,
}

func versionRunE(cmd *cobra.Command, args []string) error {
	fmt.Println(config.Version.String())
	fmt.Printf("dbschema: v%v\n", config.Version.DBSchema)
	return nil
}

func init() {
	rootCmd.AddCommand(versionCmd)

	// Here you will define your flags and configuration settings.

	// Cobra supports Persistent Flags which will work for this command
	// and all subcommands, e.g.:
	// versionCmd.PersistentFlags().String("foo", "", "A help for foo")

	// Cobra supports local flags which will only run when this command
	// is called directly, e.g.:
	// versionCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
<|endoftext|>


<commit_before>package main

import (
	"os/exec"
	"strings"
	"encoding/gob"
	"fmt"
	"bufio"
	"io"
	"log"
	"net"
	"os"

	"github.com/flynn/go-discover/discover"
	"github.com/flynn/lorne/types"
	"github.com/titanous/go-dockerclient"
	"github.com/flynn/sampi/types"
	sc "github.com/flynn/sampi/client"
	lc "github.com/flynn/lorne/client"
)

// WARNING: assumes one host at the moment (firstHost will always be the same)

var sd *discover.Client
var sched *sc.Client
var host *lc.Client
var hostid string

func init() {
	var err error
	sd, err = discover.NewClient()
	if err != nil {
		log.Fatal(err)
	}

	sched, err = sc.New()
	if err != nil {
		log.Fatal(err)
	}

	hostid = findHost()
	host, err = lc.New(hostid)
	if err != nil {
		log.Fatal(err)
	}
}

func main() {
	root := "/var/lib/demo/apps"
	hostname := shell("curl -s icanhazip.com")

	set, _ := sd.Services("shelf")
	addrs := set.OnlineAddrs()
	if len(addrs) < 1 {
		panic("Shelf is not discoverable")
	}
	shelfHost := addrs[0]

	app := os.Args[2]
	os.MkdirAll(root+"/"+app, 0755)

	fmt.Printf("-----> Building %s on %s ...\n", app, hostname)

	scheduleAndAttach(app + ".build", docker.Config{
		Image:        "flynn/slugbuilder",
		Cmd:          []string{"http://" + shelfHost + "/" + app + ".tgz"},
		Tty:          false,
		AttachStdin:  true,
		AttachStdout: true,
		AttachStderr: true,
		OpenStdin:    true,
		StdinOnce:    true,
	})

	fmt.Printf("-----> Deploying %s ...\n", app)

	jobid := app + ".web"

	stopIfExists(jobid)
	scheduleWithTcpPort(jobid, docker.Config{
		Image:        "flynn/slugrunner",
		Cmd:          []string{"start", "web"},
		Tty:          false,
		AttachStdin:  false,
		AttachStdout: false,
		AttachStderr: false,
		OpenStdin:    false,
		StdinOnce:    false,
		Env: []string{
			"SLUG_URL=http://" + shelfHost + "/" + app + ".tgz",
		},
	})

	fmt.Printf("=====> Application deployed:\n")
	fmt.Printf("       http://%s:%s\n", hostname, getPort(jobid))
	fmt.Println("")

}

func shell(cmdline string) string {
        out, err := exec.Command("bash", "-c", cmdline).Output()
        if err != nil {
                panic(err)
        }
        return strings.Trim(string(out), " \n")
}

func stopIfExists(jobid string) {
	_, err := host.GetJob(jobid)
	if err != nil {
		return
	}
	if err := host.StopJob(jobid); err != nil {
		return
	}
}

func scheduleWithTcpPort(jobid string, config docker.Config) {

	schedReq := &sampi.ScheduleReq{
		Incremental: true,
		HostJobs:    map[string][]*sampi.Job{hostid: {{ID: jobid, Config: &config, TCPPorts: 1}}},
	}
	if _, err := sched.Schedule(schedReq); err != nil {
		log.Fatal(err)
	}
}

func getPort(jobid string) string {
	job, err := host.GetJob(jobid)
	if err != nil {
		log.Fatal(err)
	}
	return job.Job.Config.PortSpecs[0]
}

func findHost() string {
	state, err := sched.State()
	if err != nil {
		log.Fatal(err)
	}

	var firstHost string
	for k := range state {
		firstHost = k
		break
	}
	if firstHost == "" {
		log.Fatal("no hosts")
	}
	return firstHost
}

func scheduleAndAttach(jobid string, config docker.Config) {

	services, err := sd.Services("flynn-lorne-attach." + hostid)
	if err != nil {
		log.Fatal(err)
	}
	conn, err := net.Dial("tcp", services.OnlineAddrs()[0])
	if err != nil {
		log.Fatal(err)
	}
	err = gob.NewEncoder(conn).Encode(&lorne.AttachReq{
		JobID: jobid,
		Flags: lorne.AttachFlagStdout | lorne.AttachFlagStderr | lorne.AttachFlagStdin | lorne.AttachFlagStream,
	})
	if err != nil {
		log.Fatal(err)
	}
	attachState := make([]byte, 1)
	if _, err := conn.Read(attachState); err != nil {
		log.Fatal(err)
	}
	switch attachState[0] {
	case lorne.AttachError:
		log.Fatal("attach error")
	}

	schedReq := &sampi.ScheduleReq{
		Incremental: true,
		HostJobs:    map[string][]*sampi.Job{hostid: {{ID: jobid, Config: &config}}},
	}
	if _, err := sched.Schedule(schedReq); err != nil {
		log.Fatal(err)
	}

	if _, err := conn.Read(attachState); err != nil {
		log.Fatal(err)
	}

	go func() {
		io.Copy(conn, os.Stdin)
		conn.(*net.TCPConn).CloseWrite()
	}()
	scanner := bufio.NewScanner(conn)
	for scanner.Scan() {
		fmt.Fprintln(os.Stdout, scanner.Text()[8:])
	}
	conn.Close()
}
<commit_msg>pulling port from epxosed ports<commit_after>package main

import (
	"os/exec"
	"strings"
	"encoding/gob"
	"fmt"
	"bufio"
	"io"
	"log"
	"net"
	"time"
	"os"

	"github.com/flynn/go-discover/discover"
	"github.com/flynn/lorne/types"
	"github.com/titanous/go-dockerclient"
	"github.com/flynn/sampi/types"
	sc "github.com/flynn/sampi/client"
	lc "github.com/flynn/lorne/client"
)

// WARNING: assumes one host at the moment (firstHost will always be the same)

var sd *discover.Client
var sched *sc.Client
var host *lc.Client
var hostid string

func init() {
	var err error
	sd, err = discover.NewClient()
	if err != nil {
		log.Fatal(err)
	}

	sched, err = sc.New()
	if err != nil {
		log.Fatal(err)
	}

	hostid = findHost()
	host, err = lc.New(hostid)
	if err != nil {
		log.Fatal(err)
	}
}

func main() {
	root := "/var/lib/demo/apps"
	hostname := shell("curl -s icanhazip.com")

	set, _ := sd.Services("shelf")
	addrs := set.OnlineAddrs()
	if len(addrs) < 1 {
		panic("Shelf is not discoverable")
	}
	shelfHost := addrs[0]

	app := os.Args[2]
	os.MkdirAll(root+"/"+app, 0755)

	fmt.Printf("-----> Building %s on %s ...\n", app, hostname)

	scheduleAndAttach(app + ".build", docker.Config{
		Image:        "flynn/slugbuilder",
		Cmd:          []string{"http://" + shelfHost + "/" + app + ".tgz"},
		Tty:          false,
		AttachStdin:  true,
		AttachStdout: true,
		AttachStderr: true,
		OpenStdin:    true,
		StdinOnce:    true,
	})

	fmt.Printf("-----> Deploying %s ...\n", app)

	jobid := app + ".web"

	stopIfExists(jobid)
	scheduleWithTcpPort(jobid, docker.Config{
		Image:        "flynn/slugrunner",
		Cmd:          []string{"start", "web"},
		Tty:          false,
		AttachStdin:  false,
		AttachStdout: false,
		AttachStderr: false,
		OpenStdin:    false,
		StdinOnce:    false,
		Env: []string{
			"SLUG_URL=http://" + shelfHost + "/" + app + ".tgz",
		},
	})

	time.Sleep(1 * time.Second)
	fmt.Printf("=====> Application deployed:\n")
	fmt.Printf("       http://%s:%s\n", hostname, getPort(jobid))
	fmt.Println("")

}

func shell(cmdline string) string {
        out, err := exec.Command("bash", "-c", cmdline).Output()
        if err != nil {
                panic(err)
        }
        return strings.Trim(string(out), " \n")
}

func stopIfExists(jobid string) {
	_, err := host.GetJob(jobid)
	if err != nil {
		return
	}
	if err := host.StopJob(jobid); err != nil {
		return
	}
}

func scheduleWithTcpPort(jobid string, config docker.Config) {

	schedReq := &sampi.ScheduleReq{
		Incremental: true,
		HostJobs:    map[string][]*sampi.Job{hostid: {{ID: jobid, Config: &config, TCPPorts: 1}}},
	}
	if _, err := sched.Schedule(schedReq); err != nil {
		log.Fatal(err)
	}
}

func getPort(jobid string) string {
	job, err := host.GetJob(jobid)
	if err != nil {
		log.Fatal(err)
	}
	for portspec := range job.Job.Config.ExposedPorts {
		return strings.Split(portspec, "/", 1)[0]
	}
}

func findHost() string {
	state, err := sched.State()
	if err != nil {
		log.Fatal(err)
	}

	var firstHost string
	for k := range state {
		firstHost = k
		break
	}
	if firstHost == "" {
		log.Fatal("no hosts")
	}
	return firstHost
}

func scheduleAndAttach(jobid string, config docker.Config) {

	services, err := sd.Services("flynn-lorne-attach." + hostid)
	if err != nil {
		log.Fatal(err)
	}
	conn, err := net.Dial("tcp", services.OnlineAddrs()[0])
	if err != nil {
		log.Fatal(err)
	}
	err = gob.NewEncoder(conn).Encode(&lorne.AttachReq{
		JobID: jobid,
		Flags: lorne.AttachFlagStdout | lorne.AttachFlagStderr | lorne.AttachFlagStdin | lorne.AttachFlagStream,
	})
	if err != nil {
		log.Fatal(err)
	}
	attachState := make([]byte, 1)
	if _, err := conn.Read(attachState); err != nil {
		log.Fatal(err)
	}
	switch attachState[0] {
	case lorne.AttachError:
		log.Fatal("attach error")
	}

	schedReq := &sampi.ScheduleReq{
		Incremental: true,
		HostJobs:    map[string][]*sampi.Job{hostid: {{ID: jobid, Config: &config}}},
	}
	if _, err := sched.Schedule(schedReq); err != nil {
		log.Fatal(err)
	}

	if _, err := conn.Read(attachState); err != nil {
		log.Fatal(err)
	}

	go func() {
		io.Copy(conn, os.Stdin)
		conn.(*net.TCPConn).CloseWrite()
	}()
	scanner := bufio.NewScanner(conn)
	for scanner.Scan() {
		fmt.Fprintln(os.Stdout, scanner.Text()[8:])
	}
	conn.Close()
}
<|endoftext|>


<commit_before>// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package leaktest provides tools to detect leaked goroutines in tests.
// To use it, call "defer leaktest.Check(t)()" at the beginning of each
// test that may use goroutines.
// copied out of the cockroachdb source tree with slight modifications to be
// more re-useable
package leaktest

import (
	"context"
	"fmt"
	"runtime"
	"sort"
	"strconv"
	"strings"
	"time"
)

type goroutine struct {
	id    uint64
	stack string
}

type goroutineByID []*goroutine

func (g goroutineByID) Len() int           { return len(g) }
func (g goroutineByID) Less(i, j int) bool { return g[i].id < g[j].id }
func (g goroutineByID) Swap(i, j int)      { g[i], g[j] = g[j], g[i] }

func interestingGoroutine(g string) (*goroutine, error) {
	sl := strings.SplitN(g, "\n", 2)
	if len(sl) != 2 {
		return nil, fmt.Errorf("error parsing stack: %q", g)
	}
	stack := strings.TrimSpace(sl[1])
	if strings.HasPrefix(stack, "testing.RunTests") {
		return nil, nil
	}

	if stack == "" ||
		// Ignore HTTP keep alives
		strings.Contains(stack, ").readLoop(") ||
		strings.Contains(stack, ").writeLoop(") ||
		// Below are the stacks ignored by the upstream leaktest code.
		strings.Contains(stack, "testing.Main(") ||
		strings.Contains(stack, "testing.(*T).Run(") ||
		strings.Contains(stack, "runtime.goexit") ||
		strings.Contains(stack, "created by runtime.gc") ||
		strings.Contains(stack, "interestingGoroutines") ||
		strings.Contains(stack, "runtime.MHeap_Scavenger") ||
		strings.Contains(stack, "signal.signal_recv") ||
		strings.Contains(stack, "sigterm.handler") ||
		strings.Contains(stack, "runtime_mcall") ||
		strings.Contains(stack, "goroutine in C code") {
		return nil, nil
	}

	// Parse the goroutine's ID from the header line.
	h := strings.SplitN(sl[0], " ", 3)
	if len(h) < 3 {
		return nil, fmt.Errorf("error parsing stack header: %q", sl[0])
	}
	id, err := strconv.ParseUint(h[1], 10, 64)
	if err != nil {
		return nil, fmt.Errorf("error parsing goroutine id: %s", err)
	}

	return &goroutine{id: id, stack: strings.TrimSpace(g)}, nil
}

// interestingGoroutines returns all goroutines we care about for the purpose
// of leak checking. It excludes testing or runtime ones.
func interestingGoroutines(t ErrorReporter) []*goroutine {
	buf := make([]byte, 2<<20)
	buf = buf[:runtime.Stack(buf, true)]
	var gs []*goroutine
	for _, g := range strings.Split(string(buf), "\n\n") {
		gr, err := interestingGoroutine(g)
		if err != nil {
			t.Errorf("leaktest: %s", err)
			continue
		} else if gr == nil {
			continue
		}
		gs = append(gs, gr)
	}
	sort.Sort(goroutineByID(gs))
	return gs
}

// ErrorReporter is a tiny subset of a testing.TB to make testing not such a
// massive pain
type ErrorReporter interface {
	Errorf(format string, args ...interface{})
}

// Check snapshots the currently-running goroutines and returns a
// function to be run at the end of tests to see whether any
// goroutines leaked, waiting up to 5 seconds in error conditions
func Check(t ErrorReporter) func() {
	return CheckTimeout(t, 5*time.Second)
}

// CheckTimeout is the same as Check, but with a configurable timeout
func CheckTimeout(t ErrorReporter, dur time.Duration) func() {
	ctx, cancel := context.WithCancel(context.Background())
	fn := CheckContext(ctx, t)
	return func() {
		timer := time.AfterFunc(dur, cancel)
		fn()
		// Remember to clean up the timer and context
		timer.Stop()
		cancel()
	}
}

// CheckContext is the same as Check, but uses a context.Context for
// cancellation and timeout control
func CheckContext(ctx context.Context, t ErrorReporter) func() {
	orig := map[uint64]bool{}
	for _, g := range interestingGoroutines(t) {
		orig[g.id] = true
	}
	return func() {
		var leaked []string
		ticker := time.NewTicker(time.Millisecond * 50)
		defer ticker.Stop()

		for {
			select {
			case <-ticker.C:
				leaked = make([]string, 0)
				for _, g := range interestingGoroutines(t) {
					if !orig[g.id] {
						leaked = append(leaked, g.stack)
					}
				}
				if len(leaked) == 0 {
					return
				}
				continue
			case <-ctx.Done():
				t.Errorf("leaktest: %v", ctx.Err())
			}
			break
		}

		for _, g := range leaked {
			t.Errorf("leaktest: leaked goroutine: %v", g)
		}
	}
}
<commit_msg>Define TickerInterval instead of using magic number<commit_after>// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package leaktest provides tools to detect leaked goroutines in tests.
// To use it, call "defer leaktest.Check(t)()" at the beginning of each
// test that may use goroutines.
// copied out of the cockroachdb source tree with slight modifications to be
// more re-useable
package leaktest

import (
	"context"
	"fmt"
	"runtime"
	"sort"
	"strconv"
	"strings"
	"time"
)

// TickerInterval defines the interval used by the ticker in Check* functions.
var TickerInterval = time.Millisecond * 50

type goroutine struct {
	id    uint64
	stack string
}

type goroutineByID []*goroutine

func (g goroutineByID) Len() int           { return len(g) }
func (g goroutineByID) Less(i, j int) bool { return g[i].id < g[j].id }
func (g goroutineByID) Swap(i, j int)      { g[i], g[j] = g[j], g[i] }

func interestingGoroutine(g string) (*goroutine, error) {
	sl := strings.SplitN(g, "\n", 2)
	if len(sl) != 2 {
		return nil, fmt.Errorf("error parsing stack: %q", g)
	}
	stack := strings.TrimSpace(sl[1])
	if strings.HasPrefix(stack, "testing.RunTests") {
		return nil, nil
	}

	if stack == "" ||
		// Ignore HTTP keep alives
		strings.Contains(stack, ").readLoop(") ||
		strings.Contains(stack, ").writeLoop(") ||
		// Below are the stacks ignored by the upstream leaktest code.
		strings.Contains(stack, "testing.Main(") ||
		strings.Contains(stack, "testing.(*T).Run(") ||
		strings.Contains(stack, "runtime.goexit") ||
		strings.Contains(stack, "created by runtime.gc") ||
		strings.Contains(stack, "interestingGoroutines") ||
		strings.Contains(stack, "runtime.MHeap_Scavenger") ||
		strings.Contains(stack, "signal.signal_recv") ||
		strings.Contains(stack, "sigterm.handler") ||
		strings.Contains(stack, "runtime_mcall") ||
		strings.Contains(stack, "goroutine in C code") {
		return nil, nil
	}

	// Parse the goroutine's ID from the header line.
	h := strings.SplitN(sl[0], " ", 3)
	if len(h) < 3 {
		return nil, fmt.Errorf("error parsing stack header: %q", sl[0])
	}
	id, err := strconv.ParseUint(h[1], 10, 64)
	if err != nil {
		return nil, fmt.Errorf("error parsing goroutine id: %s", err)
	}

	return &goroutine{id: id, stack: strings.TrimSpace(g)}, nil
}

// interestingGoroutines returns all goroutines we care about for the purpose
// of leak checking. It excludes testing or runtime ones.
func interestingGoroutines(t ErrorReporter) []*goroutine {
	buf := make([]byte, 2<<20)
	buf = buf[:runtime.Stack(buf, true)]
	var gs []*goroutine
	for _, g := range strings.Split(string(buf), "\n\n") {
		gr, err := interestingGoroutine(g)
		if err != nil {
			t.Errorf("leaktest: %s", err)
			continue
		} else if gr == nil {
			continue
		}
		gs = append(gs, gr)
	}
	sort.Sort(goroutineByID(gs))
	return gs
}

// ErrorReporter is a tiny subset of a testing.TB to make testing not such a
// massive pain
type ErrorReporter interface {
	Errorf(format string, args ...interface{})
}

// Check snapshots the currently-running goroutines and returns a
// function to be run at the end of tests to see whether any
// goroutines leaked, waiting up to 5 seconds in error conditions
func Check(t ErrorReporter) func() {
	return CheckTimeout(t, 5*time.Second)
}

// CheckTimeout is the same as Check, but with a configurable timeout
func CheckTimeout(t ErrorReporter, dur time.Duration) func() {
	ctx, cancel := context.WithCancel(context.Background())
	fn := CheckContext(ctx, t)
	return func() {
		timer := time.AfterFunc(dur, cancel)
		fn()
		// Remember to clean up the timer and context
		timer.Stop()
		cancel()
	}
}

// CheckContext is the same as Check, but uses a context.Context for
// cancellation and timeout control
func CheckContext(ctx context.Context, t ErrorReporter) func() {
	orig := map[uint64]bool{}
	for _, g := range interestingGoroutines(t) {
		orig[g.id] = true
	}
	return func() {
		var leaked []string
		ticker := time.NewTicker(TickerInterval)
		defer ticker.Stop()

		for {
			select {
			case <-ticker.C:
				leaked = make([]string, 0)
				for _, g := range interestingGoroutines(t) {
					if !orig[g.id] {
						leaked = append(leaked, g.stack)
					}
				}
				if len(leaked) == 0 {
					return
				}
				continue
			case <-ctx.Done():
				t.Errorf("leaktest: %v", ctx.Err())
			}
			break
		}

		for _, g := range leaked {
			t.Errorf("leaktest: leaked goroutine: %v", g)
		}
	}
}
<|endoftext|>


<commit_before>package cli

import (
	"bufio"
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/mgutz/ansi"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"strings"
	"text/template"
)

func FindParentPaths(fileName string) []string {
	cwd, _ := os.Getwd()

	paths := make([]string, 0)

	// special case if homedir is not in current path then check there anyway
	homedir := os.Getenv("HOME")
	if !strings.HasPrefix(cwd, homedir) {
		file := fmt.Sprintf("%s/%s", homedir, fileName)
		if _, err := os.Stat(file); err == nil {
			paths = append(paths, file)
		}
	}

	var dir string
	for _, part := range strings.Split(cwd, string(os.PathSeparator)) {
		if dir == "/" {
			dir = fmt.Sprintf("/%s", part)
		} else {
			dir = fmt.Sprintf("%s/%s", dir, part)
		}
		file := fmt.Sprintf("%s/%s", dir, fileName)
		if _, err := os.Stat(file); err == nil {
			paths = append(paths, file)
		}
	}
	return paths
}

func FindClosestParentPath(fileName string) (string, error) {
	paths := FindParentPaths(fileName)
	if len(paths) > 0 {
		return paths[len(paths)-1], nil
	}
	return "", errors.New(fmt.Sprintf("%s not found in parent directory hierarchy", fileName))
}

func readFile(file string) string {
	var bytes []byte
	var err error
	if bytes, err = ioutil.ReadFile(file); err != nil {
		log.Error("Failed to read file %s: %s", file, err)
		os.Exit(1)
	}
	return string(bytes)
}

func runTemplate(templateContent string, data interface{}, out io.Writer) error {

	if out == nil {
		out = os.Stdout
	}

	funcs := map[string]interface{}{
		"toJson": func(content interface{}) (string, error) {
			if bytes, err := json.MarshalIndent(content, "", "    "); err != nil {
				return "", err
			} else {
				return string(bytes), nil
			}
		},
		"append": func(more string, content interface{}) (string, error) {
			switch value := content.(type) {
			case string:
				return string(append([]byte(content.(string)), []byte(more)...)), nil
			case []byte:
				return string(append(content.([]byte), []byte(more)...)), nil
			default:
				return "", errors.New(fmt.Sprintf("Unknown type: %s", value))
			}
		},
		"indent": func(spaces int, content string) string {
			indent := make([]byte, spaces+1, spaces+1)
			indent[0] = '\n'
			for i := 1; i < spaces+1; i += 1 {
				indent[i] = ' '
			}
			return strings.Replace(content, "\n", string(indent), -1)
		},
		"color": func(color string) string {
			return ansi.ColorCode(color)
		},
		"split": func(sep string, content string) []string {
			return strings.Split(content, sep)
		},
	}
	if tmpl, err := template.New("template").Funcs(funcs).Parse(templateContent); err != nil {
		log.Error("Failed to parse template: %s", err)
		return err
	} else {
		if err := tmpl.Execute(out, data); err != nil {
			log.Error("Failed to execute template: %s", err)
			return err
		}
	}
	return nil
}

func responseToJson(resp *http.Response, err error) (interface{}, error) {
	if err != nil {
		return nil, err
	} else {
		return jsonDecode(resp.Body), nil
	}
}

func jsonDecode(io io.Reader) interface{} {
	content, err := ioutil.ReadAll(io)
	var data interface{}
	err = json.Unmarshal(content, &data)
	if err != nil {
		log.Error("JSON Parse Error: %s from %s", err, content)
	}
	return data
}

func jsonEncode(data interface{}) (string, error) {
	buffer := bytes.NewBuffer(make([]byte, 0))
	enc := json.NewEncoder(buffer)

	err := enc.Encode(data)
	if err != nil {
		log.Error("Failed to encode data %s: %s", data, err)
		return "", err
	}
	return buffer.String(), nil
}

func jsonWrite(file string, data interface{}) {
	fh, err := os.OpenFile(file, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
	defer fh.Close()
	if err != nil {
		log.Error("Failed to open %s: %s", file, err)
		os.Exit(1)
	}
	enc := json.NewEncoder(fh)
	enc.Encode(data)
}

func promptYN(prompt string, yes bool) bool {
	reader := bufio.NewReader(os.Stdin)
	if !yes {
		prompt = fmt.Sprintf("%s [y/N]: ", prompt)
	} else {
		prompt = fmt.Sprintf("%s [Y/n]: ", prompt)
	}

	fmt.Printf("%s", prompt)
	text, _ := reader.ReadString('\n')
	ans := strings.ToLower(strings.TrimRight(text, "\n"))
	if ans == "" {
		return yes
	}
	if strings.HasPrefix(ans, "y") {
		return true
	}
	return false
}

func yamlFixup(data interface{}) (interface{}, error) {
	switch d := data.(type) {
	case map[interface{}]interface{}:
		// need to copy this map into a string map so json can encode it
		copy := make(map[string]interface{})
		for key, val := range d {
			switch k := key.(type) {
			case string:
				if fixed, err := yamlFixup(val); err != nil {
					return nil, err
				} else if fixed != nil {
					copy[k] = fixed
				}
			default:
				err := fmt.Errorf("YAML: key %s is type '%T', require 'string'", key, k)
				log.Error("%s", err)
				return nil, err
			}
		}
		return copy, nil
	case map[string]interface{}:
		for k, v := range d {
			if fixed, err := yamlFixup(v); err != nil {
				return nil, err
			} else if fixed != nil {
				d[k] = fixed
			}
		}
		return d, nil
	case []interface{}:
		for i, val := range d {
			if fixed, err := yamlFixup(val); err != nil {
				return nil, err
			} else if fixed != nil {
				d[i] = fixed
			}
		}
		return data, nil
	case string:
		if d == "" {
			return nil, nil
		}
		return d, nil
	default:
		return d, nil
	}
}

func mkdir(dir string) error {
	if stat, err := os.Stat(dir); err != nil && !os.IsNotExist(err) {
		log.Error("Failed to stat %s: %s", dir, err)
		return err
	} else if err == nil && !stat.IsDir() {
		err := fmt.Errorf("%s exists and is not a directory!", dir)
		log.Error("%s", err)
		return err
	} else {
		// dir does not exist, so try to create it
		if err := os.MkdirAll(dir, 0755); err != nil {
			log.Error("Failed to mkdir -p %s: %s", dir, err)
			return err
		}
	}
	return nil
}
<commit_msg>if response is 400, check json for errorMessages and log them<commit_after>package cli

import (
	"bufio"
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/mgutz/ansi"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"strings"
	"text/template"
)

func FindParentPaths(fileName string) []string {
	cwd, _ := os.Getwd()

	paths := make([]string, 0)

	// special case if homedir is not in current path then check there anyway
	homedir := os.Getenv("HOME")
	if !strings.HasPrefix(cwd, homedir) {
		file := fmt.Sprintf("%s/%s", homedir, fileName)
		if _, err := os.Stat(file); err == nil {
			paths = append(paths, file)
		}
	}

	var dir string
	for _, part := range strings.Split(cwd, string(os.PathSeparator)) {
		if dir == "/" {
			dir = fmt.Sprintf("/%s", part)
		} else {
			dir = fmt.Sprintf("%s/%s", dir, part)
		}
		file := fmt.Sprintf("%s/%s", dir, fileName)
		if _, err := os.Stat(file); err == nil {
			paths = append(paths, file)
		}
	}
	return paths
}

func FindClosestParentPath(fileName string) (string, error) {
	paths := FindParentPaths(fileName)
	if len(paths) > 0 {
		return paths[len(paths)-1], nil
	}
	return "", errors.New(fmt.Sprintf("%s not found in parent directory hierarchy", fileName))
}

func readFile(file string) string {
	var bytes []byte
	var err error
	if bytes, err = ioutil.ReadFile(file); err != nil {
		log.Error("Failed to read file %s: %s", file, err)
		os.Exit(1)
	}
	return string(bytes)
}

func runTemplate(templateContent string, data interface{}, out io.Writer) error {

	if out == nil {
		out = os.Stdout
	}

	funcs := map[string]interface{}{
		"toJson": func(content interface{}) (string, error) {
			if bytes, err := json.MarshalIndent(content, "", "    "); err != nil {
				return "", err
			} else {
				return string(bytes), nil
			}
		},
		"append": func(more string, content interface{}) (string, error) {
			switch value := content.(type) {
			case string:
				return string(append([]byte(content.(string)), []byte(more)...)), nil
			case []byte:
				return string(append(content.([]byte), []byte(more)...)), nil
			default:
				return "", errors.New(fmt.Sprintf("Unknown type: %s", value))
			}
		},
		"indent": func(spaces int, content string) string {
			indent := make([]byte, spaces+1, spaces+1)
			indent[0] = '\n'
			for i := 1; i < spaces+1; i += 1 {
				indent[i] = ' '
			}
			return strings.Replace(content, "\n", string(indent), -1)
		},
		"color": func(color string) string {
			return ansi.ColorCode(color)
		},
		"split": func(sep string, content string) []string {
			return strings.Split(content, sep)
		},
	}
	if tmpl, err := template.New("template").Funcs(funcs).Parse(templateContent); err != nil {
		log.Error("Failed to parse template: %s", err)
		return err
	} else {
		if err := tmpl.Execute(out, data); err != nil {
			log.Error("Failed to execute template: %s", err)
			return err
		}
	}
	return nil
}

func responseToJson(resp *http.Response, err error) (interface{}, error) {
	if err != nil {
		return nil, err
	}

	data := jsonDecode(resp.Body)
	if resp.StatusCode == 400 {
		if val, ok := data.(map[string]interface{})["errorMessages"]; ok {
			for _,errMsg := range val.([]interface{}) {
				log.Error("%s", errMsg)
			}
		}
	}

	return data, nil
}

func jsonDecode(io io.Reader) interface{} {
	content, err := ioutil.ReadAll(io)
	var data interface{}
	err = json.Unmarshal(content, &data)
	if err != nil {
		log.Error("JSON Parse Error: %s from %s", err, content)
	}
	return data
}

func jsonEncode(data interface{}) (string, error) {
	buffer := bytes.NewBuffer(make([]byte, 0))
	enc := json.NewEncoder(buffer)

	err := enc.Encode(data)
	if err != nil {
		log.Error("Failed to encode data %s: %s", data, err)
		return "", err
	}
	return buffer.String(), nil
}

func jsonWrite(file string, data interface{}) {
	fh, err := os.OpenFile(file, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
	defer fh.Close()
	if err != nil {
		log.Error("Failed to open %s: %s", file, err)
		os.Exit(1)
	}
	enc := json.NewEncoder(fh)
	enc.Encode(data)
}

func promptYN(prompt string, yes bool) bool {
	reader := bufio.NewReader(os.Stdin)
	if !yes {
		prompt = fmt.Sprintf("%s [y/N]: ", prompt)
	} else {
		prompt = fmt.Sprintf("%s [Y/n]: ", prompt)
	}

	fmt.Printf("%s", prompt)
	text, _ := reader.ReadString('\n')
	ans := strings.ToLower(strings.TrimRight(text, "\n"))
	if ans == "" {
		return yes
	}
	if strings.HasPrefix(ans, "y") {
		return true
	}
	return false
}

func yamlFixup(data interface{}) (interface{}, error) {
	switch d := data.(type) {
	case map[interface{}]interface{}:
		// need to copy this map into a string map so json can encode it
		copy := make(map[string]interface{})
		for key, val := range d {
			switch k := key.(type) {
			case string:
				if fixed, err := yamlFixup(val); err != nil {
					return nil, err
				} else if fixed != nil {
					copy[k] = fixed
				}
			default:
				err := fmt.Errorf("YAML: key %s is type '%T', require 'string'", key, k)
				log.Error("%s", err)
				return nil, err
			}
		}
		return copy, nil
	case map[string]interface{}:
		for k, v := range d {
			if fixed, err := yamlFixup(v); err != nil {
				return nil, err
			} else if fixed != nil {
				d[k] = fixed
			}
		}
		return d, nil
	case []interface{}:
		for i, val := range d {
			if fixed, err := yamlFixup(val); err != nil {
				return nil, err
			} else if fixed != nil {
				d[i] = fixed
			}
		}
		return data, nil
	case string:
		if d == "" {
			return nil, nil
		}
		return d, nil
	default:
		return d, nil
	}
}

func mkdir(dir string) error {
	if stat, err := os.Stat(dir); err != nil && !os.IsNotExist(err) {
		log.Error("Failed to stat %s: %s", dir, err)
		return err
	} else if err == nil && !stat.IsDir() {
		err := fmt.Errorf("%s exists and is not a directory!", dir)
		log.Error("%s", err)
		return err
	} else {
		// dir does not exist, so try to create it
		if err := os.MkdirAll(dir, 0755); err != nil {
			log.Error("Failed to mkdir -p %s: %s", dir, err)
			return err
		}
	}
	return nil
}
<|endoftext|>


<commit_before>/*
Package gothic wraps common behaviour when using Goth. This makes it quick, and easy, to get up
and running with Goth. Of course, if you want complete control over how things flow, in regards
to the authentication process, feel free and use Goth directly.

See https://github.com/markbates/goth/examples/main.go to see this in action.
*/
package gothic

import (
	"errors"
	"fmt"
	"net/http"
	"net/url"
	"os"

	"github.com/gorilla/mux"
	"github.com/gorilla/sessions"
	"github.com/markbates/goth"
)

// SessionName is the key used to access the session store.
const SessionName = "_gothic_session"

// Store can/should be set by applications using gothic. The default is a cookie store.
var Store sessions.Store
var defaultStore sessions.Store

var keySet = false

func init() {
	key := []byte(os.Getenv("SESSION_SECRET"))
	keySet = len(key) != 0
	Store = sessions.NewCookieStore([]byte(key))
	defaultStore = Store
}

/*
BeginAuthHandler is a convienence handler for starting the authentication process.
It expects to be able to get the name of the provider from the query parameters
as either "provider" or ":provider".

BeginAuthHandler will redirect the user to the appropriate authentication end-point
for the requested provider.

See https://github.com/markbates/goth/examples/main.go to see this in action.
*/
func BeginAuthHandler(res http.ResponseWriter, req *http.Request) {
	url, err := GetAuthURL(res, req)
	if err != nil {
		res.WriteHeader(http.StatusBadRequest)
		fmt.Fprintln(res, err)
		return
	}

	http.Redirect(res, req, url, http.StatusTemporaryRedirect)
}

// SetState sets the state string associated with the given request.
// If no state string is associated with the request, one will be generated.
// This state is sent to the provider and can be retrieved during the
// callback.
var SetState = func(req *http.Request) string {
	state := req.URL.Query().Get("state")
	if len(state) > 0 {
		return state
	}

	return "state"

}

// GetState gets the state returned by the provider during the callback.
// This is used to prevent CSRF attacks, see
// http://tools.ietf.org/html/rfc6749#section-10.12
var GetState = func(req *http.Request) string {
	return req.URL.Query().Get("state")
}

/*
GetAuthURL starts the authentication process with the requested provided.
It will return a URL that should be used to send users to.

It expects to be able to get the name of the provider from the query parameters
as either "provider" or ":provider".

I would recommend using the BeginAuthHandler instead of doing all of these steps
yourself, but that's entirely up to you.
*/
func GetAuthURL(res http.ResponseWriter, req *http.Request) (string, error) {
	if !keySet && defaultStore == Store {
		fmt.Println("goth/gothic: no SESSION_SECRET environment variable is set. The default cookie store is not available and any calls will fail. Ignore this warning if you are using a different store.")
	}

	providerName, err := GetProviderName(req)
	if err != nil {
		return "", err
	}

	provider, err := goth.GetProvider(providerName)
	if err != nil {
		return "", err
	}
	sess, err := provider.BeginAuth(SetState(req))
	if err != nil {
		return "", err
	}

	url, err := sess.GetAuthURL()
	if err != nil {
		return "", err
	}

	err = storeInSession(providerName, sess.Marshal(), req, res)

	if err != nil {
		return "", err
	}

	return url, err
}

/*
CompleteUserAuth does what it says on the tin. It completes the authentication
process and fetches all of the basic information about the user from the provider.

It expects to be able to get the name of the provider from the query parameters
as either "provider" or ":provider".

See https://github.com/markbates/goth/examples/main.go to see this in action.
*/
var CompleteUserAuth = func(res http.ResponseWriter, req *http.Request) (goth.User, error) {
	if !keySet && defaultStore == Store {
		fmt.Println("goth/gothic: no SESSION_SECRET environment variable is set. The default cookie store is not available and any calls will fail. Ignore this warning if you are using a different store.")
	}

	providerName, err := GetProviderName(req)
	if err != nil {
		return goth.User{}, err
	}

	provider, err := goth.GetProvider(providerName)
	if err != nil {
		return goth.User{}, err
	}

	value, err := getFromSession(providerName, req)
	if err != nil {
		return goth.User{}, err
	}

	sess, err := provider.UnmarshalSession(value)
	if err != nil {
		return goth.User{}, err
	}

	err = validateState(req, sess)
	if err != nil {
		return goth.User{}, err
	}

	user, err := provider.FetchUser(sess)
	if err == nil {
		// user can be found with existing session data
		return user, err
	}

	// get new token and retry fetch
	_, err = sess.Authorize(provider, req.URL.Query())
	if err != nil {
		return goth.User{}, err
	}

	err = storeInSession(providerName, sess.Marshal(), req, res)

	if err != nil {
		return goth.User{}, err
	}

	return provider.FetchUser(sess)
}

// validateState checks whether a state token was stored
// with the original session and, if so, makes sure that
// the current request contains a matching state value.
func validateState(req *http.Request, sess goth.Session) error {
	rawAuthURL, err := sess.GetAuthURL()
	if err != nil {
		return err
	}

	authURL, err := url.Parse(rawAuthURL)
	if err != nil {
		return err
	}

	state := authURL.Query().Get("state")
	if state != "" && state != req.URL.Query().Get("state") {
		return errors.New("state token mismatch")
	}
	return nil
}

// Logout invalidates a user session.
func Logout(res http.ResponseWriter, req *http.Request) error {
	providerName, err := GetProviderName(req)
	if err != nil {
		return err
	}

	session, err := Store.Get(req, providerName+SessionName)
	if err != nil {
		return err
	}
	session.Options.MaxAge = -1
	session.Values = make(map[interface{}]interface{})
	err = session.Save(req, res)
	if err != nil {
		return errors.New("Could not delete user session ")
	}
	return nil
}

// GetProviderName is a function used to get the name of a provider
// for a given request. By default, this provider is fetched from
// the URL query string. If you provide it in a different way,
// assign your own function to this variable that returns the provider
// name for your request.
var GetProviderName = getProviderName

func getProviderName(req *http.Request) (string, error) {
	// try to get it from the url param "provider"
	if p := req.URL.Query().Get("provider"); p != "" {
		return p, nil
	}

	// try to get it from the url param ":provider"
	if p := req.URL.Query().Get(":provider"); p != "" {
		return p, nil
	}

	// try to get it from the context's value of "provider" key
	if p, ok := mux.Vars(req)["provider"]; ok {
		return p, nil
	}

	// if not found then return an empty string with the corresponding error
	return "", errors.New("you must select a provider")
}

func storeInSession(key string, value string, req *http.Request, res http.ResponseWriter) error {
	session, _ := Store.Get(req, key+SessionName)

	session.Values[key] = value

	return session.Save(req, res)
}

func getFromSession(key string, req *http.Request) (string, error) {
	session, _ := Store.Get(req, key+SessionName)

	value := session.Values[key]
	if value == nil {
		return "", errors.New("could not find a matching session for this request")
	}

	return value.(string), nil
}
<commit_msg>Changed validateState to handle empty state tokens the same as any other<commit_after>/*
Package gothic wraps common behaviour when using Goth. This makes it quick, and easy, to get up
and running with Goth. Of course, if you want complete control over how things flow, in regards
to the authentication process, feel free and use Goth directly.

See https://github.com/markbates/goth/examples/main.go to see this in action.
*/
package gothic

import (
	"errors"
	"fmt"
	"net/http"
	"net/url"
	"os"

	"github.com/gorilla/mux"
	"github.com/gorilla/sessions"
	"github.com/markbates/goth"
)

// SessionName is the key used to access the session store.
const SessionName = "_gothic_session"

// Store can/should be set by applications using gothic. The default is a cookie store.
var Store sessions.Store
var defaultStore sessions.Store

var keySet = false

func init() {
	key := []byte(os.Getenv("SESSION_SECRET"))
	keySet = len(key) != 0
	Store = sessions.NewCookieStore([]byte(key))
	defaultStore = Store
}

/*
BeginAuthHandler is a convienence handler for starting the authentication process.
It expects to be able to get the name of the provider from the query parameters
as either "provider" or ":provider".

BeginAuthHandler will redirect the user to the appropriate authentication end-point
for the requested provider.

See https://github.com/markbates/goth/examples/main.go to see this in action.
*/
func BeginAuthHandler(res http.ResponseWriter, req *http.Request) {
	url, err := GetAuthURL(res, req)
	if err != nil {
		res.WriteHeader(http.StatusBadRequest)
		fmt.Fprintln(res, err)
		return
	}

	http.Redirect(res, req, url, http.StatusTemporaryRedirect)
}

// SetState sets the state string associated with the given request.
// If no state string is associated with the request, one will be generated.
// This state is sent to the provider and can be retrieved during the
// callback.
var SetState = func(req *http.Request) string {
	state := req.URL.Query().Get("state")
	if len(state) > 0 {
		return state
	}

	return "state"

}

// GetState gets the state returned by the provider during the callback.
// This is used to prevent CSRF attacks, see
// http://tools.ietf.org/html/rfc6749#section-10.12
var GetState = func(req *http.Request) string {
	return req.URL.Query().Get("state")
}

/*
GetAuthURL starts the authentication process with the requested provided.
It will return a URL that should be used to send users to.

It expects to be able to get the name of the provider from the query parameters
as either "provider" or ":provider".

I would recommend using the BeginAuthHandler instead of doing all of these steps
yourself, but that's entirely up to you.
*/
func GetAuthURL(res http.ResponseWriter, req *http.Request) (string, error) {
	if !keySet && defaultStore == Store {
		fmt.Println("goth/gothic: no SESSION_SECRET environment variable is set. The default cookie store is not available and any calls will fail. Ignore this warning if you are using a different store.")
	}

	providerName, err := GetProviderName(req)
	if err != nil {
		return "", err
	}

	provider, err := goth.GetProvider(providerName)
	if err != nil {
		return "", err
	}
	sess, err := provider.BeginAuth(SetState(req))
	if err != nil {
		return "", err
	}

	url, err := sess.GetAuthURL()
	if err != nil {
		return "", err
	}

	err = storeInSession(providerName, sess.Marshal(), req, res)

	if err != nil {
		return "", err
	}

	return url, err
}

/*
CompleteUserAuth does what it says on the tin. It completes the authentication
process and fetches all of the basic information about the user from the provider.

It expects to be able to get the name of the provider from the query parameters
as either "provider" or ":provider".

See https://github.com/markbates/goth/examples/main.go to see this in action.
*/
var CompleteUserAuth = func(res http.ResponseWriter, req *http.Request) (goth.User, error) {
	if !keySet && defaultStore == Store {
		fmt.Println("goth/gothic: no SESSION_SECRET environment variable is set. The default cookie store is not available and any calls will fail. Ignore this warning if you are using a different store.")
	}

	providerName, err := GetProviderName(req)
	if err != nil {
		return goth.User{}, err
	}

	provider, err := goth.GetProvider(providerName)
	if err != nil {
		return goth.User{}, err
	}

	value, err := getFromSession(providerName, req)
	if err != nil {
		return goth.User{}, err
	}

	sess, err := provider.UnmarshalSession(value)
	if err != nil {
		return goth.User{}, err
	}

	err = validateState(req, sess)
	if err != nil {
		return goth.User{}, err
	}

	user, err := provider.FetchUser(sess)
	if err == nil {
		// user can be found with existing session data
		return user, err
	}

	// get new token and retry fetch
	_, err = sess.Authorize(provider, req.URL.Query())
	if err != nil {
		return goth.User{}, err
	}

	err = storeInSession(providerName, sess.Marshal(), req, res)

	if err != nil {
		return goth.User{}, err
	}

	return provider.FetchUser(sess)
}

// validateState ensures that the state token param from the original
// AuthURL matches the one included in the current (callback) request.
func validateState(req *http.Request, sess goth.Session) error {
	rawAuthURL, err := sess.GetAuthURL()
	if err != nil {
		return err
	}

	authURL, err := url.Parse(rawAuthURL)
	if err != nil {
		return err
	}

	if authURL.Query().Get("state") != req.URL.Query().Get("state") {
		return errors.New("state token mismatch")
	}
	return nil
}

// Logout invalidates a user session.
func Logout(res http.ResponseWriter, req *http.Request) error {
	providerName, err := GetProviderName(req)
	if err != nil {
		return err
	}

	session, err := Store.Get(req, providerName+SessionName)
	if err != nil {
		return err
	}
	session.Options.MaxAge = -1
	session.Values = make(map[interface{}]interface{})
	err = session.Save(req, res)
	if err != nil {
		return errors.New("Could not delete user session ")
	}
	return nil
}

// GetProviderName is a function used to get the name of a provider
// for a given request. By default, this provider is fetched from
// the URL query string. If you provide it in a different way,
// assign your own function to this variable that returns the provider
// name for your request.
var GetProviderName = getProviderName

func getProviderName(req *http.Request) (string, error) {
	// try to get it from the url param "provider"
	if p := req.URL.Query().Get("provider"); p != "" {
		return p, nil
	}

	// try to get it from the url param ":provider"
	if p := req.URL.Query().Get(":provider"); p != "" {
		return p, nil
	}

	// try to get it from the context's value of "provider" key
	if p, ok := mux.Vars(req)["provider"]; ok {
		return p, nil
	}

	// if not found then return an empty string with the corresponding error
	return "", errors.New("you must select a provider")
}

func storeInSession(key string, value string, req *http.Request, res http.ResponseWriter) error {
	session, _ := Store.Get(req, key+SessionName)

	session.Values[key] = value

	return session.Save(req, res)
}

func getFromSession(key string, req *http.Request) (string, error) {
	session, _ := Store.Get(req, key+SessionName)

	value := session.Values[key]
	if value == nil {
		return "", errors.New("could not find a matching session for this request")
	}

	return value.(string), nil
}
<|endoftext|>


<commit_before>package main

import (
  "net/http"
  "log"
  "io/ioutil"
  "html/template"
)

var root = "/";

type Entry struct {
  Name string
  FullName string
}

func main() {
  http.HandleFunc("/", indexHandler)
  log.Println("Server is started...")
  http.ListenAndServe(":8000", nil)
}

func indexHandler(w http.ResponseWriter, r *http.Request) {
  path := r.URL.Query().Get("path")
  if (path == "") {
    path = root
  }

  t, err := template.ParseFiles("templates/fs.html")
  if err != nil {
    log.Println(err.Error())
    http.Error(w, http.StatusText(500), 500)
  }

  entries := []Entry{}
  files, _ := ioutil.ReadDir(path)
  for _, e := range files {
    entries = append(entries, Entry{
      Name: e.Name(),
      FullName: path + "/" + e.Name(),
    })
  }

  t.Execute(w, entries)
}
<commit_msg>Handling not exist directory<commit_after>package main

import (
  "net/http"
  "log"
  "io/ioutil"
  "html/template"
  "os"
)

var root = "/";

type Entry struct {
  Name string
  FullName string
}

func main() {
  http.HandleFunc("/", indexHandler)
  log.Println("Server is started...")
  http.ListenAndServe(":8000", nil)
}

func indexHandler(w http.ResponseWriter, r *http.Request) {
  path := r.URL.Query().Get("path")
  if (path == "") {
    path = root
  }

  if _, err := os.Stat(path); os.IsNotExist(err) {
    log.Println(err.Error())
    http.Error(w, http.StatusText(404), 404)
    return
  }

  t, err := template.ParseFiles("templates/fs.html")
  if err != nil {
    log.Println(err.Error())
    http.Error(w, http.StatusText(500), 500)
    return
  }

  entries := []Entry{}
  files, _ := ioutil.ReadDir(path)
  for _, e := range files {
    entries = append(entries, Entry{
      Name: e.Name(),
      FullName: path + "/" + e.Name(),
    })
  }

  t.Execute(w, entries)
}
<|endoftext|>


<commit_before>
package fs

import (
	"time"
)

// FileOffset is the relative offset in the file from
// a given  position
type FileOffset int

// Beginning
// Current
// End
const (
	Beginning FileOffset = iota
	Current
	End
)

// FileStats holds information related to a file
// TODO: Use this and fill it out
type FileStats interface {
	// Created returns the date and time the file was created
	Created() time.Time

	// LastModified returns the date and time the file was last modified
	LastModified() time.Time

	// Size returns the size of the file
	Size() int

	// Handles holds a list of current handles to the File
	// TODO: Too dangerous?  Who cares?  Security issues?
	Handles() []File
}

// File is the common interface all files will have
type File interface {
	// 	Close will close the flush all writes and close the file
	// 	any new writes will be ignored and all reads terminated
	Close() error

	//	Given a slice of data we will try to write this to the
	//	file.  Returns the number of bytes written and if an error
	//	occurs that is returned as well.
	//
	//	If an error is returned then the length written will be 0
	//
	Write(data []byte) (int, error)

	//	Read will attemp to read from the file and fill up the byte
	//	slice.  The amount of bytes written will be returned as the
	//	first return value.  If there is an error it will be returned
	//	as the second result, otherwise a nil will be returned instead.
	//
	//	If an error occurs the amount of data read will be 0
	//
	Read(data []byte) (int, error)

	//	Seek will try to move the file pointer to the position given
	//	from the offset provided.
	//
	//	If the resuting position is out of bounds it is clamped to
	//	either the beginning or the end of the file.
	//
	Seek(int, FileOffset)

	//	IsNew returns true if this file was created during opening.
	IsNew() bool

	// Name returns the name of the file.
	Name() string

	// Size returns the size of the file in bytes
	Size() int
}
<commit_msg>Cleanup<commit_after>
package go-fs

import (
	"time"
)

// FileOffset is the relative offset in the file from
// a given  position
type FileOffset int

// Beginning
// Current
// End
const (
	Beginning FileOffset = iota
	Current
	End
)

// FileStats holds information related to a file
// TODO: Use this and fill it out
type FileStats interface {
	// Created returns the date and time the file was created
	Created() time.Time

	// LastModified returns the date and time the file was last modified
	LastModified() time.Time

	// Size returns the size of the file
	Size() int

	// Handles holds a list of current handles to the File
	// TODO: Too dangerous?  Who cares?  Security issues?
	Handles() []File
}

// File is the common interface all files will have
type File interface {
	// 	Close will close the flush all writes and close the file
	// 	any new writes will be ignored and all reads terminated
	Close() error

	//	Given a slice of data we will try to write this to the
	//	file.  Returns the number of bytes written and if an error
	//	occurs that is returned as well.
	//
	//	If an error is returned then the length written will be 0
	//
	Write(data []byte) (int, error)

	//	Read will attemp to read from the file and fill up the byte
	//	slice.  The amount of bytes written will be returned as the
	//	first return value.  If there is an error it will be returned
	//	as the second result, otherwise a nil will be returned instead.
	//
	//	If an error occurs the amount of data read will be 0
	//
	Read(data []byte) (int, error)

	//	Seek will try to move the file pointer to the position given
	//	from the offset provided.
	//
	//	If the resuting position is out of bounds it is clamped to
	//	either the beginning or the end of the file.
	//
	Seek(int, FileOffset)

	//	IsNew returns true if this file was created during opening.
	IsNew() bool

	// Name returns the name of the file.
	Name() string

	// Size returns the size of the file in bytes
	Size() int
}
<|endoftext|>


<commit_before>package astar

import (
	"testing"
)

func AddTruck(x int, y int, label string) *Truck {
	t1 := new(Truck)
	t1.X = x
	t1.Y = y
	t1.label = label
	return t1
}

func AddTube(t1, t2 *Truck, cost float64) *Tube {
	tube1 := new(Tube)
	tube1.Cost = cost
	tube1.from = t1
	tube1.to = t2

	t1.out_to = append(t1.out_to, *tube1)

	return tube1
}

/*

Consider a world with Nodes (Trucks) and Edges (Tubes), Edges each having a cost

   E
  /|
 / |
S--M

S=Start at (0,0)
E=End at (1,1)
M=Middle at (0,1)

S-M and M-E are clean clear tubes. cost: 1

S-E is either:

1) TestGraphPath_ShortDiagonal : diagonal is a nice clean clear Tube , cost: 1.9
   Solver should traverse the bridge.
   Expect solution: Start, End  Total cost: 1.9

1) TestGraphPath_LongDiagonal : diagonal is a Tube plugged full of
   "enormous amounts of material"!, cost: 10000.
   Solver should avoid the plugged tube.
   Expect solution Start,Middle,End  Total cost: 2.0
*/

func createGorelandGraphPath_Diagonal(t *testing.T, diagonal_cost float64, expectedDist float64) {

	world := new(Goreland)

	tr_start := AddTruck(0, 0, "Start")
	tr_mid := AddTruck(0, 1, "Middle")
	tr_end := AddTruck(1, 1, "End")

	AddTube(tr_start, tr_end, diagonal_cost)
	AddTube(tr_start, tr_mid, 1)
	AddTube(tr_mid, tr_end, 1)

	t.Logf("Goreland.  Diagonal cost: %v\n\n", diagonal_cost)

	p, dist, found := Path(tr_start, tr_end)

	if !found {
		t.Log("Could not find a path")
	} else {
		t.Logf("Resulting path\n%s", world.RenderPath(p))
	}
	if !found && expectedDist >= 0 {
		t.Fatal("Could not find a path")
	}
	if found && dist != expectedDist {
		t.Fatalf("Expected dist to be %v but got %v", expectedDist, dist)
	}
}

func TestGraphPaths_ShortDiagonal(t *testing.T) {
	createGorelandGraphPath_Diagonal(t, 1.9, 1.9)
}
func TestGraphPaths_LongDiagonal(t *testing.T) {
	createGorelandGraphPath_Diagonal(t, 10000, 2.0)
}
<commit_msg>changing to // comments<commit_after>package astar

import (
	"testing"
)

func AddTruck(x int, y int, label string) *Truck {
	t1 := new(Truck)
	t1.X = x
	t1.Y = y
	t1.label = label
	return t1
}

func AddTube(t1, t2 *Truck, cost float64) *Tube {
	tube1 := new(Tube)
	tube1.Cost = cost
	tube1.from = t1
	tube1.to = t2

	t1.out_to = append(t1.out_to, *tube1)

	return tube1
}

// Consider a world with Nodes (Trucks) and Edges (Tubes), Edges each having a cost
//
//    E
//   /|
//  / |
// S--M
//
// S=Start at (0,0)
// E=End at (1,1)
// M=Middle at (0,1)
//
// S-M and M-E are clean clear tubes. cost: 1
//
// S-E is either:
//
// 1) TestGraphPath_ShortDiagonal : diagonal is a nice clean clear Tube , cost: 1.9
//    Solver should traverse the bridge.
//    Expect solution: Start, End  Total cost: 1.9
//
// 1) TestGraphPath_LongDiagonal : diagonal is a Tube plugged full of
//    "enormous amounts of material"!, cost: 10000.
//    Solver should avoid the plugged tube.
//    Expect solution Start,Middle,End  Total cost: 2.0

func createGorelandGraphPath_Diagonal(t *testing.T, diagonal_cost float64, expectedDist float64) {

	world := new(Goreland)

	tr_start := AddTruck(0, 0, "Start")
	tr_mid := AddTruck(0, 1, "Middle")
	tr_end := AddTruck(1, 1, "End")

	AddTube(tr_start, tr_end, diagonal_cost)
	AddTube(tr_start, tr_mid, 1)
	AddTube(tr_mid, tr_end, 1)

	t.Logf("Goreland.  Diagonal cost: %v\n\n", diagonal_cost)

	p, dist, found := Path(tr_start, tr_end)

	if !found {
		t.Log("Could not find a path")
	} else {
		t.Logf("Resulting path\n%s", world.RenderPath(p))
	}
	if !found && expectedDist >= 0 {
		t.Fatal("Could not find a path")
	}
	if found && dist != expectedDist {
		t.Fatalf("Expected dist to be %v but got %v", expectedDist, dist)
	}
}

func TestGraphPaths_ShortDiagonal(t *testing.T) {
	createGorelandGraphPath_Diagonal(t, 1.9, 1.9)
}
func TestGraphPaths_LongDiagonal(t *testing.T) {
	createGorelandGraphPath_Diagonal(t, 10000, 2.0)
}
<|endoftext|>


<commit_before>/*
Copyright 2018 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 app implements a server that runs a set of active
// components.  This includes node controllers, service and
// route controller, and so on.
//
package app

import (
	"fmt"
	"net"
	"net/http"
	"strings"

	cloudprovider "k8s.io/cloud-provider"
	"k8s.io/cloud-provider/app/config"
	cloudnodecontroller "k8s.io/cloud-provider/controllers/node"
	cloudnodelifecyclecontroller "k8s.io/cloud-provider/controllers/nodelifecycle"
	routecontroller "k8s.io/cloud-provider/controllers/route"
	servicecontroller "k8s.io/cloud-provider/controllers/service"
	"k8s.io/klog/v2"
	netutils "k8s.io/utils/net"

	utilfeature "k8s.io/apiserver/pkg/util/feature"
)

const (
	// IPv6DualStack enables ipv6 dual stack feature
	// Original copy from pkg/features/kube_features.go
	IPv6DualStack = "IPv6DualStack"
)

func startCloudNodeController(ctx *config.CompletedConfig, cloud cloudprovider.Interface, stopCh <-chan struct{}) (http.Handler, bool, error) {
	// Start the CloudNodeController
	nodeController, err := cloudnodecontroller.NewCloudNodeController(
		ctx.SharedInformers.Core().V1().Nodes(),
		// cloud node controller uses existing cluster role from node-controller
		ctx.ClientBuilder.ClientOrDie("node-controller"),
		cloud,
		ctx.ComponentConfig.NodeStatusUpdateFrequency.Duration,
	)
	if err != nil {
		klog.Warningf("failed to start cloud node controller: %s", err)
		return nil, false, nil
	}

	go nodeController.Run(stopCh)

	return nil, true, nil
}

func startCloudNodeLifecycleController(ctx *config.CompletedConfig, cloud cloudprovider.Interface, stopCh <-chan struct{}) (http.Handler, bool, error) {
	// Start the cloudNodeLifecycleController
	cloudNodeLifecycleController, err := cloudnodelifecyclecontroller.NewCloudNodeLifecycleController(
		ctx.SharedInformers.Core().V1().Nodes(),
		// cloud node lifecycle controller uses existing cluster role from node-controller
		ctx.ClientBuilder.ClientOrDie("node-controller"),
		cloud,
		ctx.ComponentConfig.KubeCloudShared.NodeMonitorPeriod.Duration,
	)
	if err != nil {
		klog.Warningf("failed to start cloud node lifecycle controller: %s", err)
		return nil, false, nil
	}

	go cloudNodeLifecycleController.Run(stopCh)

	return nil, true, nil
}

func startServiceController(ctx *config.CompletedConfig, cloud cloudprovider.Interface, stopCh <-chan struct{}) (http.Handler, bool, error) {
	// Start the service controller
	serviceController, err := servicecontroller.New(
		cloud,
		ctx.ClientBuilder.ClientOrDie("service-controller"),
		ctx.SharedInformers.Core().V1().Services(),
		ctx.SharedInformers.Core().V1().Nodes(),
		ctx.ComponentConfig.KubeCloudShared.ClusterName,
		utilfeature.DefaultFeatureGate,
	)
	if err != nil {
		// This error shouldn't fail. It lives like this as a legacy.
		klog.Errorf("Failed to start service controller: %v", err)
		return nil, false, nil
	}

	go serviceController.Run(stopCh, int(ctx.ComponentConfig.ServiceController.ConcurrentServiceSyncs))

	return nil, true, nil
}

func startRouteController(ctx *config.CompletedConfig, cloud cloudprovider.Interface, stopCh <-chan struct{}) (http.Handler, bool, error) {
	if !ctx.ComponentConfig.KubeCloudShared.ConfigureCloudRoutes {
		klog.Infof("Will not configure cloud provider routes, --configure-cloud-routes: %v", ctx.ComponentConfig.KubeCloudShared.ConfigureCloudRoutes)
		return nil, false, nil
	}

	// If CIDRs should be allocated for pods and set on the CloudProvider, then start the route controller
	routes, ok := cloud.Routes()
	if !ok {
		klog.Warning("configure-cloud-routes is set, but cloud provider does not support routes. Will not configure cloud provider routes.")
		return nil, false, nil
	}

	// failure: bad cidrs in config
	clusterCIDRs, dualStack, err := processCIDRs(ctx.ComponentConfig.KubeCloudShared.ClusterCIDR)
	if err != nil {
		return nil, false, err
	}

	// failure: more than one cidr and dual stack is not enabled
	if len(clusterCIDRs) > 1 && !utilfeature.DefaultFeatureGate.Enabled(IPv6DualStack) {
		return nil, false, fmt.Errorf("len of ClusterCIDRs==%v and dualstack feature is not enabled", len(clusterCIDRs))
	}

	// failure: more than one cidr but they are not configured as dual stack
	if len(clusterCIDRs) > 1 && !dualStack {
		return nil, false, fmt.Errorf("len of ClusterCIDRs==%v and they are not configured as dual stack (at least one from each IPFamily", len(clusterCIDRs))
	}

	// failure: more than cidrs is not allowed even with dual stack
	if len(clusterCIDRs) > 2 {
		return nil, false, fmt.Errorf("length of clusterCIDRs is:%v more than max allowed of 2", len(clusterCIDRs))
	}

	routeController := routecontroller.New(
		routes,
		ctx.ClientBuilder.ClientOrDie("route-controller"),
		ctx.SharedInformers.Core().V1().Nodes(),
		ctx.ComponentConfig.KubeCloudShared.ClusterName,
		clusterCIDRs,
	)
	go routeController.Run(stopCh, ctx.ComponentConfig.KubeCloudShared.RouteReconciliationPeriod.Duration)

	return nil, true, nil
}

// processCIDRs is a helper function that works on a comma separated cidrs and returns
// a list of typed cidrs
// a flag if cidrs represents a dual stack
// error if failed to parse any of the cidrs
func processCIDRs(cidrsList string) ([]*net.IPNet, bool, error) {
	cidrsSplit := strings.Split(strings.TrimSpace(cidrsList), ",")

	cidrs, err := netutils.ParseCIDRs(cidrsSplit)
	if err != nil {
		return nil, false, err
	}

	// if cidrs has an error then the previous call will fail
	// safe to ignore error checking on next call
	dualstack, _ := netutils.IsDualStackCIDRs(cidrs)

	return cidrs, dualstack, nil
}
<commit_msg>cloud-controller-manager: improve warning message for --configure-cloud-routes<commit_after>/*
Copyright 2018 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 app implements a server that runs a set of active
// components.  This includes node controllers, service and
// route controller, and so on.
//
package app

import (
	"fmt"
	"net"
	"net/http"
	"strings"

	cloudprovider "k8s.io/cloud-provider"
	"k8s.io/cloud-provider/app/config"
	cloudnodecontroller "k8s.io/cloud-provider/controllers/node"
	cloudnodelifecyclecontroller "k8s.io/cloud-provider/controllers/nodelifecycle"
	routecontroller "k8s.io/cloud-provider/controllers/route"
	servicecontroller "k8s.io/cloud-provider/controllers/service"
	"k8s.io/klog/v2"
	netutils "k8s.io/utils/net"

	utilfeature "k8s.io/apiserver/pkg/util/feature"
)

const (
	// IPv6DualStack enables ipv6 dual stack feature
	// Original copy from pkg/features/kube_features.go
	IPv6DualStack = "IPv6DualStack"
)

func startCloudNodeController(ctx *config.CompletedConfig, cloud cloudprovider.Interface, stopCh <-chan struct{}) (http.Handler, bool, error) {
	// Start the CloudNodeController
	nodeController, err := cloudnodecontroller.NewCloudNodeController(
		ctx.SharedInformers.Core().V1().Nodes(),
		// cloud node controller uses existing cluster role from node-controller
		ctx.ClientBuilder.ClientOrDie("node-controller"),
		cloud,
		ctx.ComponentConfig.NodeStatusUpdateFrequency.Duration,
	)
	if err != nil {
		klog.Warningf("failed to start cloud node controller: %s", err)
		return nil, false, nil
	}

	go nodeController.Run(stopCh)

	return nil, true, nil
}

func startCloudNodeLifecycleController(ctx *config.CompletedConfig, cloud cloudprovider.Interface, stopCh <-chan struct{}) (http.Handler, bool, error) {
	// Start the cloudNodeLifecycleController
	cloudNodeLifecycleController, err := cloudnodelifecyclecontroller.NewCloudNodeLifecycleController(
		ctx.SharedInformers.Core().V1().Nodes(),
		// cloud node lifecycle controller uses existing cluster role from node-controller
		ctx.ClientBuilder.ClientOrDie("node-controller"),
		cloud,
		ctx.ComponentConfig.KubeCloudShared.NodeMonitorPeriod.Duration,
	)
	if err != nil {
		klog.Warningf("failed to start cloud node lifecycle controller: %s", err)
		return nil, false, nil
	}

	go cloudNodeLifecycleController.Run(stopCh)

	return nil, true, nil
}

func startServiceController(ctx *config.CompletedConfig, cloud cloudprovider.Interface, stopCh <-chan struct{}) (http.Handler, bool, error) {
	// Start the service controller
	serviceController, err := servicecontroller.New(
		cloud,
		ctx.ClientBuilder.ClientOrDie("service-controller"),
		ctx.SharedInformers.Core().V1().Services(),
		ctx.SharedInformers.Core().V1().Nodes(),
		ctx.ComponentConfig.KubeCloudShared.ClusterName,
		utilfeature.DefaultFeatureGate,
	)
	if err != nil {
		// This error shouldn't fail. It lives like this as a legacy.
		klog.Errorf("Failed to start service controller: %v", err)
		return nil, false, nil
	}

	go serviceController.Run(stopCh, int(ctx.ComponentConfig.ServiceController.ConcurrentServiceSyncs))

	return nil, true, nil
}

func startRouteController(ctx *config.CompletedConfig, cloud cloudprovider.Interface, stopCh <-chan struct{}) (http.Handler, bool, error) {
	if !ctx.ComponentConfig.KubeCloudShared.ConfigureCloudRoutes {
		klog.Infof("Will not configure cloud provider routes, --configure-cloud-routes: %v", ctx.ComponentConfig.KubeCloudShared.ConfigureCloudRoutes)
		return nil, false, nil
	}

	// If CIDRs should be allocated for pods and set on the CloudProvider, then start the route controller
	routes, ok := cloud.Routes()
	if !ok {
		klog.Warning("--configure-cloud-routes is set, but cloud provider does not support routes. Will not configure cloud provider routes.")
		return nil, false, nil
	}

	// failure: bad cidrs in config
	clusterCIDRs, dualStack, err := processCIDRs(ctx.ComponentConfig.KubeCloudShared.ClusterCIDR)
	if err != nil {
		return nil, false, err
	}

	// failure: more than one cidr and dual stack is not enabled
	if len(clusterCIDRs) > 1 && !utilfeature.DefaultFeatureGate.Enabled(IPv6DualStack) {
		return nil, false, fmt.Errorf("len of ClusterCIDRs==%v and dualstack feature is not enabled", len(clusterCIDRs))
	}

	// failure: more than one cidr but they are not configured as dual stack
	if len(clusterCIDRs) > 1 && !dualStack {
		return nil, false, fmt.Errorf("len of ClusterCIDRs==%v and they are not configured as dual stack (at least one from each IPFamily", len(clusterCIDRs))
	}

	// failure: more than cidrs is not allowed even with dual stack
	if len(clusterCIDRs) > 2 {
		return nil, false, fmt.Errorf("length of clusterCIDRs is:%v more than max allowed of 2", len(clusterCIDRs))
	}

	routeController := routecontroller.New(
		routes,
		ctx.ClientBuilder.ClientOrDie("route-controller"),
		ctx.SharedInformers.Core().V1().Nodes(),
		ctx.ComponentConfig.KubeCloudShared.ClusterName,
		clusterCIDRs,
	)
	go routeController.Run(stopCh, ctx.ComponentConfig.KubeCloudShared.RouteReconciliationPeriod.Duration)

	return nil, true, nil
}

// processCIDRs is a helper function that works on a comma separated cidrs and returns
// a list of typed cidrs
// a flag if cidrs represents a dual stack
// error if failed to parse any of the cidrs
func processCIDRs(cidrsList string) ([]*net.IPNet, bool, error) {
	cidrsSplit := strings.Split(strings.TrimSpace(cidrsList), ",")

	cidrs, err := netutils.ParseCIDRs(cidrsSplit)
	if err != nil {
		return nil, false, err
	}

	// if cidrs has an error then the previous call will fail
	// safe to ignore error checking on next call
	dualstack, _ := netutils.IsDualStackCIDRs(cidrs)

	return cidrs, dualstack, nil
}
<|endoftext|>