<commit_before>package main

import (
	"flag"
	"fmt"
	"io/ioutil"

	"os"

	"strings"

	mp "github.com/mackerelio/go-mackerel-plugin-helper"
)

var graphdef = map[string](mp.Graphs){
	"unicorn.memory": mp.Graphs{
		Label: "Unicorn Memory",
		Unit:  "bytes",
		Metrics: [](mp.Metrics){
			mp.Metrics{Name: "memory_used", Label: "Memory Used", Diff: false},
		},
	},
	"unicorn.workers": mp.Graphs{
		Label: "Unicorn Workers",
		Unit:  "integer",
		Metrics: [](mp.Metrics){
			mp.Metrics{Name: "worker_total", Label: "Worker Total", Diff: false},
			mp.Metrics{Name: "worker_idles", Label: "Worker Idles", Diff: false},
		},
	},
}

// UnicornPlugin mackerel plugin for Unicorn
type UnicornPlugin struct {
	MasterPid  string
	WorkerPids []string
}

// FetchMetrics interface for mackerelplugin
func (u UnicornPlugin) FetchMetrics() (map[string]interface{}, error) {
	stat := make(map[string]interface{})

	workers := len(u.WorkerPids)
	idles, err := idleWorkerCount(u.WorkerPids)
	if err != nil {
		return stat, err
	}
	used, err := usedMemory()
	if err != nil {
		return stat, err
	}

	stat["worker_total"] = fmt.Sprint(workers)
	stat["worker_idles"] = fmt.Sprint(idles)
	stat["memory_used"] = used

	return stat, nil
}

// GraphDefinition interface for mackerelplugin
func (n UnicornPlugin) GraphDefinition() map[string](mp.Graphs) {
	return graphdef
}

func main() {
	optPidFile := flag.String("pidfile", "", "pidfile path")
	flag.Parse()
	var unicorn UnicornPlugin

	command = RealCommand{}
	pipedCommands = RealPipedCommands{}

	if *optPidFile == "" {
		fmt.Errorf("Required unicorn pidfile.")
		os.Exit(1)
	} else {
		pid, err := ioutil.ReadFile(*optPidFile)
		if err != nil {
			fmt.Errorf("Failed to load unicorn pid file. %s", err)
			os.Exit(1)
		}
		unicorn.MasterPid = strings.Replace(string(pid), "\n", "", 1)
	}

	workerPids, err := fetchUnicornWorkerPids(unicorn.MasterPid)
	if err != nil {
		fmt.Errorf("Failed to fetch unicorn worker pids. %s", err)
		os.Exit(1)
	}
	unicorn.WorkerPids = workerPids

	helper := mp.NewMackerelPlugin(unicorn)

	if os.Getenv("MACKEREL_AGENT_PLUGIN_META") != "" {
		helper.OutputDefinitions()
	} else {
		helper.OutputValues()
	}
}
<commit_msg>stacked true<commit_after>package main

import (
	"flag"
	"fmt"
	"io/ioutil"

	"os"

	"strings"

	mp "github.com/mackerelio/go-mackerel-plugin-helper"
)

var graphdef = map[string](mp.Graphs){
	"unicorn.memory": mp.Graphs{
		Label: "Unicorn Memory",
		Unit:  "bytes",
		Metrics: [](mp.Metrics){
			mp.Metrics{Name: "memory_used", Label: "Memory Used", Diff: false, Stacked: true},
		},
	},
	"unicorn.workers": mp.Graphs{
		Label: "Unicorn Workers",
		Unit:  "integer",
		Metrics: [](mp.Metrics){
			mp.Metrics{Name: "worker_total", Label: "Worker Total", Diff: false, Stacked: true},
			mp.Metrics{Name: "worker_idles", Label: "Worker Idles", Diff: false, Stacked: true},
		},
	},
}

// UnicornPlugin mackerel plugin for Unicorn
type UnicornPlugin struct {
	MasterPid  string
	WorkerPids []string
}

// FetchMetrics interface for mackerelplugin
func (u UnicornPlugin) FetchMetrics() (map[string]interface{}, error) {
	stat := make(map[string]interface{})

	workers := len(u.WorkerPids)
	idles, err := idleWorkerCount(u.WorkerPids)
	if err != nil {
		return stat, err
	}
	used, err := usedMemory()
	if err != nil {
		return stat, err
	}

	stat["worker_total"] = fmt.Sprint(workers)
	stat["worker_idles"] = fmt.Sprint(idles)
	stat["memory_used"] = used

	return stat, nil
}

// GraphDefinition interface for mackerelplugin
func (n UnicornPlugin) GraphDefinition() map[string](mp.Graphs) {
	return graphdef
}

func main() {
	optPidFile := flag.String("pidfile", "", "pidfile path")
	flag.Parse()
	var unicorn UnicornPlugin

	command = RealCommand{}
	pipedCommands = RealPipedCommands{}

	if *optPidFile == "" {
		fmt.Errorf("Required unicorn pidfile.")
		os.Exit(1)
	} else {
		pid, err := ioutil.ReadFile(*optPidFile)
		if err != nil {
			fmt.Errorf("Failed to load unicorn pid file. %s", err)
			os.Exit(1)
		}
		unicorn.MasterPid = strings.Replace(string(pid), "\n", "", 1)
	}

	workerPids, err := fetchUnicornWorkerPids(unicorn.MasterPid)
	if err != nil {
		fmt.Errorf("Failed to fetch unicorn worker pids. %s", err)
		os.Exit(1)
	}
	unicorn.WorkerPids = workerPids

	helper := mp.NewMackerelPlugin(unicorn)

	if os.Getenv("MACKEREL_AGENT_PLUGIN_META") != "" {
		helper.OutputDefinitions()
	} else {
		helper.OutputValues()
	}
}
<|endoftext|>


<commit_before>package main

import (
	"app/controllers"
	"configs"
	"log"
	"net/http"

	"github.com/gorilla/mux"
)

func main() {

	router := mux.NewRouter()

	// controller intances...
	UrlsController := controllers.UrlsController{}

	// web routes...
	router.HandleFunc("/{short-url}/{broadcast-id}/{subscriber-email}", UrlsController.RedirectToLongUrl).Methods("GET")

	// api routes...
	router.HandleFunc("/api/short-url", UrlsController.Index).Methods("POST")

	// serve...
	log.Fatal(http.ListenAndServe(":"+configs.APP_RUNNING_PORT, router))
}
<commit_msg>Fix typo<commit_after>package main

import (
	"app/controllers"
	"configs"
	"log"
	"net/http"

	"github.com/gorilla/mux"
)

func main() {

	router := mux.NewRouter()

	// controller instance...
	UrlsController := controllers.UrlsController{}

	// web routes...
	router.HandleFunc("/{short-url}/{broadcast-id}/{subscriber-email}", UrlsController.RedirectToLongUrl).Methods("GET")

	// api routes...
	router.HandleFunc("/api/short-url", UrlsController.Index).Methods("POST")

	// serve...
	log.Fatal(http.ListenAndServe(":"+configs.APP_RUNNING_PORT, router))
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/goDB/single-server/data"
	"fmt"
)

func main(){
	s := new(data.Store)
	s.M = make(map[string]int)
	s.M["it"]=1
	fmt.Println(s.M)
}
<commit_msg>Delete app.go<commit_after><|endoftext|>


<commit_before>// Copyright 2013, Cong Ding. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: Cong Ding <dinggnu@gmail.com>

package stun

import (
	"errors"
	"net"
)

// Padding the length of the byte slice to multiple of 4.
func padding(bytes []byte) []byte {
	length := uint16(len(bytes))
	return append(bytes, make([]byte, align(length)-length)...)
}

// Align the uint16 number to the smallest multiple of 4, which is larger than
// or equal to the uint16 number.
func align(n uint16) uint16 {
	return (n + 3) & 0xfffc
}

func isLocalAddress(local, localRemote string) bool {
	// Resolve the IP returned by the STUN server first.
	localRemoteAddr, err := net.ResolveUDPAddr("udp", localRemote)
	if err != nil {
		return false
	}

	// Try comparing with the local address on the socket first, but only if
	// it's actually specified.
	addr, err := net.ResolveUDPAddr("udp", local)
	if err == nil && addr.IP != nil && !addr.IP.IsUnspecified() {
		return addr.IP.Equal(localRemoteAddr.IP)
	}

	// Fallback to checking IPs of all interfaces
	addrs, err := net.InterfaceAddrs()
	if err != nil {
		return false
	}
	for _, addr := range addrs {
		ip, _, err := net.ParseCIDR(addr.String())
		if err != nil {
			continue
		}
		if ip.Equal(localRemoteAddr.IP) {
			return true
		}
	}
	return false
}

func sendBindingReq(conn net.PacketConn, addr net.Addr, softwareName string) (*packet, error) {
	// Construct packet.
	packet := newPacket()
	packet.types = type_BINDING_REQUEST
	attribute := newSoftwareAttribute(packet, softwareName)
	packet.addAttribute(*attribute)
	attribute = newFingerprintAttribute(packet)
	packet.addAttribute(*attribute)
	// Send packet.
	packet, err := packet.send(conn, addr)
	if err != nil {
		return nil, err
	}
	return packet, nil
}

func sendChangeReq(conn net.PacketConn, addr net.Addr, softwareName string, changeIP bool, changePort bool) (*packet, error) {
	// Construct packet.
	packet := newPacket()
	packet.types = type_BINDING_REQUEST
	attribute := newSoftwareAttribute(packet, softwareName)
	packet.addAttribute(*attribute)
	attribute = newChangeReqAttribute(packet, changeIP, changePort)
	packet.addAttribute(*attribute)
	attribute = newFingerprintAttribute(packet)
	packet.addAttribute(*attribute)
	// Send packet.
	packet, err := packet.send(conn, addr)
	if err != nil {
		return nil, err
	}
	return packet, nil
}

func test1(conn net.PacketConn, addr net.Addr, softwareName string) (*packet, net.Addr, bool, *Host, error) {
	packet, err := sendBindingReq(conn, addr, softwareName)
	if err != nil {
		return nil, nil, false, nil, err
	}
	if packet == nil {
		return nil, nil, false, nil, nil
	}

	// RFC 3489 doesn't require the server return XOR mapped address.
	hostMappedAddr := packet.xorMappedAddr()
	if hostMappedAddr == nil {
		hostMappedAddr = packet.mappedAddr()
		if hostMappedAddr == nil {
			return nil, nil, false, nil, errors.New("No mapped address.")
		}
	}

	hostChangedAddr := packet.changedAddr()
	if hostChangedAddr == nil {
		return nil, nil, false, nil, errors.New("No changed address.")
	}
	changeAddrStr := hostChangedAddr.TransportAddr()
	changeAddr, err := net.ResolveUDPAddr("udp", changeAddrStr)
	if err != nil {
		return nil, nil, false, nil, errors.New("Failed to resolve changed address.")
	}
	identical := isLocalAddress(conn.LocalAddr().String(), hostMappedAddr.TransportAddr())
	return packet, changeAddr, identical, hostMappedAddr, nil
}

func test2(conn net.PacketConn, addr net.Addr, softwareName string) (*packet, error) {
	return sendChangeReq(conn, addr, softwareName, true, true)
}

func test3(conn net.PacketConn, addr net.Addr, softwareName string) (*packet, error) {
	return sendChangeReq(conn, addr, softwareName, false, true)
}

// Follow RFC 3489 and RFC 5389.
// Figure 2: Flow for type discovery process (from RFC 3489).
//                        +--------+
//                        |  Test  |
//                        |   I    |
//                        +--------+
//                             |
//                             |
//                             V
//                            /\              /\
//                         N /  \ Y          /  \ Y             +--------+
//          UDP     <-------/Resp\--------->/ IP \------------->|  Test  |
//          Blocked         \ ?  /          \Same/              |   II   |
//                           \  /            \? /               +--------+
//                            \/              \/                    |
//                                             | N                  |
//                                             |                    V
//                                             V                    /\
//                                         +--------+  Sym.      N /  \
//                                         |  Test  |  UDP    <---/Resp\
//                                         |   II   |  Firewall   \ ?  /
//                                         +--------+              \  /
//                                             |                    \/
//                                             V                     |Y
//                  /\                         /\                    |
//   Symmetric  N  /  \       +--------+   N  /  \                   V
//      NAT  <--- / IP \<-----|  Test  |<--- /Resp\               Open
//                \Same/      |   I    |     \ ?  /               Internet
//                 \? /       +--------+      \  /
//                  \/                         \/
//                  |Y                          |Y
//                  |                           |
//                  |                           V
//                  |                           Full
//                  |                           Cone
//                  V              /\
//              +--------+        /  \ Y
//              |  Test  |------>/Resp\---->Restricted
//              |   III  |       \ ?  /
//              +--------+        \  /
//                                 \/
//                                  |N
//                                  |       Port
//                                  +------>Restricted
func discover(conn net.PacketConn, addr net.Addr, softwareName string) (NATType, *Host, error) {
	packet, changeAddr, identical, host, err := test1(conn, addr, softwareName)
	if err != nil {
		return NAT_ERROR, nil, err
	}
	if packet == nil {
		return NAT_BLOCKED, nil, nil
	}
	packet, err = test2(conn, addr, softwareName)
	if err != nil {
		return NAT_ERROR, host, err
	}
	if identical {
		if packet == nil {
			return NAT_SYMETRIC_UDP_FIREWALL, host, nil
		}
		return NAT_NONE, host, nil
	}
	if packet != nil {
		return NAT_FULL, host, nil
	}

	otherConn, err := net.ListenUDP("udp", nil)
	if err != nil {
		return NAT_ERROR, nil, err
	}

	packet, _, identical, _, err = test1(otherConn, changeAddr, softwareName)
	if err != nil {
		return NAT_ERROR, host, err
	}
	if packet == nil {
		// It should be NAT_BLOCKED, but will be detected in the first
		// step. So this will never happen.
		return NAT_UNKNOWN, host, nil
	}
	if identical {
		packet, err = test3(conn, addr, softwareName)
		if err != nil {
			return NAT_ERROR, host, err
		}
		if packet == nil {
			return NAT_PORT_RESTRICTED, host, nil
		}
		return NAT_RESTRICTED, host, nil
	}
	return NAT_SYMETRIC, host, nil
}
<commit_msg>allow non-changed addr in test1 (fix #9)<commit_after>// Copyright 2013, Cong Ding. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: Cong Ding <dinggnu@gmail.com>

package stun

import (
	"errors"
	"net"
)

// Padding the length of the byte slice to multiple of 4.
func padding(bytes []byte) []byte {
	length := uint16(len(bytes))
	return append(bytes, make([]byte, align(length)-length)...)
}

// Align the uint16 number to the smallest multiple of 4, which is larger than
// or equal to the uint16 number.
func align(n uint16) uint16 {
	return (n + 3) & 0xfffc
}

func isLocalAddress(local, localRemote string) bool {
	// Resolve the IP returned by the STUN server first.
	localRemoteAddr, err := net.ResolveUDPAddr("udp", localRemote)
	if err != nil {
		return false
	}

	// Try comparing with the local address on the socket first, but only if
	// it's actually specified.
	addr, err := net.ResolveUDPAddr("udp", local)
	if err == nil && addr.IP != nil && !addr.IP.IsUnspecified() {
		return addr.IP.Equal(localRemoteAddr.IP)
	}

	// Fallback to checking IPs of all interfaces
	addrs, err := net.InterfaceAddrs()
	if err != nil {
		return false
	}
	for _, addr := range addrs {
		ip, _, err := net.ParseCIDR(addr.String())
		if err != nil {
			continue
		}
		if ip.Equal(localRemoteAddr.IP) {
			return true
		}
	}
	return false
}

func sendBindingReq(conn net.PacketConn, addr net.Addr, softwareName string) (*packet, error) {
	// Construct packet.
	packet := newPacket()
	packet.types = type_BINDING_REQUEST
	attribute := newSoftwareAttribute(packet, softwareName)
	packet.addAttribute(*attribute)
	attribute = newFingerprintAttribute(packet)
	packet.addAttribute(*attribute)
	// Send packet.
	packet, err := packet.send(conn, addr)
	if err != nil {
		return nil, err
	}
	return packet, nil
}

func sendChangeReq(conn net.PacketConn, addr net.Addr, softwareName string, changeIP bool, changePort bool) (*packet, error) {
	// Construct packet.
	packet := newPacket()
	packet.types = type_BINDING_REQUEST
	attribute := newSoftwareAttribute(packet, softwareName)
	packet.addAttribute(*attribute)
	attribute = newChangeReqAttribute(packet, changeIP, changePort)
	packet.addAttribute(*attribute)
	attribute = newFingerprintAttribute(packet)
	packet.addAttribute(*attribute)
	// Send packet.
	packet, err := packet.send(conn, addr)
	if err != nil {
		return nil, err
	}
	return packet, nil
}

func test1(conn net.PacketConn, addr net.Addr, softwareName string) (*packet, net.Addr, bool, *Host, error) {
	packet, err := sendBindingReq(conn, addr, softwareName)
	if err != nil {
		return nil, nil, false, nil, err
	}
	if packet == nil {
		return nil, nil, false, nil, nil
	}

	// RFC 3489 doesn't require the server return XOR mapped address.
	hostMappedAddr := packet.xorMappedAddr()
	if hostMappedAddr == nil {
		hostMappedAddr = packet.mappedAddr()
		if hostMappedAddr == nil {
			return nil, nil, false, nil, errors.New("No mapped address.")
		}
	}

	identical := isLocalAddress(conn.LocalAddr().String(), hostMappedAddr.TransportAddr())

	hostChangedAddr := packet.changedAddr()
	if hostChangedAddr == nil {
		return packet, nil, identical, hostMappedAddr, nil
	}
	changeAddrStr := hostChangedAddr.TransportAddr()
	changeAddr, err := net.ResolveUDPAddr("udp", changeAddrStr)
	if err != nil {
		return nil, nil, false, nil, errors.New("Failed to resolve changed address.")
	}
	return packet, changeAddr, identical, hostMappedAddr, nil
}

func test2(conn net.PacketConn, addr net.Addr, softwareName string) (*packet, error) {
	return sendChangeReq(conn, addr, softwareName, true, true)
}

func test3(conn net.PacketConn, addr net.Addr, softwareName string) (*packet, error) {
	return sendChangeReq(conn, addr, softwareName, false, true)
}

// Follow RFC 3489 and RFC 5389.
// Figure 2: Flow for type discovery process (from RFC 3489).
//                        +--------+
//                        |  Test  |
//                        |   I    |
//                        +--------+
//                             |
//                             |
//                             V
//                            /\              /\
//                         N /  \ Y          /  \ Y             +--------+
//          UDP     <-------/Resp\--------->/ IP \------------->|  Test  |
//          Blocked         \ ?  /          \Same/              |   II   |
//                           \  /            \? /               +--------+
//                            \/              \/                    |
//                                             | N                  |
//                                             |                    V
//                                             V                    /\
//                                         +--------+  Sym.      N /  \
//                                         |  Test  |  UDP    <---/Resp\
//                                         |   II   |  Firewall   \ ?  /
//                                         +--------+              \  /
//                                             |                    \/
//                                             V                     |Y
//                  /\                         /\                    |
//   Symmetric  N  /  \       +--------+   N  /  \                   V
//      NAT  <--- / IP \<-----|  Test  |<--- /Resp\               Open
//                \Same/      |   I    |     \ ?  /               Internet
//                 \? /       +--------+      \  /
//                  \/                         \/
//                  |Y                          |Y
//                  |                           |
//                  |                           V
//                  |                           Full
//                  |                           Cone
//                  V              /\
//              +--------+        /  \ Y
//              |  Test  |------>/Resp\---->Restricted
//              |   III  |       \ ?  /
//              +--------+        \  /
//                                 \/
//                                  |N
//                                  |       Port
//                                  +------>Restricted
func discover(conn net.PacketConn, addr net.Addr, softwareName string) (NATType, *Host, error) {
	packet, changeAddr, identical, host, err := test1(conn, addr, softwareName)
	if err != nil {
		return NAT_ERROR, nil, err
	}
	if packet == nil {
		return NAT_BLOCKED, nil, nil
	}
	packet, err = test2(conn, addr, softwareName)
	if err != nil {
		return NAT_ERROR, host, err
	}
	if identical {
		if packet == nil {
			return NAT_SYMETRIC_UDP_FIREWALL, host, nil
		}
		return NAT_NONE, host, nil
	}
	if packet != nil {
		return NAT_FULL, host, nil
	}

	otherConn, err := net.ListenUDP("udp", nil)
	if err != nil {
		return NAT_ERROR, nil, err
	}

	if changeAddr == nil {
		return NAT_ERROR, host, errors.New("No changed address.")
	}

	packet, _, identical, _, err = test1(otherConn, changeAddr, softwareName)
	if err != nil {
		return NAT_ERROR, host, err
	}
	if packet == nil {
		// It should be NAT_BLOCKED, but will be detected in the first
		// step. So this will never happen.
		return NAT_UNKNOWN, host, nil
	}
	if identical {
		packet, err = test3(conn, addr, softwareName)
		if err != nil {
			return NAT_ERROR, host, err
		}
		if packet == nil {
			return NAT_PORT_RESTRICTED, host, nil
		}
		return NAT_RESTRICTED, host, nil
	}
	return NAT_SYMETRIC, host, nil
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"fmt"
	"os"
	"path/filepath"

	"github.com/restic/restic/internal/debug"
	"github.com/restic/restic/internal/errors"
	"github.com/restic/restic/internal/restic"

	"github.com/spf13/cobra"
)

var cmdCatFile = &cobra.Command{
	Use:   "catfile [flags] file snapshotID",
	Short: "Print a backed-up file to stdout",
	Long: `
The "catfile" command extracts a single file from a snapshot from the repository and
prints its contents to stdout.

The special snapshot "latest" can be used to use the latest snapshot in the
repository.
`,
	DisableAutoGenTag: true,
	RunE: func(cmd *cobra.Command, args []string) error {
		return runCatFile(catFileOptions, globalOptions, args)
	},
}

// CatFileOptions collects all options for the catfile command.
type CatFileOptions struct {
	Host  string
	Paths []string
	Tags  restic.TagLists
}

var catFileOptions CatFileOptions

func init() {
	cmdRoot.AddCommand(cmdCatFile)

	flags := cmdCatFile.Flags()
	flags.StringVarP(&catFileOptions.Host, "host", "H", "", `only consider snapshots for this host when the snapshot ID is "latest"`)
	flags.Var(&catFileOptions.Tags, "tag", "only consider snapshots which include this `taglist` for snapshot ID \"latest\"")
	flags.StringArrayVar(&catFileOptions.Paths, "path", nil, "only consider snapshots which include this (absolute) `path` for snapshot ID \"latest\"")
}

func splitPath(path string) []string {
	d, f := filepath.Split(path)
	if d == "" {
		return []string{f}
	}
	s := splitPath(filepath.Clean(d))
	return append(s, f)
}

func catNode(ctx context.Context, repo restic.Repository, node *restic.Node) error {
	var buf []byte
	for _, id := range node.Content {
		size, err := repo.LookupBlobSize(id, restic.DataBlob)
		if err != nil {
			return err
		}

		buf = buf[:cap(buf)]
		if len(buf) < restic.CiphertextLength(int(size)) {
			buf = restic.NewBlobBuffer(int(size))
		}

		n, err := repo.LoadBlob(ctx, restic.DataBlob, id, buf)
		if err != nil {
			return err
		}
		buf = buf[:n]

		_, err = os.Stdout.Write(buf)
		if err != nil {
			return errors.Wrap(err, "Write")
		}
	}
	return nil
}

func printFromTree(ctx context.Context, tree *restic.Tree, repo restic.Repository, prefix string, pathComponents []string) error {
	if tree == nil {
		return fmt.Errorf("called with a nil tree")
	}
	if repo == nil {
		return fmt.Errorf("called with a nil repository")
	}
	l := len(pathComponents)
	if l == 0 {
		return fmt.Errorf("empty path components")
	}
	item := filepath.Join(prefix, pathComponents[0])
	for _, node := range tree.Nodes {
		if node.Name == pathComponents[0] {
			switch {
			case l == 1 && node.Type == "file":
				return catNode(ctx, repo, node)
			case l > 1 && node.Type == "dir":
				subtree, err := repo.LoadTree(ctx, *node.Subtree)
				if err != nil {
					return errors.Wrapf(err, "cannot load subtree for %q", item)
				}
				return printFromTree(ctx, subtree, repo, item, pathComponents[1:])
			case l > 1:
				return fmt.Errorf("%q should be a dir, but s a %q", item, node.Type)
			case node.Type != "file":
				return fmt.Errorf("%q should be a file, but is a %q", item, node.Type)
			}
		}
	}
	return fmt.Errorf("path %q not found in snapshot", item)
}

func runCatFile(opts CatFileOptions, gopts GlobalOptions, args []string) error {
	ctx := gopts.ctx

	if len(args) != 2 {
		return errors.Fatal("no file and no snapshot ID specified")
	}

	pathToPrint := args[0]
	snapshotIDString := args[1]

	debug.Log("cat file %q from %q", pathToPrint, snapshotIDString)

	splittedPath := splitPath(pathToPrint)

	repo, err := OpenRepository(gopts)
	if err != nil {
		return err
	}

	if !gopts.NoLock {
		lock, err := lockRepo(repo)
		defer unlockRepo(lock)
		if err != nil {
			return err
		}
	}

	err = repo.LoadIndex(ctx)
	if err != nil {
		return err
	}

	var id restic.ID

	if snapshotIDString == "latest" {
		id, err = restic.FindLatestSnapshot(ctx, repo, opts.Paths, opts.Tags, opts.Host)
		if err != nil {
			Exitf(1, "latest snapshot for criteria not found: %v Paths:%v Host:%v", err, opts.Paths, opts.Host)
		}
	} else {
		id, err = restic.FindSnapshot(repo, snapshotIDString)
		if err != nil {
			Exitf(1, "invalid id %q: %v", snapshotIDString, err)
		}
	}

	sn, err := restic.LoadSnapshot(context.TODO(), repo, id)
	if err != nil {
		Exitf(2, "loading snapshot %q failed: %v", snapshotIDString, err)
	}

	tree, err := repo.LoadTree(ctx, *sn.Tree)
	if err != nil {
		Exitf(2, "loading tree for snapshot %q failed: %v", snapshotIDString, err)
	}

	err = printFromTree(ctx, tree, repo, "", splittedPath)
	if err != nil {
		Exitf(2, "cannot cat file: %v", err)
	}

	return nil
}
<commit_msg>Rename subcommand catfile to dump<commit_after>package main

import (
	"context"
	"fmt"
	"os"
	"path/filepath"

	"github.com/restic/restic/internal/debug"
	"github.com/restic/restic/internal/errors"
	"github.com/restic/restic/internal/restic"

	"github.com/spf13/cobra"
)

var cmdDump = &cobra.Command{
	Use:   "dump [flags] snapshotID file",
	Short: "Print a backed-up file to stdout",
	Long: `
The "dump" command extracts a single file from a snapshot from the repository and
prints its contents to stdout.

The special snapshot "latest" can be used to use the latest snapshot in the
repository.
`,
	DisableAutoGenTag: true,
	RunE: func(cmd *cobra.Command, args []string) error {
		return runDump(dumpOptions, globalOptions, args)
	},
}

// DumpOptions collects all options for the dump command.
type DumpOptions struct {
	Host  string
	Paths []string
	Tags  restic.TagLists
}

var dumpOptions DumpOptions

func init() {
	cmdRoot.AddCommand(cmdDump)

	flags := cmdDump.Flags()
	flags.StringVarP(&dumpOptions.Host, "host", "H", "", `only consider snapshots for this host when the snapshot ID is "latest"`)
	flags.Var(&dumpOptions.Tags, "tag", "only consider snapshots which include this `taglist` for snapshot ID \"latest\"")
	flags.StringArrayVar(&dumpOptions.Paths, "path", nil, "only consider snapshots which include this (absolute) `path` for snapshot ID \"latest\"")
}

func splitPath(path string) []string {
	d, f := filepath.Split(path)
	if d == "" {
		return []string{f}
	}
	s := splitPath(filepath.Clean(d))
	return append(s, f)
}

func dumpNode(ctx context.Context, repo restic.Repository, node *restic.Node) error {
	var buf []byte
	for _, id := range node.Content {
		size, err := repo.LookupBlobSize(id, restic.DataBlob)
		if err != nil {
			return err
		}

		buf = buf[:cap(buf)]
		if len(buf) < restic.CiphertextLength(int(size)) {
			buf = restic.NewBlobBuffer(int(size))
		}

		n, err := repo.LoadBlob(ctx, restic.DataBlob, id, buf)
		if err != nil {
			return err
		}
		buf = buf[:n]

		_, err = os.Stdout.Write(buf)
		if err != nil {
			return errors.Wrap(err, "Write")
		}
	}
	return nil
}

func printFromTree(ctx context.Context, tree *restic.Tree, repo restic.Repository, prefix string, pathComponents []string) error {
	if tree == nil {
		return fmt.Errorf("called with a nil tree")
	}
	if repo == nil {
		return fmt.Errorf("called with a nil repository")
	}
	l := len(pathComponents)
	if l == 0 {
		return fmt.Errorf("empty path components")
	}
	item := filepath.Join(prefix, pathComponents[0])
	for _, node := range tree.Nodes {
		if node.Name == pathComponents[0] {
			switch {
			case l == 1 && node.Type == "file":
				return dumpNode(ctx, repo, node)
			case l > 1 && node.Type == "dir":
				subtree, err := repo.LoadTree(ctx, *node.Subtree)
				if err != nil {
					return errors.Wrapf(err, "cannot load subtree for %q", item)
				}
				return printFromTree(ctx, subtree, repo, item, pathComponents[1:])
			case l > 1:
				return fmt.Errorf("%q should be a dir, but s a %q", item, node.Type)
			case node.Type != "file":
				return fmt.Errorf("%q should be a file, but is a %q", item, node.Type)
			}
		}
	}
	return fmt.Errorf("path %q not found in snapshot", item)
}

func runDump(opts DumpOptions, gopts GlobalOptions, args []string) error {
	ctx := gopts.ctx

	if len(args) != 2 {
		return errors.Fatal("no file and no snapshot ID specified")
	}

	snapshotIDString := args[0]
	pathToPrint := args[1]

	debug.Log("dump file %q from %q", pathToPrint, snapshotIDString)

	splittedPath := splitPath(pathToPrint)

	repo, err := OpenRepository(gopts)
	if err != nil {
		return err
	}

	if !gopts.NoLock {
		lock, err := lockRepo(repo)
		defer unlockRepo(lock)
		if err != nil {
			return err
		}
	}

	err = repo.LoadIndex(ctx)
	if err != nil {
		return err
	}

	var id restic.ID

	if snapshotIDString == "latest" {
		id, err = restic.FindLatestSnapshot(ctx, repo, opts.Paths, opts.Tags, opts.Host)
		if err != nil {
			Exitf(1, "latest snapshot for criteria not found: %v Paths:%v Host:%v", err, opts.Paths, opts.Host)
		}
	} else {
		id, err = restic.FindSnapshot(repo, snapshotIDString)
		if err != nil {
			Exitf(1, "invalid id %q: %v", snapshotIDString, err)
		}
	}

	sn, err := restic.LoadSnapshot(context.TODO(), repo, id)
	if err != nil {
		Exitf(2, "loading snapshot %q failed: %v", snapshotIDString, err)
	}

	tree, err := repo.LoadTree(ctx, *sn.Tree)
	if err != nil {
		Exitf(2, "loading tree for snapshot %q failed: %v", snapshotIDString, err)
	}

	err = printFromTree(ctx, tree, repo, "", splittedPath)
	if err != nil {
		Exitf(2, "cannot dump file: %v", err)
	}

	return nil
}
<|endoftext|>


<commit_before>package app

import (
	"context"
	"net/http"
	"os"

	"github.com/rancher/norman/pkg/k8scheck"
	"github.com/rancher/rancher/pkg/audit"
	"github.com/rancher/rancher/pkg/auth/providerrefresh"
	"github.com/rancher/rancher/pkg/auth/providers/common"
	"github.com/rancher/rancher/pkg/auth/tokens"
	"github.com/rancher/rancher/pkg/clustermanager"
	managementController "github.com/rancher/rancher/pkg/controllers/management"
	"github.com/rancher/rancher/pkg/cron"
	"github.com/rancher/rancher/pkg/dialer"
	"github.com/rancher/rancher/pkg/features"
	"github.com/rancher/rancher/pkg/jailer"
	"github.com/rancher/rancher/pkg/metrics"
	"github.com/rancher/rancher/pkg/rbac"
	"github.com/rancher/rancher/pkg/settings"
	"github.com/rancher/rancher/pkg/steve"
	"github.com/rancher/rancher/pkg/telemetry"
	"github.com/rancher/rancher/pkg/tls"
	"github.com/rancher/rancher/pkg/tunnelserver"
	"github.com/rancher/rancher/pkg/wrangler"
	"github.com/rancher/rancher/server"
	"github.com/rancher/remotedialer"
	"github.com/rancher/steve/pkg/accesscontrol"
	"github.com/rancher/steve/pkg/auth"
	steveserver "github.com/rancher/steve/pkg/server"
	"github.com/rancher/types/config"
	"github.com/rancher/wrangler/pkg/crd"
	"github.com/rancher/wrangler/pkg/leader"
	"github.com/sirupsen/logrus"
	"github.com/urfave/cli"
	"k8s.io/client-go/rest"
)

type Config struct {
	ACMEDomains       cli.StringSlice
	AddLocal          string
	Embedded          bool
	HTTPListenPort    int
	HTTPSListenPort   int
	K8sMode           string
	Debug             bool
	NoCACerts         bool
	AuditLogPath      string
	AuditLogMaxage    int
	AuditLogMaxsize   int
	AuditLogMaxbackup int
	AuditLevel        int
	Features          string
}

type Rancher struct {
	Config          Config
	AccessSetLookup accesscontrol.AccessSetLookup
	Handler         http.Handler
	Auth            auth.Middleware
	ScaledContext   *config.ScaledContext
	WranglerContext *wrangler.Context
	ClusterManager  *clustermanager.Manager
}

func (r *Rancher) ListenAndServe(ctx context.Context) error {
	if err := r.Start(ctx); err != nil {
		return err
	}

	if err := tls.ListenAndServe(ctx, &r.ScaledContext.RESTConfig,
		r.Handler,
		r.Config.HTTPSListenPort,
		r.Config.HTTPListenPort,
		r.Config.ACMEDomains,
		r.Config.NoCACerts); err != nil {
		return err
	}

	<-ctx.Done()
	return ctx.Err()
}

func initFeatures(ctx context.Context, scaledContext *config.ScaledContext, cfg *Config) error {
	factory, err := crd.NewFactoryFromClient(&scaledContext.RESTConfig)
	if err != nil {
		return err
	}

	if _, err := factory.CreateCRDs(ctx, crd.NonNamespacedType("Feature.management.cattle.io/v3")); err != nil {
		return err
	}

	scaledContext.Management.Features("").Controller()
	if err := scaledContext.Start(ctx); err != nil {
		return err
	}
	features.InitializeFeatures(scaledContext, cfg.Features)
	return nil
}

func buildScaledContext(ctx context.Context, kubeConfig rest.Config, cfg *Config) (*config.ScaledContext, *clustermanager.Manager, error) {
	scaledContext, err := config.NewScaledContext(kubeConfig)
	if err != nil {
		return nil, nil, err
	}

	if err := initFeatures(ctx, scaledContext, cfg); err != nil {
		return nil, nil, err
	}

	if err := k8scheck.Wait(ctx, kubeConfig); err != nil {
		return nil, nil, err
	}

	dialerFactory, err := dialer.NewFactory(scaledContext)
	if err != nil {
		return nil, nil, err
	}

	scaledContext.Dialer = dialerFactory
	scaledContext.PeerManager, err = tunnelserver.NewPeerManager(ctx, scaledContext, dialerFactory.TunnelServer)
	if err != nil {
		return nil, nil, err
	}

	manager := clustermanager.NewManager(cfg.HTTPSListenPort, scaledContext)
	scaledContext.AccessControl = manager
	scaledContext.ClientGetter = manager

	userManager, err := common.NewUserManager(scaledContext)
	if err != nil {
		return nil, nil, err
	}

	scaledContext.UserManager = userManager
	scaledContext.RunContext = ctx

	return scaledContext, manager, nil
}

func New(ctx context.Context, restConfig *rest.Config, cfg *Config) (*Rancher, error) {
	scaledContext, clusterManager, err := buildScaledContext(ctx, *restConfig, cfg)
	if err != nil {
		return nil, err
	}

	var tunnelServer *remotedialer.Server
	if df, ok := scaledContext.Dialer.(*dialer.Factory); ok {
		tunnelServer = df.TunnelServer
	}

	wranglerContext, err := wrangler.NewContext(steveserver.RestConfigDefaults(&scaledContext.RESTConfig), tunnelServer)
	if err != nil {
		return nil, err
	}

	asl := accesscontrol.NewAccessStore(ctx, features.Steve.Enabled(), wranglerContext.RBAC)

	auditLogWriter := audit.NewLogWriter(cfg.AuditLogPath, cfg.AuditLevel, cfg.AuditLogMaxage, cfg.AuditLogMaxbackup, cfg.AuditLogMaxsize)

	authMiddleware, handler, err := server.Start(ctx, localClusterEnabled(*cfg), scaledContext, clusterManager, auditLogWriter, rbac.NewAccessControlHandler(asl))
	if err != nil {
		return nil, err
	}

	if os.Getenv("CATTLE_PROMETHEUS_METRICS") == "true" {
		metrics.Register(ctx, scaledContext)
	}

	if auditLogWriter != nil {
		go func() {
			<-ctx.Done()
			auditLogWriter.Output.Close()
		}()
	}

	rancher := &Rancher{
		AccessSetLookup: asl,
		Config:          *cfg,
		Handler:         handler,
		Auth:            authMiddleware,
		ScaledContext:   scaledContext,
		WranglerContext: wranglerContext,
		ClusterManager:  clusterManager,
	}

	return rancher, nil
}

func (r *Rancher) Start(ctx context.Context) error {
	if err := r.ScaledContext.Start(ctx); err != nil {
		return err
	}

	if err := r.WranglerContext.Start(ctx); err != nil {
		return err
	}

	if dm := os.Getenv("CATTLE_DEV_MODE"); dm == "" {
		if err := jailer.CreateJail("driver-jail"); err != nil {
			return err
		}

		if err := cron.StartJailSyncCron(r.ScaledContext); err != nil {
			return err
		}
	}

	go leader.RunOrDie(ctx, "", "cattle-controllers", r.ScaledContext.K8sClient, func(ctx context.Context) {
		if r.ScaledContext.PeerManager != nil {
			r.ScaledContext.PeerManager.Leader()
		}

		management, err := r.ScaledContext.NewManagementContext()
		if err != nil {
			panic(err)
		}

		managementController.Register(ctx, management, r.ScaledContext.ClientGetter.(*clustermanager.Manager))
		if err := management.Start(ctx); err != nil {
			panic(err)
		}

		managementController.RegisterWrangler(ctx, r.WranglerContext, management, r.ScaledContext.ClientGetter.(*clustermanager.Manager))
		if err := r.WranglerContext.Start(ctx); err != nil {
			panic(err)
		}

		if err := addData(management, r.Config); err != nil {
			panic(err)
		}

		if err := telemetry.Start(ctx, r.Config.HTTPSListenPort, r.ScaledContext); err != nil {
			panic(err)
		}

		tokens.StartPurgeDaemon(ctx, management)
		cronTime := settings.AuthUserInfoResyncCron.Get()
		maxAge := settings.AuthUserInfoMaxAgeSeconds.Get()
		providerrefresh.StartRefreshDaemon(ctx, r.ScaledContext, management, cronTime, maxAge)
		cleanupOrphanedSystemUsers(ctx, management)
		logrus.Infof("Rancher startup complete")

		<-ctx.Done()
	})

	if features.Steve.Enabled() {
		handler, err := newSteve(ctx, r)
		if err != nil {
			return err
		}
		r.Handler = handler
	}

	return nil
}

func addData(management *config.ManagementContext, cfg Config) error {
	adminName, err := addRoles(management)
	if err != nil {
		return err
	}

	if localClusterEnabled(cfg) {
		if err := addLocalCluster(cfg.Embedded, adminName, management); err != nil {
			return err
		}
	} else if cfg.AddLocal == "false" {
		if err := removeLocalCluster(management); err != nil {
			return err
		}
	}

	if err := addAuthConfigs(management); err != nil {
		return err
	}

	if err := syncCatalogs(management); err != nil {
		return err
	}

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

	if err := addDefaultPodSecurityPolicyTemplates(management); err != nil {
		return err
	}

	if err := addKontainerDrivers(management); err != nil {
		return err
	}

	if err := addCattleGlobalNamespaces(management); err != nil {
		return err
	}

	return addMachineDrivers(management)
}

func localClusterEnabled(cfg Config) bool {
	if cfg.AddLocal == "true" || (cfg.AddLocal == "auto" && !cfg.Embedded) {
		return true
	}
	return false
}

func newSteve(ctx context.Context, rancher *Rancher) (http.Handler, error) {
	cfg := steveserver.Server{
		AccessSetLookup: rancher.AccessSetLookup,
		Controllers:     rancher.WranglerContext.Controllers,
		RestConfig:      steveserver.RestConfigDefaults(&rancher.ScaledContext.RESTConfig),
		AuthMiddleware:  rancher.Auth,
		Next:            rancher.Handler,
		StartHooks: []steveserver.StartHook{
			func(ctx context.Context, server *steveserver.Server) error {
				return steve.Setup(server, rancher.WranglerContext)
			},
		},
	}

	return cfg.Handler(ctx)
}
<commit_msg>Move k8s start check to the very beginning<commit_after>package app

import (
	"context"
	"net/http"
	"os"

	"github.com/rancher/norman/pkg/k8scheck"
	"github.com/rancher/rancher/pkg/audit"
	"github.com/rancher/rancher/pkg/auth/providerrefresh"
	"github.com/rancher/rancher/pkg/auth/providers/common"
	"github.com/rancher/rancher/pkg/auth/tokens"
	"github.com/rancher/rancher/pkg/clustermanager"
	managementController "github.com/rancher/rancher/pkg/controllers/management"
	"github.com/rancher/rancher/pkg/cron"
	"github.com/rancher/rancher/pkg/dialer"
	"github.com/rancher/rancher/pkg/features"
	"github.com/rancher/rancher/pkg/jailer"
	"github.com/rancher/rancher/pkg/metrics"
	"github.com/rancher/rancher/pkg/rbac"
	"github.com/rancher/rancher/pkg/settings"
	"github.com/rancher/rancher/pkg/steve"
	"github.com/rancher/rancher/pkg/telemetry"
	"github.com/rancher/rancher/pkg/tls"
	"github.com/rancher/rancher/pkg/tunnelserver"
	"github.com/rancher/rancher/pkg/wrangler"
	"github.com/rancher/rancher/server"
	"github.com/rancher/remotedialer"
	"github.com/rancher/steve/pkg/accesscontrol"
	"github.com/rancher/steve/pkg/auth"
	steveserver "github.com/rancher/steve/pkg/server"
	"github.com/rancher/types/config"
	"github.com/rancher/wrangler/pkg/crd"
	"github.com/rancher/wrangler/pkg/leader"
	"github.com/sirupsen/logrus"
	"github.com/urfave/cli"
	"k8s.io/client-go/rest"
)

type Config struct {
	ACMEDomains       cli.StringSlice
	AddLocal          string
	Embedded          bool
	HTTPListenPort    int
	HTTPSListenPort   int
	K8sMode           string
	Debug             bool
	NoCACerts         bool
	AuditLogPath      string
	AuditLogMaxage    int
	AuditLogMaxsize   int
	AuditLogMaxbackup int
	AuditLevel        int
	Features          string
}

type Rancher struct {
	Config          Config
	AccessSetLookup accesscontrol.AccessSetLookup
	Handler         http.Handler
	Auth            auth.Middleware
	ScaledContext   *config.ScaledContext
	WranglerContext *wrangler.Context
	ClusterManager  *clustermanager.Manager
}

func (r *Rancher) ListenAndServe(ctx context.Context) error {
	if err := r.Start(ctx); err != nil {
		return err
	}

	if err := tls.ListenAndServe(ctx, &r.ScaledContext.RESTConfig,
		r.Handler,
		r.Config.HTTPSListenPort,
		r.Config.HTTPListenPort,
		r.Config.ACMEDomains,
		r.Config.NoCACerts); err != nil {
		return err
	}

	<-ctx.Done()
	return ctx.Err()
}

func initFeatures(ctx context.Context, scaledContext *config.ScaledContext, cfg *Config) error {
	factory, err := crd.NewFactoryFromClient(&scaledContext.RESTConfig)
	if err != nil {
		return err
	}

	if _, err := factory.CreateCRDs(ctx, crd.NonNamespacedType("Feature.management.cattle.io/v3")); err != nil {
		return err
	}

	scaledContext.Management.Features("").Controller()
	if err := scaledContext.Start(ctx); err != nil {
		return err
	}
	features.InitializeFeatures(scaledContext, cfg.Features)
	return nil
}

func buildScaledContext(ctx context.Context, kubeConfig rest.Config, cfg *Config) (*config.ScaledContext, *clustermanager.Manager, error) {
	if err := k8scheck.Wait(ctx, kubeConfig); err != nil {
		return nil, nil, err
	}

	scaledContext, err := config.NewScaledContext(kubeConfig)
	if err != nil {
		return nil, nil, err
	}

	if err := initFeatures(ctx, scaledContext, cfg); err != nil {
		return nil, nil, err
	}

	dialerFactory, err := dialer.NewFactory(scaledContext)
	if err != nil {
		return nil, nil, err
	}

	scaledContext.Dialer = dialerFactory
	scaledContext.PeerManager, err = tunnelserver.NewPeerManager(ctx, scaledContext, dialerFactory.TunnelServer)
	if err != nil {
		return nil, nil, err
	}

	manager := clustermanager.NewManager(cfg.HTTPSListenPort, scaledContext)
	scaledContext.AccessControl = manager
	scaledContext.ClientGetter = manager

	userManager, err := common.NewUserManager(scaledContext)
	if err != nil {
		return nil, nil, err
	}

	scaledContext.UserManager = userManager
	scaledContext.RunContext = ctx

	return scaledContext, manager, nil
}

func New(ctx context.Context, restConfig *rest.Config, cfg *Config) (*Rancher, error) {
	scaledContext, clusterManager, err := buildScaledContext(ctx, *restConfig, cfg)
	if err != nil {
		return nil, err
	}

	var tunnelServer *remotedialer.Server
	if df, ok := scaledContext.Dialer.(*dialer.Factory); ok {
		tunnelServer = df.TunnelServer
	}

	wranglerContext, err := wrangler.NewContext(steveserver.RestConfigDefaults(&scaledContext.RESTConfig), tunnelServer)
	if err != nil {
		return nil, err
	}

	asl := accesscontrol.NewAccessStore(ctx, features.Steve.Enabled(), wranglerContext.RBAC)

	auditLogWriter := audit.NewLogWriter(cfg.AuditLogPath, cfg.AuditLevel, cfg.AuditLogMaxage, cfg.AuditLogMaxbackup, cfg.AuditLogMaxsize)

	authMiddleware, handler, err := server.Start(ctx, localClusterEnabled(*cfg), scaledContext, clusterManager, auditLogWriter, rbac.NewAccessControlHandler(asl))
	if err != nil {
		return nil, err
	}

	if os.Getenv("CATTLE_PROMETHEUS_METRICS") == "true" {
		metrics.Register(ctx, scaledContext)
	}

	if auditLogWriter != nil {
		go func() {
			<-ctx.Done()
			auditLogWriter.Output.Close()
		}()
	}

	rancher := &Rancher{
		AccessSetLookup: asl,
		Config:          *cfg,
		Handler:         handler,
		Auth:            authMiddleware,
		ScaledContext:   scaledContext,
		WranglerContext: wranglerContext,
		ClusterManager:  clusterManager,
	}

	return rancher, nil
}

func (r *Rancher) Start(ctx context.Context) error {
	if err := r.ScaledContext.Start(ctx); err != nil {
		return err
	}

	if err := r.WranglerContext.Start(ctx); err != nil {
		return err
	}

	if dm := os.Getenv("CATTLE_DEV_MODE"); dm == "" {
		if err := jailer.CreateJail("driver-jail"); err != nil {
			return err
		}

		if err := cron.StartJailSyncCron(r.ScaledContext); err != nil {
			return err
		}
	}

	go leader.RunOrDie(ctx, "", "cattle-controllers", r.ScaledContext.K8sClient, func(ctx context.Context) {
		if r.ScaledContext.PeerManager != nil {
			r.ScaledContext.PeerManager.Leader()
		}

		management, err := r.ScaledContext.NewManagementContext()
		if err != nil {
			panic(err)
		}

		managementController.Register(ctx, management, r.ScaledContext.ClientGetter.(*clustermanager.Manager))
		if err := management.Start(ctx); err != nil {
			panic(err)
		}

		managementController.RegisterWrangler(ctx, r.WranglerContext, management, r.ScaledContext.ClientGetter.(*clustermanager.Manager))
		if err := r.WranglerContext.Start(ctx); err != nil {
			panic(err)
		}

		if err := addData(management, r.Config); err != nil {
			panic(err)
		}

		if err := telemetry.Start(ctx, r.Config.HTTPSListenPort, r.ScaledContext); err != nil {
			panic(err)
		}

		tokens.StartPurgeDaemon(ctx, management)
		cronTime := settings.AuthUserInfoResyncCron.Get()
		maxAge := settings.AuthUserInfoMaxAgeSeconds.Get()
		providerrefresh.StartRefreshDaemon(ctx, r.ScaledContext, management, cronTime, maxAge)
		cleanupOrphanedSystemUsers(ctx, management)
		logrus.Infof("Rancher startup complete")

		<-ctx.Done()
	})

	if features.Steve.Enabled() {
		handler, err := newSteve(ctx, r)
		if err != nil {
			return err
		}
		r.Handler = handler
	}

	return nil
}

func addData(management *config.ManagementContext, cfg Config) error {
	adminName, err := addRoles(management)
	if err != nil {
		return err
	}

	if localClusterEnabled(cfg) {
		if err := addLocalCluster(cfg.Embedded, adminName, management); err != nil {
			return err
		}
	} else if cfg.AddLocal == "false" {
		if err := removeLocalCluster(management); err != nil {
			return err
		}
	}

	if err := addAuthConfigs(management); err != nil {
		return err
	}

	if err := syncCatalogs(management); err != nil {
		return err
	}

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

	if err := addDefaultPodSecurityPolicyTemplates(management); err != nil {
		return err
	}

	if err := addKontainerDrivers(management); err != nil {
		return err
	}

	if err := addCattleGlobalNamespaces(management); err != nil {
		return err
	}

	return addMachineDrivers(management)
}

func localClusterEnabled(cfg Config) bool {
	if cfg.AddLocal == "true" || (cfg.AddLocal == "auto" && !cfg.Embedded) {
		return true
	}
	return false
}

func newSteve(ctx context.Context, rancher *Rancher) (http.Handler, error) {
	cfg := steveserver.Server{
		AccessSetLookup: rancher.AccessSetLookup,
		Controllers:     rancher.WranglerContext.Controllers,
		RestConfig:      steveserver.RestConfigDefaults(&rancher.ScaledContext.RESTConfig),
		AuthMiddleware:  rancher.Auth,
		Next:            rancher.Handler,
		StartHooks: []steveserver.StartHook{
			func(ctx context.Context, server *steveserver.Server) error {
				return steve.Setup(server, rancher.WranglerContext)
			},
		},
	}

	return cfg.Handler(ctx)
}
<|endoftext|>


<commit_before>package queue
<commit_msg>queue package draft<commit_after>package queue

import "sync"

// Item struct is the basic queue item
type Item struct {
	Tag   string `json:"tag"`
	Value []byte `json:"value"`
}

// Data contains all data in the current queue
type Data struct {
	Tag      string          `json:"tag"`
	ItemList map[string]Item `json:"item"`
	control  queueControl
}

type queueControl struct {
	mutex *sync.Mutex
}

// New queue
func New() (q *Data, err error) {
	q = &Data{
		ItemList: make(map[string]Item),
		control:  queueControl{mutex: &sync.Mutex{}},
	}
	return
}

// Count items in the queue
func (q *Data) Count() int {
	return len(q.ItemList)
}
<|endoftext|>


<commit_before>// Copyright 2019 Google Inc.
//
// 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.

// Binary termdashdemo demonstrates the functionality of termdash and its various widgets.
// Exist when 'q' is pressed.
package main

import (
	"context"
	"fmt"
	"math"
	"math/rand"
	"time"

	"github.com/mum4k/termdash"
	"github.com/mum4k/termdash/cell"
	"github.com/mum4k/termdash/container"
	"github.com/mum4k/termdash/draw"
	"github.com/mum4k/termdash/terminal/termbox"
	"github.com/mum4k/termdash/terminalapi"
	"github.com/mum4k/termdash/widgets/barchart"
	"github.com/mum4k/termdash/widgets/donut"
	"github.com/mum4k/termdash/widgets/gauge"
	"github.com/mum4k/termdash/widgets/linechart"
	"github.com/mum4k/termdash/widgets/sparkline"
	"github.com/mum4k/termdash/widgets/text"
)

// redrawInterval is how often termdash redraws the screen.
const redrawInterval = 250 * time.Millisecond

// layout prepares the screen layout by creating the container and placing
// widgets.
func layout(ctx context.Context, t terminalapi.Terminal) (*container.Container, error) {
	spGreen, spRed := newSparkLines(ctx)
	textAndSpark := []container.Option{
		container.SplitHorizontal(
			container.Top(
				container.Border(draw.LineStyleLight),
				container.BorderTitle("Termdash demo, press Q to quit"),
				container.BorderColor(cell.ColorNumber(39)),
				container.PlaceWidget(newTextTime(ctx)),
			),
			container.Bottom(
				container.SplitVertical(
					container.Left(
						container.Border(draw.LineStyleLight),
						container.BorderTitle("A rolling text"),
						container.PlaceWidget(newRollText(ctx)),
					),
					container.Right(
						container.Border(draw.LineStyleLight),
						container.BorderTitle("A SparkLine group"),
						container.SplitHorizontal(
							container.Top(container.PlaceWidget(spGreen)),
							container.Bottom(container.PlaceWidget(spRed)),
						),
					),
				),
			),
			container.SplitPercent(30),
		),
	}

	gaugeAndHeartbeat := []container.Option{
		container.SplitHorizontal(
			container.Top(
				container.Border(draw.LineStyleLight),
				container.BorderTitle("A Gauge"),
				container.BorderColor(cell.ColorNumber(39)),
				container.PlaceWidget(newGauge(ctx)),
			),
			container.Bottom(
				container.Border(draw.LineStyleLight),
				container.BorderTitle("A LineChart"),
				container.PlaceWidget(newHeartbeat(ctx)),
			),
			container.SplitPercent(20),
		),
	}

	leftSide := []container.Option{
		container.SplitHorizontal(
			container.Top(textAndSpark...),
			container.Bottom(gaugeAndHeartbeat...),
			container.SplitPercent(50),
		),
	}

	don, err := newDonut(ctx)
	if err != nil {
		return nil, err
	}

	rightSide := []container.Option{
		container.SplitHorizontal(
			container.Top(
				container.Border(draw.LineStyleLight),
				container.BorderTitle("BarChart"),
				container.PlaceWidget(newBarChart(ctx)),
				container.BorderTitleAlignRight(),
			),
			container.Bottom(
				container.SplitHorizontal(
					container.Top(
						container.Border(draw.LineStyleLight),
						container.BorderTitle("A Donut"),
						container.BorderTitleAlignRight(),
						container.PlaceWidget(don),
					),
					container.Bottom(
						container.Border(draw.LineStyleLight),
						container.BorderTitle("Multiple series"),
						container.BorderTitleAlignRight(),
						container.PlaceWidget(newSines(ctx)),
					),
					container.SplitPercent(30),
				),
			),
			container.SplitPercent(30),
		),
	}

	c, err := container.New(
		t,
		container.SplitVertical(
			container.Left(leftSide...),
			container.Right(rightSide...),
			container.SplitPercent(70),
		),
	)
	if err != nil {
		return nil, err
	}
	return c, nil
}

func main() {
	t, err := termbox.New(termbox.ColorMode(terminalapi.ColorMode256))
	if err != nil {
		panic(err)
	}
	defer t.Close()

	ctx, cancel := context.WithCancel(context.Background())
	c, err := layout(ctx, t)
	if err != nil {
		panic(err)
	}

	quitter := func(k *terminalapi.Keyboard) {
		if k.Key == 'q' || k.Key == 'Q' {
			cancel()
		}
	}
	if err := termdash.Run(ctx, t, c, termdash.KeyboardSubscriber(quitter), termdash.RedrawInterval(redrawInterval)); err != nil {
		panic(err)
	}
}

// periodic executes the provided closure periodically every interval.
// Exits when the context expires.
func periodic(ctx context.Context, interval time.Duration, fn func() error) {
	ticker := time.NewTicker(interval)
	defer ticker.Stop()
	for {
		select {
		case <-ticker.C:
			if err := fn(); err != nil {
				panic(err)
			}
		case <-ctx.Done():
			return
		}
	}
}

// newTextTime creates a new Text widget that displays the current time.
func newTextTime(ctx context.Context) *text.Text {
	t := text.New()

	go periodic(ctx, 1*time.Second, func() error {
		t.Reset()
		txt := time.Now().UTC().Format(time.UnixDate)
		return t.Write(fmt.Sprintf("\n%s", txt), text.WriteCellOpts(cell.FgColor(cell.ColorMagenta)))
	})
	return t
}

// newRollText creates a new Text widget that displays rolling text.
func newRollText(ctx context.Context) *text.Text {
	t := text.New(text.RollContent())

	i := 0
	go periodic(ctx, 1*time.Second, func() error {
		if err := t.Write(fmt.Sprintf("Writing line %d.\n", i), text.WriteCellOpts(cell.FgColor(cell.ColorNumber(142)))); err != nil {
			return err
		}
		i++
		return nil
	})
	return t
}

// newSparkLines creates two new sparklines displaying random values.
func newSparkLines(ctx context.Context) (*sparkline.SparkLine, *sparkline.SparkLine) {
	spGreen := sparkline.New(
		sparkline.Label("Green SparkLine", cell.FgColor(cell.ColorBlue)),
		sparkline.Color(cell.ColorGreen),
	)

	const max = 100
	go periodic(ctx, 250*time.Millisecond, func() error {
		v := int(rand.Int31n(max + 1))
		return spGreen.Add([]int{v})
	})

	spRed := sparkline.New(
		sparkline.Label("Red SparkLine", cell.FgColor(cell.ColorBlue)),
		sparkline.Color(cell.ColorRed),
	)
	go periodic(ctx, 500*time.Millisecond, func() error {
		v := int(rand.Int31n(max + 1))
		return err := spRed.Add([]int{v})
	})
	return spGreen, spRed

}

// newGauge creates a demo Gauge widget.
func newGauge(ctx context.Context) *gauge.Gauge {
	g := gauge.New()

	const start = 35
	progress := start

	go periodic(ctx, 2*time.Second, func() error {
		if err := g.Percent(progress); err != nil {
			return err
		}
		progress++
		if progress > 100 {
			progress = start
		}
		return nil
	})
	return g
}

// newDonut creates a demo Donut widget.
func newDonut(ctx context.Context) (*donut.Donut, error) {
	d, err := donut.New(donut.CellOpts(
		cell.FgColor(cell.ColorNumber(33))),
	)
	if err != nil {
		return nil, err
	}

	const start = 35
	progress := start

	go periodic(ctx, 500*time.Millisecond, func() error {
		if err := d.Percent(progress); err != nil {
			return err
		}
		progress++
		if progress > 100 {
			progress = start
		}
		return nil
	})
	return d, nil
}

// newHeartbeat returns a line chart that displays a heartbeat-like progression.
func newHeartbeat(ctx context.Context) *linechart.LineChart {
	var inputs []float64
	for i := 0; i < 100; i++ {
		v := math.Pow(math.Sin(float64(i)), 63) * math.Sin(float64(i)+1.5) * 8
		inputs = append(inputs, v)
	}

	lc := linechart.New(
		linechart.AxesCellOpts(cell.FgColor(cell.ColorRed)),
		linechart.YLabelCellOpts(cell.FgColor(cell.ColorGreen)),
		linechart.XLabelCellOpts(cell.FgColor(cell.ColorGreen)),
	)
	step := 0
	go periodic(ctx, redrawInterval/3, func() error {
		step = (step + 1) % len(inputs)
		return lc.Series("heartbeat", rotate(inputs, step),
		linechart.SeriesCellOpts(cell.FgColor(cell.ColorNumber(87))),
		linechart.SeriesXLabels(map[int]string{
			0: "zero",
		}),
	)
	})
	return lc
}

// newBarChart returns a BarcChart that displays random values on multiple bars.
func newBarChart(ctx context.Context) *barchart.BarChart {
	bc := barchart.New(
		barchart.BarColors([]cell.Color{
			cell.ColorNumber(33),
			cell.ColorNumber(39),
			cell.ColorNumber(45),
			cell.ColorNumber(51),
			cell.ColorNumber(81),
			cell.ColorNumber(87),
		}),
		barchart.ValueColors([]cell.Color{
			cell.ColorBlack,
			cell.ColorBlack,
			cell.ColorBlack,
			cell.ColorBlack,
			cell.ColorBlack,
			cell.ColorBlack,
		}),
		barchart.ShowValues(),
	)

	const (
		bars = 6
		max  = 100
	)
	values := make([]int, bars)
	go periodic(ctx, 1*time.Second, func() error {
		for i := range values {
			values[i] = int(rand.Int31n(max + 1))
		}

		return bc.Values(values, max)
	})
	return bc
}

// newSines returns a line chart that displays multiple sine series.
func newSines(ctx context.Context) *linechart.LineChart {
	var inputs []float64
	for i := 0; i < 200; i++ {
		v := math.Sin(float64(i) / 100 * math.Pi)
		inputs = append(inputs, v)
	}

	lc := linechart.New(
		linechart.AxesCellOpts(cell.FgColor(cell.ColorRed)),
		linechart.YLabelCellOpts(cell.FgColor(cell.ColorGreen)),
		linechart.XLabelCellOpts(cell.FgColor(cell.ColorGreen)),
	)
	step1 := 0
	go periodic(ctx, redrawInterval/3, func() error {
		step1 = (step1 + 1) % len(inputs)
		if err := lc.Series("first", rotate(inputs, step1),
			linechart.SeriesCellOpts(cell.FgColor(cell.ColorBlue)),
		); err != nil {
			return err
		}

		step2 := (step1 + 100) % len(inputs)
		return lc.Series("second", rotate(inputs, step2), linechart.SeriesCellOpts(cell.FgColor(cell.ColorWhite)))
	})
	return lc
}

// rotate returns a new slice with inputs rotated by step.
// I.e. for a step of one:
//   inputs[0] -> inputs[len(inputs)-1]
//   inputs[1] -> inputs[0]
// And so on.
func rotate(inputs []float64, step int) []float64 {
	return append(inputs[step:], inputs[:step]...)
}
<commit_msg>Removed another one<commit_after>// Copyright 2019 Google Inc.
//
// 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.

// Binary termdashdemo demonstrates the functionality of termdash and its various widgets.
// Exist when 'q' is pressed.
package main

import (
	"context"
	"fmt"
	"math"
	"math/rand"
	"time"

	"github.com/mum4k/termdash"
	"github.com/mum4k/termdash/cell"
	"github.com/mum4k/termdash/container"
	"github.com/mum4k/termdash/draw"
	"github.com/mum4k/termdash/terminal/termbox"
	"github.com/mum4k/termdash/terminalapi"
	"github.com/mum4k/termdash/widgets/barchart"
	"github.com/mum4k/termdash/widgets/donut"
	"github.com/mum4k/termdash/widgets/gauge"
	"github.com/mum4k/termdash/widgets/linechart"
	"github.com/mum4k/termdash/widgets/sparkline"
	"github.com/mum4k/termdash/widgets/text"
)

// redrawInterval is how often termdash redraws the screen.
const redrawInterval = 250 * time.Millisecond

// layout prepares the screen layout by creating the container and placing
// widgets.
func layout(ctx context.Context, t terminalapi.Terminal) (*container.Container, error) {
	spGreen, spRed := newSparkLines(ctx)
	textAndSpark := []container.Option{
		container.SplitHorizontal(
			container.Top(
				container.Border(draw.LineStyleLight),
				container.BorderTitle("Termdash demo, press Q to quit"),
				container.BorderColor(cell.ColorNumber(39)),
				container.PlaceWidget(newTextTime(ctx)),
			),
			container.Bottom(
				container.SplitVertical(
					container.Left(
						container.Border(draw.LineStyleLight),
						container.BorderTitle("A rolling text"),
						container.PlaceWidget(newRollText(ctx)),
					),
					container.Right(
						container.Border(draw.LineStyleLight),
						container.BorderTitle("A SparkLine group"),
						container.SplitHorizontal(
							container.Top(container.PlaceWidget(spGreen)),
							container.Bottom(container.PlaceWidget(spRed)),
						),
					),
				),
			),
			container.SplitPercent(30),
		),
	}

	gaugeAndHeartbeat := []container.Option{
		container.SplitHorizontal(
			container.Top(
				container.Border(draw.LineStyleLight),
				container.BorderTitle("A Gauge"),
				container.BorderColor(cell.ColorNumber(39)),
				container.PlaceWidget(newGauge(ctx)),
			),
			container.Bottom(
				container.Border(draw.LineStyleLight),
				container.BorderTitle("A LineChart"),
				container.PlaceWidget(newHeartbeat(ctx)),
			),
			container.SplitPercent(20),
		),
	}

	leftSide := []container.Option{
		container.SplitHorizontal(
			container.Top(textAndSpark...),
			container.Bottom(gaugeAndHeartbeat...),
			container.SplitPercent(50),
		),
	}

	don, err := newDonut(ctx)
	if err != nil {
		return nil, err
	}

	rightSide := []container.Option{
		container.SplitHorizontal(
			container.Top(
				container.Border(draw.LineStyleLight),
				container.BorderTitle("BarChart"),
				container.PlaceWidget(newBarChart(ctx)),
				container.BorderTitleAlignRight(),
			),
			container.Bottom(
				container.SplitHorizontal(
					container.Top(
						container.Border(draw.LineStyleLight),
						container.BorderTitle("A Donut"),
						container.BorderTitleAlignRight(),
						container.PlaceWidget(don),
					),
					container.Bottom(
						container.Border(draw.LineStyleLight),
						container.BorderTitle("Multiple series"),
						container.BorderTitleAlignRight(),
						container.PlaceWidget(newSines(ctx)),
					),
					container.SplitPercent(30),
				),
			),
			container.SplitPercent(30),
		),
	}

	c, err := container.New(
		t,
		container.SplitVertical(
			container.Left(leftSide...),
			container.Right(rightSide...),
			container.SplitPercent(70),
		),
	)
	if err != nil {
		return nil, err
	}
	return c, nil
}

func main() {
	t, err := termbox.New(termbox.ColorMode(terminalapi.ColorMode256))
	if err != nil {
		panic(err)
	}
	defer t.Close()

	ctx, cancel := context.WithCancel(context.Background())
	c, err := layout(ctx, t)
	if err != nil {
		panic(err)
	}

	quitter := func(k *terminalapi.Keyboard) {
		if k.Key == 'q' || k.Key == 'Q' {
			cancel()
		}
	}
	if err := termdash.Run(ctx, t, c, termdash.KeyboardSubscriber(quitter), termdash.RedrawInterval(redrawInterval)); err != nil {
		panic(err)
	}
}

// periodic executes the provided closure periodically every interval.
// Exits when the context expires.
func periodic(ctx context.Context, interval time.Duration, fn func() error) {
	ticker := time.NewTicker(interval)
	defer ticker.Stop()
	for {
		select {
		case <-ticker.C:
			if err := fn(); err != nil {
				panic(err)
			}
		case <-ctx.Done():
			return
		}
	}
}

// newTextTime creates a new Text widget that displays the current time.
func newTextTime(ctx context.Context) *text.Text {
	t := text.New()

	go periodic(ctx, 1*time.Second, func() error {
		t.Reset()
		txt := time.Now().UTC().Format(time.UnixDate)
		return t.Write(fmt.Sprintf("\n%s", txt), text.WriteCellOpts(cell.FgColor(cell.ColorMagenta)))
	})
	return t
}

// newRollText creates a new Text widget that displays rolling text.
func newRollText(ctx context.Context) *text.Text {
	t := text.New(text.RollContent())

	i := 0
	go periodic(ctx, 1*time.Second, func() error {
		if err := t.Write(fmt.Sprintf("Writing line %d.\n", i), text.WriteCellOpts(cell.FgColor(cell.ColorNumber(142)))); err != nil {
			return err
		}
		i++
		return nil
	})
	return t
}

// newSparkLines creates two new sparklines displaying random values.
func newSparkLines(ctx context.Context) (*sparkline.SparkLine, *sparkline.SparkLine) {
	spGreen := sparkline.New(
		sparkline.Label("Green SparkLine", cell.FgColor(cell.ColorBlue)),
		sparkline.Color(cell.ColorGreen),
	)

	const max = 100
	go periodic(ctx, 250*time.Millisecond, func() error {
		v := int(rand.Int31n(max + 1))
		return spGreen.Add([]int{v})
	})

	spRed := sparkline.New(
		sparkline.Label("Red SparkLine", cell.FgColor(cell.ColorBlue)),
		sparkline.Color(cell.ColorRed),
	)
	go periodic(ctx, 500*time.Millisecond, func() error {
		v := int(rand.Int31n(max + 1))
		return spRed.Add([]int{v})
	})
	return spGreen, spRed

}

// newGauge creates a demo Gauge widget.
func newGauge(ctx context.Context) *gauge.Gauge {
	g := gauge.New()

	const start = 35
	progress := start

	go periodic(ctx, 2*time.Second, func() error {
		if err := g.Percent(progress); err != nil {
			return err
		}
		progress++
		if progress > 100 {
			progress = start
		}
		return nil
	})
	return g
}

// newDonut creates a demo Donut widget.
func newDonut(ctx context.Context) (*donut.Donut, error) {
	d, err := donut.New(donut.CellOpts(
		cell.FgColor(cell.ColorNumber(33))),
	)
	if err != nil {
		return nil, err
	}

	const start = 35
	progress := start

	go periodic(ctx, 500*time.Millisecond, func() error {
		if err := d.Percent(progress); err != nil {
			return err
		}
		progress++
		if progress > 100 {
			progress = start
		}
		return nil
	})
	return d, nil
}

// newHeartbeat returns a line chart that displays a heartbeat-like progression.
func newHeartbeat(ctx context.Context) *linechart.LineChart {
	var inputs []float64
	for i := 0; i < 100; i++ {
		v := math.Pow(math.Sin(float64(i)), 63) * math.Sin(float64(i)+1.5) * 8
		inputs = append(inputs, v)
	}

	lc := linechart.New(
		linechart.AxesCellOpts(cell.FgColor(cell.ColorRed)),
		linechart.YLabelCellOpts(cell.FgColor(cell.ColorGreen)),
		linechart.XLabelCellOpts(cell.FgColor(cell.ColorGreen)),
	)
	step := 0
	go periodic(ctx, redrawInterval/3, func() error {
		step = (step + 1) % len(inputs)
		return lc.Series("heartbeat", rotate(inputs, step),
			linechart.SeriesCellOpts(cell.FgColor(cell.ColorNumber(87))),
			linechart.SeriesXLabels(map[int]string{
				0: "zero",
			}),
		)
	})
	return lc
}

// newBarChart returns a BarcChart that displays random values on multiple bars.
func newBarChart(ctx context.Context) *barchart.BarChart {
	bc := barchart.New(
		barchart.BarColors([]cell.Color{
			cell.ColorNumber(33),
			cell.ColorNumber(39),
			cell.ColorNumber(45),
			cell.ColorNumber(51),
			cell.ColorNumber(81),
			cell.ColorNumber(87),
		}),
		barchart.ValueColors([]cell.Color{
			cell.ColorBlack,
			cell.ColorBlack,
			cell.ColorBlack,
			cell.ColorBlack,
			cell.ColorBlack,
			cell.ColorBlack,
		}),
		barchart.ShowValues(),
	)

	const (
		bars = 6
		max  = 100
	)
	values := make([]int, bars)
	go periodic(ctx, 1*time.Second, func() error {
		for i := range values {
			values[i] = int(rand.Int31n(max + 1))
		}

		return bc.Values(values, max)
	})
	return bc
}

// newSines returns a line chart that displays multiple sine series.
func newSines(ctx context.Context) *linechart.LineChart {
	var inputs []float64
	for i := 0; i < 200; i++ {
		v := math.Sin(float64(i) / 100 * math.Pi)
		inputs = append(inputs, v)
	}

	lc := linechart.New(
		linechart.AxesCellOpts(cell.FgColor(cell.ColorRed)),
		linechart.YLabelCellOpts(cell.FgColor(cell.ColorGreen)),
		linechart.XLabelCellOpts(cell.FgColor(cell.ColorGreen)),
	)
	step1 := 0
	go periodic(ctx, redrawInterval/3, func() error {
		step1 = (step1 + 1) % len(inputs)
		if err := lc.Series("first", rotate(inputs, step1),
			linechart.SeriesCellOpts(cell.FgColor(cell.ColorBlue)),
		); err != nil {
			return err
		}

		step2 := (step1 + 100) % len(inputs)
		return lc.Series("second", rotate(inputs, step2), linechart.SeriesCellOpts(cell.FgColor(cell.ColorWhite)))
	})
	return lc
}

// rotate returns a new slice with inputs rotated by step.
// I.e. for a step of one:
//   inputs[0] -> inputs[len(inputs)-1]
//   inputs[1] -> inputs[0]
// And so on.
func rotate(inputs []float64, step int) []float64 {
	return append(inputs[step:], inputs[:step]...)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"os/signal"

	"github.com/Sirupsen/logrus"
	"github.com/codegangsta/cli"
	"github.com/streadway/amqp"
	"github.com/travis-ci/worker/lib"
	"github.com/travis-ci/worker/lib/backend"
	"golang.org/x/net/context"
)

func main() {
	app := cli.NewApp()
	app.Usage = "Travis Worker daemon"
	app.Version = lib.VersionString
	app.Action = runWorker

	app.Run(os.Args)
}

func runWorker(c *cli.Context) {
	logger := logrus.New().WithField("pid", os.Getpid())

	config := lib.EnvToConfig()
	logger.WithField("config", fmt.Sprintf("%+v", config)).Info("read config")

	amqpConn, err := amqp.Dial(config.AmqpURI)
	if err != nil {
		logger.WithField("err", err).Error("couldn't connect to AMQP")
		return
	}

	logger.Info("connected to AMQP")

	generator := lib.NewBuildScriptGenerator(config.BuildAPIURI)
	provider := backend.NewProvider(config.ProviderName, config.ProviderConfig)

	ctx := context.Background()

	pool := &lib.ProcessorPool{
		Context:   ctx,
		Conn:      amqpConn,
		Provider:  provider,
		Generator: generator,
		Logger:    logger,
	}

	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, os.Interrupt)
	go func() {
		<-signalChan
		logger.Info("SIGTERM received, starting graceful shutdown")
		pool.GracefulShutdown()
	}()

	pool.Run(config.PoolSize, "builds.test")

	err = amqpConn.Close()
	if err != nil {
		logger.WithField("err", err).Error("couldn't close AMQP connection")
		return
	}
}
<commit_msg>Update logging in main<commit_after>package main

import (
	"fmt"
	"os"
	"os/signal"

	"github.com/codegangsta/cli"
	"github.com/streadway/amqp"
	"github.com/travis-ci/worker/lib"
	"github.com/travis-ci/worker/lib/backend"
	"golang.org/x/net/context"
)

func main() {
	app := cli.NewApp()
	app.Usage = "Travis Worker daemon"
	app.Version = lib.VersionString
	app.Action = runWorker

	app.Run(os.Args)
}

func runWorker(c *cli.Context) {
	ctx := context.Background()
	logger := lib.LoggerFromContext(ctx)

	config := lib.EnvToConfig()
	logger.WithField("config", fmt.Sprintf("%+v", config)).Debug("read config")

	amqpConn, err := amqp.Dial(config.AmqpURI)
	if err != nil {
		logger.WithField("err", err).Error("couldn't connect to AMQP")
		return
	}

	logger.Debug("connected to AMQP")

	generator := lib.NewBuildScriptGenerator(config.BuildAPIURI)
	provider := backend.NewProvider(config.ProviderName, config.ProviderConfig)

	pool := &lib.ProcessorPool{
		Context:   ctx,
		Conn:      amqpConn,
		Provider:  provider,
		Generator: generator,
		Logger:    logger,
	}

	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, os.Interrupt)
	go func() {
		<-signalChan
		logger.Info("SIGTERM received, starting graceful shutdown")
		pool.GracefulShutdown()
	}()

	pool.Run(config.PoolSize, "builds.test")

	err = amqpConn.Close()
	if err != nil {
		logger.WithField("err", err).Error("couldn't close AMQP connection cleanly")
		return
	}
}
<|endoftext|>


<commit_before>package queue

import (
	"crypto/rand"
	"errors"
	"sync"
	"time"
)

var ERROR_HASH_NOT_FOUND = errors.New("Hash not found")
var ERROR_ALREADY_RESERVED = errors.New("Item already reserved")
var ERROR_NOT_RESERVED = errors.New("Item not reserved")
var ERROR_NO_ITEMS_AVALIABLE = errors.New("No items available")

// Item struct is the basic queue item
type Item struct {
	ReservedAt time.Time `json:"reserved_at"`
	Value      []byte    `json:"value"`
}

// Data contains all data in the current queue
type Data struct {
	MaxReserTime float64
	ItemList     map[string]Item `json:"item"`
	sync.RWMutex
}

// New queue
func New() (q *Data, err error) {
	q = &Data{
		MaxReserTime: 30.0,
		ItemList:     make(map[string]Item),
	}
	return
}

// Count items in the queue
func (q *Data) Count() int {
	return len(q.ItemList)
}

// Put data in the queue
func (q *Data) Put(b []byte) {
	q.Lock()
	defer q.Unlock()
	q.ItemList[randStr()] = Item{Value: b}
}

// Renew the reservation of an item in the queue
func (q *Data) Renew(hash string) (err error) {
	q.Lock()
	defer q.Unlock()
	v, ok := q.ItemList[hash]
	if !ok {
		err = ERROR_HASH_NOT_FOUND
		return
	}
	now := time.Now()
	diff := now.Sub(v.ReservedAt)
	if diff.Seconds() >= q.MaxReserTime {
		err = ERROR_NOT_RESERVED
		return
	}
	v.ReservedAt = now
	q.ItemList[hash] = v
	return
}

// Reserve searches for the next available item in the queue
// If the item is not removed or the reservation time is not
// renewed, the item will returns to the queue automatically
func (q *Data) Reserve() (hash string, value []byte, err error) {
	q.Lock()
	defer q.Unlock()
	for k, v := range q.ItemList {
		now := time.Now()
		diff := now.Sub(v.ReservedAt)
		if diff.Seconds() > q.MaxReserTime {
			v.ReservedAt = now
			q.ItemList[k] = v
			value = v.Value
			hash = k
			return
		}
	}
	err = ERROR_NO_ITEMS_AVALIABLE
	return
}

// Remove item from the queue, the item must be reserved
func (q *Data) Remove(hash string) (err error) {
	q.Lock()
	defer q.Unlock()
	v, ok := q.ItemList[hash]
	if !ok {
		err = ERROR_HASH_NOT_FOUND
		return
	}
	diff := time.Since(v.ReservedAt)
	if diff.Seconds() >= q.MaxReserTime {
		err = ERROR_NOT_RESERVED
		return
	}
	delete(q.ItemList, hash)
	return
}

func randStr() (ret string) {
	const charList = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
	const clLen byte = 62
	const size = 36
	var bytes = make([]byte, size)
	if _, err := rand.Read(bytes); err != nil {
		panic(err.Error())
	}
	for k, v := range bytes {
		bytes[k] = charList[v%clLen]
	}
	ret = string(bytes)
	return
}
<commit_msg>update mutex system<commit_after>package queue

import (
	"crypto/rand"
	"errors"
	"sync"
	"time"
)

var ERROR_HASH_NOT_FOUND = errors.New("Hash not found")
var ERROR_ALREADY_RESERVED = errors.New("Item already reserved")
var ERROR_NOT_RESERVED = errors.New("Item not reserved")
var ERROR_NO_ITEMS_AVALIABLE = errors.New("No items available")

// Item struct is the basic queue item
type Item struct {
	ReservedAt time.Time `json:"reserved_at"`
	Value      []byte    `json:"value"`
}

// Data contains all data in the current queue
type Data struct {
	MaxReserTime float64
	ItemList     map[string]Item `json:"item"`
	mutex        *sync.RWMutex
}

// New queue
func New() (q *Data, err error) {
	q = &Data{
		MaxReserTime: 30.0,
		mutex:        &sync.RWMutex{},
		ItemList:     make(map[string]Item),
	}
	return
}

// Count items in the queue
func (q *Data) Count() int {
	return len(q.ItemList)
}

// Put data in the queue
func (q *Data) Put(b []byte) {
	q.mutex.Lock()
	defer q.mutex.Unlock()
	q.ItemList[randStr()] = Item{Value: b}
}

// Renew the reservation of an item in the queue
func (q *Data) Renew(hash string) (err error) {
	q.mutex.Lock()
	defer q.mutex.Unlock()
	v, ok := q.ItemList[hash]
	if !ok {
		err = ERROR_HASH_NOT_FOUND
		return
	}
	now := time.Now()
	diff := now.Sub(v.ReservedAt)
	if diff.Seconds() >= q.MaxReserTime {
		err = ERROR_NOT_RESERVED
		return
	}
	v.ReservedAt = now
	q.ItemList[hash] = v
	return
}

// Reserve searches for the next available item in the queue
// If the item is not removed or the reservation time is not
// renewed, the item will returns to the queue automatically
func (q *Data) Reserve() (hash string, value []byte, err error) {
	q.mutex.Lock()
	defer q.mutex.Unlock()
	for k, v := range q.ItemList {
		now := time.Now()
		diff := now.Sub(v.ReservedAt)
		if diff.Seconds() > q.MaxReserTime {
			v.ReservedAt = now
			q.ItemList[k] = v
			value = v.Value
			hash = k
			return
		}
	}
	err = ERROR_NO_ITEMS_AVALIABLE
	return
}

// Remove item from the queue, the item must be reserved
func (q *Data) Remove(hash string) (err error) {
	q.mutex.Lock()
	defer q.mutex.Unlock()
	v, ok := q.ItemList[hash]
	if !ok {
		err = ERROR_HASH_NOT_FOUND
		return
	}
	diff := time.Since(v.ReservedAt)
	if diff.Seconds() >= q.MaxReserTime {
		err = ERROR_NOT_RESERVED
		return
	}
	delete(q.ItemList, hash)
	return
}

func randStr() (ret string) {
	const charList = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
	const clLen byte = 62
	const size = 36
	var bytes = make([]byte, size)
	if _, err := rand.Read(bytes); err != nil {
		panic(err.Error())
	}
	for k, v := range bytes {
		bytes[k] = charList[v%clLen]
	}
	ret = string(bytes)
	return
}
<|endoftext|>


<commit_before>package command

import (
	"flag"
	"fmt"
	"sort"
	"strings"

	"github.com/funkygao/gafka/ctx"
	gzk "github.com/funkygao/gafka/zk"
	"github.com/funkygao/gocli"
	"github.com/samuel/go-zookeeper/zk"
)

type Replace struct {
	Ui  cli.Ui
	Cmd string

	zone     string
	path     string
	from, to string
}

func (this *Replace) Run(args []string) (exitCode int) {
	cmdFlags := flag.NewFlagSet("replace", flag.ContinueOnError)
	cmdFlags.Usage = func() { this.Ui.Output(this.Help()) }
	cmdFlags.StringVar(&this.zone, "z", ctx.ZkDefaultZone(), "")
	cmdFlags.StringVar(&this.from, "from", "", "")
	cmdFlags.StringVar(&this.to, "to", "", "")
	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	if this.zone == "" || this.from == "" || this.to == "" {
		this.Ui.Output(this.Help())
		return 2
	}

	if len(args) == 0 {
		this.Ui.Error("missing path")
		return 2
	}

	this.path = args[len(args)-1]

	zkzone := gzk.NewZkZone(gzk.DefaultConfig(this.zone, ctx.ZoneZkAddrs(this.zone)))
	defer zkzone.Close()

	this.replaceZnodes(zkzone.Conn(), this.path, this.from, this.to)

	return
}

func (this *Replace) replaceZnodes(conn *zk.Conn, path string, from, to string) {
	children, _, err := conn.Children(path)
	if err != nil {
		return
	}

	sort.Strings(children)
	for _, child := range children {
		if path == "/" {
			path = ""
		}

		znode := fmt.Sprintf("%s/%s", path, child)

		// display znode content
		data, stat, err := conn.Get(znode)
		must(err)

		if stat.EphemeralOwner > 0 {
			// ephemeral znode ignored
			continue
		}

		sdata := string(data)
		if len(data) > 0 && patternMatched(sdata, from) {
			replacedBy := strings.Replace(sdata, from, to, -1)
			yes, err := this.Ui.Ask(fmt.Sprintf("%s -> %s? [Y/n]", sdata, replacedBy))
			if err != nil {
				panic(err)
			}

			if yes != "n" && yes != "N" {
				_, err := conn.Set(znode, []byte(replacedBy), -1)
				if err != nil {
					panic(err)
				}
			}
		}

		this.replaceZnodes(conn, znode, from, to)
	}
}

func (*Replace) Synopsis() string {
	return "Recursively interactively replace znode values"
}

func (this *Replace) Help() string {
	help := fmt.Sprintf(`
Usage: %s replace [options] <path>

    %s

Options:

    -z zone

    -from from

    -to to

`, this.Cmd, this.Synopsis())
	return strings.TrimSpace(help)
}
<commit_msg>'zk replace' need admin rights<commit_after>package command

import (
	"flag"
	"fmt"
	"sort"
	"strings"

	"github.com/funkygao/gafka/ctx"
	gzk "github.com/funkygao/gafka/zk"
	"github.com/funkygao/gocli"
	"github.com/samuel/go-zookeeper/zk"
)

type Replace struct {
	Ui  cli.Ui
	Cmd string

	zone     string
	path     string
	from, to string
}

func (this *Replace) Run(args []string) (exitCode int) {
	cmdFlags := flag.NewFlagSet("replace", flag.ContinueOnError)
	cmdFlags.Usage = func() { this.Ui.Output(this.Help()) }
	cmdFlags.StringVar(&this.zone, "z", ctx.ZkDefaultZone(), "")
	cmdFlags.StringVar(&this.from, "from", "", "")
	cmdFlags.StringVar(&this.to, "to", "", "")
	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	if validateArgs(this, this.Ui).
		require("-from", "-to").
		requireAdminRights("-f").
		invalid(args) {
		return 2
	}

	if len(args) == 0 {
		this.Ui.Error("missing path")
		return 2
	}

	this.path = args[len(args)-1]

	zkzone := gzk.NewZkZone(gzk.DefaultConfig(this.zone, ctx.ZoneZkAddrs(this.zone)))
	defer zkzone.Close()

	this.replaceZnodes(zkzone.Conn(), this.path, this.from, this.to)

	return
}

func (this *Replace) replaceZnodes(conn *zk.Conn, path string, from, to string) {
	children, _, err := conn.Children(path)
	if err != nil {
		return
	}

	sort.Strings(children)
	for _, child := range children {
		if path == "/" {
			path = ""
		}

		znode := fmt.Sprintf("%s/%s", path, child)

		// display znode content
		data, stat, err := conn.Get(znode)
		must(err)

		if stat.EphemeralOwner > 0 {
			// ephemeral znode ignored
			continue
		}

		sdata := string(data)
		if len(data) > 0 && patternMatched(sdata, from) {
			replacedBy := strings.Replace(sdata, from, to, -1)
			yes, err := this.Ui.Ask(fmt.Sprintf("%s -> %s? [Y/n]", sdata, replacedBy))
			if err != nil {
				panic(err)
			}

			if yes != "n" && yes != "N" {
				_, err := conn.Set(znode, []byte(replacedBy), -1)
				if err != nil {
					panic(err)
				}
			}
		}

		this.replaceZnodes(conn, znode, from, to)
	}
}

func (*Replace) Synopsis() string {
	return "Recursively interactively replace znode values"
}

func (this *Replace) Help() string {
	help := fmt.Sprintf(`
Usage: %s replace [options] <path>

    %s

Options:

    -z zone

    -from from

    -to to

`, this.Cmd, this.Synopsis())
	return strings.TrimSpace(help)
}
<|endoftext|>


<commit_before>//go:build e2e
// +build e2e

package e2e

import (
	"context"
	"fmt"
	"os"
	"os/exec"
	"strings"
	"testing"

	cloudevents "github.com/cloudevents/sdk-go/v2"
	. "knative.dev/kn-plugin-func/testing"
)

// TestInvokeFunction is used when testing the 'func invoke' subcommand.
// It responds with a CloudEvent containing an echo of the data received
// If the CloudEvent received has source "func:set" it will update the
// current value of data.
var TestInvokeFunctionImpl = `
package function

import (
  "context"

  ce "github.com/cloudevents/sdk-go/v2/event"
)

var _data = []byte{}
var _type = "text/plain"

func Handle(ctx context.Context, event ce.Event) (*ce.Event, error) {
	if event.Source() == "func:set" {
		_data = event.Data()
		_type = event.DataContentType()
	}
	res := ce.New()
	res.SetSource("func:testInvokeHandler")
	res.SetData(_type, _data)
	return &res, nil
}
`

// TestInvoke ensures that invoking a CloudEvent Function succeeds, including
// preserving custom values through the full round-trip.
func TestInvoke(t *testing.T) {
	var (
		root        = "testdata/e2e/testinvoke" // root path for the test Function
		bin, prefix = bin()                     // path to test binary and prefix args
		cleanup     = Within(t, root)           // Create and CD to root.
		cwd, _      = os.Getwd()                // the current working directory (absolute)
	)
	defer cleanup()

	run(t, bin, prefix, "create", "--verbose=true", "--language=go", "--template=cloudevents", cwd)
	set(t, "handle.go", TestInvokeFunctionImpl)
	run(t, bin, prefix, "deploy", "--verbose=true", "--registry", GetRegistry())
	run(t, bin, prefix, "invoke", "--verbose=true", "--content-type=text/plain", "--source=func:set", "--data=TEST")

	// Validate by fetching the contents of the Function's data global
	fmt.Println("Validate:")
	req := cloudevents.NewEvent()
	req.SetID("1")
	req.SetSource("func:get")
	req.SetType("func.test")
	c, err := cloudevents.NewClientHTTP(cloudevents.WithTarget("http://testinvoke.default.127.0.0.1.sslip.io"))
	if err != nil {
		return
	}
	res, err := c.Request(context.Background(), req)
	if cloudevents.IsUndelivered(err) {
		t.Fatal(err)
	}
	if string(res.Data()) != "TEST" {
		t.Fatalf("expected data 'TEST' got '%v'", string(res.Data()))
	}
	return
}

// bin returns the path to use for the binary plus any leading args that
// should be prepended.
// For example, this will usually either return `/path/to/func` or `kn func`.
// See NewKnFuncShellCli for original source of this logic.
func bin() (path string, args []string) {
	if IsUseKnFunc() {
		return "kn", []string{"func"}
	}
	if path = GetFuncBinaryPath(); path == "" {
		fmt.Fprintf(os.Stderr, "'E2E_FUNC_BIN_PATH' or 'E2E_USE_KN_FUNC' can be used to specify test binary path.")
		return "func", []string{} //default
	}
	return path, []string{}
}

// run the given binary with the given two sets of arguments
// This allows for swappable running between the two forms:
// func [subcommand] [flags]
//   and
// kn func [subcommand] [flags]
func run(t *testing.T, bin string, prefix []string, suffix ...string) {
	t.Helper()
	args := append(prefix, suffix...)
	fmt.Printf("%v %v\n", bin, strings.Join(args, " "))

	cmd := exec.Command(bin, args...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		t.Fatal(err)
	}
}

// set the contents of the given file
func set(t *testing.T, path, data string) {
	if err := os.WriteFile(path, []byte(data), os.ModePerm); err != nil {
		t.Fatal(err)
	}
}
<commit_msg>test: url for invoke test (#863)<commit_after>//go:build e2e
// +build e2e

package e2e

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"os"
	"os/exec"
	"regexp"
	"strings"
	"testing"

	cloudevents "github.com/cloudevents/sdk-go/v2"
	. "knative.dev/kn-plugin-func/testing"
)

// TestInvokeFunction is used when testing the 'func invoke' subcommand.
// It responds with a CloudEvent containing an echo of the data received
// If the CloudEvent received has source "func:set" it will update the
// current value of data.
var TestInvokeFunctionImpl = `
package function

import (
  "context"

  ce "github.com/cloudevents/sdk-go/v2/event"
)

var _data = []byte{}
var _type = "text/plain"

func Handle(ctx context.Context, event ce.Event) (*ce.Event, error) {
	if event.Source() == "func:set" {
		_data = event.Data()
		_type = event.DataContentType()
	}
	res := ce.New()
	res.SetSource("func:testInvokeHandler")
	res.SetData(_type, _data)
	return &res, nil
}
`

// TestInvoke ensures that invoking a CloudEvent Function succeeds, including
// preserving custom values through the full round-trip.
func TestInvoke(t *testing.T) {
	var (
		root        = "testdata/e2e/testinvoke" // root path for the test Function
		bin, prefix = bin()                     // path to test binary and prefix args
		cleanup     = Within(t, root)           // Create and CD to root.
		cwd, _      = os.Getwd()                // the current working directory (absolute)
	)
	defer cleanup()

	run(t, bin, prefix, "create", "--verbose=true", "--language=go", "--template=cloudevents", cwd)
	set(t, "handle.go", TestInvokeFunctionImpl)
	run(t, bin, prefix, "deploy", "--verbose=true", "--registry", GetRegistry())
	infoOut := run(t, bin, prefix, "info", "--output", "plain")
	run(t, bin, prefix, "invoke", "--verbose=true", "--content-type=text/plain", "--source=func:set", "--data=TEST")

	// Resolve target service URL from info command stdout
	targetUrl := "http://testinvoke.default.127.0.0.1.sslip.io"
	matches := regexp.MustCompile("Route (http.*)").FindStringSubmatch(infoOut)
	if len(matches) > 1 {
		targetUrl = matches[1]
	}

	// Validate by fetching the contents of the Function's data global
	fmt.Println("Validate:")
	req := cloudevents.NewEvent()
	req.SetID("1")
	req.SetSource("func:get")
	req.SetType("func.test")
	c, err := cloudevents.NewClientHTTP(cloudevents.WithTarget(targetUrl))
	if err != nil {
		return
	}
	res, err := c.Request(context.Background(), req)
	if cloudevents.IsUndelivered(err) {
		t.Fatal(err)
	}
	if string(res.Data()) != "TEST" {
		t.Fatalf("expected data 'TEST' got '%v'", string(res.Data()))
	}
	return
}

// bin returns the path to use for the binary plus any leading args that
// should be prepended.
// For example, this will usually either return `/path/to/func` or `kn func`.
// See NewKnFuncShellCli for original source of this logic.
func bin() (path string, args []string) {
	if IsUseKnFunc() {
		return "kn", []string{"func"}
	}
	if path = GetFuncBinaryPath(); path == "" {
		fmt.Fprintf(os.Stderr, "'E2E_FUNC_BIN_PATH' or 'E2E_USE_KN_FUNC' can be used to specify test binary path.")
		return "func", []string{} //default
	}
	return path, []string{}
}

// run the given binary with the given two sets of arguments
// This allows for swappable running between the two forms:
// func [subcommand] [flags]
//   and
// kn func [subcommand] [flags]
func run(t *testing.T, bin string, prefix []string, suffix ...string) string {
	t.Helper()
	args := append(prefix, suffix...)
	fmt.Printf("%v %v\n", bin, strings.Join(args, " "))

	var stdout bytes.Buffer

	cmd := exec.Command(bin, args...)
	cmd.Stdout = io.MultiWriter(os.Stdout, &stdout)
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		t.Fatal(err)
	}
	return stdout.String()
}

// set the contents of the given file
func set(t *testing.T, path, data string) {
	if err := os.WriteFile(path, []byte(data), os.ModePerm); err != nil {
		t.Fatal(err)
	}
}
<|endoftext|>