<commit_before>package main

import (
    "flag"
    "fmt"
    "github.com/kierdavis/avr/clock"
    "github.com/kierdavis/avr/emulator"
    "github.com/kierdavis/avr/hardware/gpio"
    "github.com/kierdavis/avr/hardware/timer"
    "github.com/kierdavis/avr/loader/ihexloader"
    "github.com/kierdavis/avr/spec"
    "os"
    "log"
)

func main() {
    flag.Parse()

    if flag.NArg() < 1 {
        fmt.Fprintf(os.Stderr, "usage: %s <program.hex>\n", os.Args[0])
        os.Exit(2)
    }

    runEmulator()
}

func runEmulator() {
    clk := clock.New()

    em := emulator.NewEmulator(spec.ATmega168)
    em.SetLogging(true)
    clk.Add(em)

    loadProgram(em)
    setupIO(em, clk)

    /*
    // main loop
    m := 20
    n := 10000000 / m
    for {
        t1 := time.Now()
        for i := 0; i < n; i++ {
            em.Run(uint(m))
            t0.Run(uint(m))
            totalTicks += uint64(m)
        }
        t2 := time.Now()

        secs := float64(t2.Sub(t1)) / float64(time.Second)
        fmt.Printf("Running at: %f MHz (%f ns/tick)\n", float64(n*m) / (secs * 1e6), (secs * 1e9) / float64(n*m))
    }
    */

    for {
        freq := clk.MonitorFrequency()
        log.Printf("[avr/cmd/avrem] Running at: %.1f MHz (%.1f ns/tick)", freq / 1e6, 1e9 / freq)

        for i := 0; i < 1e5; i++ {
            clk.Run(20)
        }

        clk.Throttle(16e6)
    }

    fmt.Println("OK.")
}

func loadProgram(em *emulator.Emulator) {
    f, err := os.Open(flag.Arg(0))
    if err != nil {
        fmt.Fprintf(os.Stderr, "error: %s\n", err.Error())
        os.Exit(1)
    }

    err = ihexloader.Load(em, f)
    f.Close()
    if err != nil {
        fmt.Fprintf(os.Stderr, "error: %s\n", err.Error())
        os.Exit(1)
    }
}

func setupIO(em *emulator.Emulator, clk *clock.Clock) {
    gpioB := gpio.New('B', 8)
    gpioB.SetOutputAdapter(5, &PrintingOutputPinAdapter{Label: "LED"})
    gpioB.AddTo(em)

    t0 := timer.New(0)
    t0.SetLogging(true)
    t0.AddTo(em)
    clk.Add(t0)
}

type PrintingOutputPinAdapter struct {
    Label string
    Prev bool
}

func (a *PrintingOutputPinAdapter) SetState(state bool) {
    if state != a.Prev {
        a.Prev = state
        if state {
            fmt.Printf("%s changed to high\n", a.Label)
        } else {
            fmt.Printf("%s changed to low\n", a.Label)
        }
    } else {
        fmt.Printf("%s remained the same\n", a.Label)
    }
}
<commit_msg>Add CPU profiling to try to find bottlenecks in emulator<commit_after>package main

import (
    "flag"
    "fmt"
    "github.com/kierdavis/avr/clock"
    "github.com/kierdavis/avr/emulator"
    "github.com/kierdavis/avr/hardware/gpio"
    "github.com/kierdavis/avr/hardware/timer"
    "github.com/kierdavis/avr/loader/ihexloader"
    "github.com/kierdavis/avr/spec"
    "os"
    "log"
    "runtime/pprof"
)

var cpuProfile = flag.String("cpuprofile", "", "filename to write profiling data to")

func main() {
    flag.Parse()

    if flag.NArg() < 1 {
        fmt.Fprintf(os.Stderr, "usage: %s <program.hex>\n", os.Args[0])
        os.Exit(2)
    }

    if *cpuProfile != "" {
        f, err := os.Create(*cpuProfile)
        if err != nil {
            fmt.Fprintf(os.Stderr, "error: %s\n", err.Error())
            os.Exit(1)
        }
        pprof.StartCPUProfile(f)
        defer func() {
            pprof.StopCPUProfile()
            f.Close()
        }()
    }

    runEmulator()
}

func runEmulator() {
    clk := clock.New()

    em := emulator.NewEmulator(spec.ATmega168)
    em.SetLogging(true)
    clk.Add(em)

    loadProgram(em)
    setupIO(em, clk)

    /*
    // main loop
    m := 20
    n := 10000000 / m
    for {
        t1 := time.Now()
        for i := 0; i < n; i++ {
            em.Run(uint(m))
            t0.Run(uint(m))
            totalTicks += uint64(m)
        }
        t2 := time.Now()

        secs := float64(t2.Sub(t1)) / float64(time.Second)
        fmt.Printf("Running at: %f MHz (%f ns/tick)\n", float64(n*m) / (secs * 1e6), (secs * 1e9) / float64(n*m))
    }
    */

    for i := 0; i < 100; i++ {
        freq := clk.MonitorFrequency()
        log.Printf("[avr/cmd/avrem] Running at: %.1f MHz (%.1f ns/tick)", freq / 1e6, 1e9 / freq)

        for i := 0; i < 1e5; i++ {
            clk.Run(20)
        }

        clk.Throttle(16e6)
    }

    fmt.Println("OK.")
}

func loadProgram(em *emulator.Emulator) {
    f, err := os.Open(flag.Arg(0))
    if err != nil {
        fmt.Fprintf(os.Stderr, "error: %s\n", err.Error())
        os.Exit(1)
    }

    err = ihexloader.Load(em, f)
    f.Close()
    if err != nil {
        fmt.Fprintf(os.Stderr, "error: %s\n", err.Error())
        os.Exit(1)
    }
}

func setupIO(em *emulator.Emulator, clk *clock.Clock) {
    gpioB := gpio.New('B', 8)
    gpioB.SetOutputAdapter(5, &PrintingOutputPinAdapter{Label: "LED"})
    gpioB.AddTo(em)

    t0 := timer.New(0)
    t0.SetLogging(true)
    t0.AddTo(em)
    clk.Add(t0)
}

type PrintingOutputPinAdapter struct {
    Label string
    Prev bool
}

func (a *PrintingOutputPinAdapter) SetState(state bool) {
    if state != a.Prev {
        a.Prev = state
        if state {
            fmt.Printf("%s changed to high\n", a.Label)
        } else {
            fmt.Printf("%s changed to low\n", a.Label)
        }
    } else {
        fmt.Printf("%s remained the same\n", a.Label)
    }
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net"
	"strconv"
	"strings"
	"time"

	"github.com/spf13/cobra"

	"github.com/datawire/ambassador/pkg/supervisor"
)

func (d *Daemon) handleCommand(p *supervisor.Process, conn net.Conn, data *ClientMessage) error {
	out := NewEmitter(conn)
	rootCmd := d.getRootCommand(p, out, data)
	rootCmd.SetOutput(conn) // FIXME replace with SetOut and SetErr
	rootCmd.PersistentPreRun = func(cmd *cobra.Command, _ []string) {
		if batch, _ := cmd.Flags().GetBool("batch"); batch {
			out.SetKV()
		}
	}
	rootCmd.SetArgs(data.Args[1:])
	err := rootCmd.Execute()
	if err != nil {
		out.SendExit(1)
	}
	return out.Err()
}

func (d *Daemon) getRootCommand(p *supervisor.Process, out *Emitter, data *ClientMessage) *cobra.Command {
	rootCmd := &cobra.Command{
		Use:          "edgectl",
		Short:        "Edge Control",
		SilenceUsage: true, // https://github.com/spf13/cobra/issues/340
	}
	_ = rootCmd.PersistentFlags().Bool("batch", false, "Emit machine-readable output")
	_ = rootCmd.PersistentFlags().MarkHidden("batch")

	rootCmd.AddCommand(&cobra.Command{
		Use:   "version",
		Short: "Show program's version number and exit",
		Args:  cobra.ExactArgs(0),
		RunE: func(_ *cobra.Command, _ []string) error {
			out.Println("Client", data.ClientVersion)
			out.Println("Daemon", displayVersion)
			out.Send("daemon.version", Version)
			out.Send("daemon.apiVersion", apiVersion)
			return out.Err()
		},
	})
	rootCmd.AddCommand(&cobra.Command{
		Use:   "status",
		Short: "Show connectivity status",
		Args:  cobra.ExactArgs(0),
		RunE: func(_ *cobra.Command, _ []string) error {
			if err := d.Status(p, out); err != nil {
				return err
			}
			return out.Err()
		},
	})
	rootCmd.AddCommand(&cobra.Command{
		Use:   "pause",
		Short: "Turn off network overrides (to use a VPN)",
		Args:  cobra.ExactArgs(0),
		RunE: func(_ *cobra.Command, _ []string) error {
			if d.network == nil {
				out.Println("Network overrides are already paused")
				out.Send("paused", true)
				return out.Err()
			}
			if d.cluster != nil {
				out.Println("Edge Control is connected to a cluster.")
				out.Println("See \"edgectl status\" for details.")
				out.Println("Please disconnect before pausing.")
				out.Send("paused", false)
				out.SendExit(1)
				return out.Err()
			}

			if err := d.network.Close(); err != nil {
				p.Logf("pause: %v", err)
				out.Printf("Unexpected error while pausing: %v\n", err)
			}
			d.network = nil

			out.Println("Network overrides paused.")
			out.Println("Used \"edgectl resume\" to reestablish network overrides.")
			out.Send("paused", true)

			return out.Err()
		},
	})
	rootCmd.AddCommand(&cobra.Command{
		Use:     "resume",
		Short:   "Turn network overrides on (after using edgectl pause)",
		Aliases: []string{"unpause"},
		Args:    cobra.ExactArgs(0),
		RunE: func(_ *cobra.Command, _ []string) error {
			if d.network != nil {
				if d.network.IsOkay() {
					out.Println("Network overrides are established (not paused)")
				} else {
					out.Println("Network overrides are being reestablished...")
				}
				out.Send("paused", false)
				return out.Err()
			}

			if err := d.MakeNetOverride(p); err != nil {
				p.Logf("resume: %v", err)
				out.Printf("Unexpected error establishing network overrides: %v", err)
			}
			out.Send("paused", d.network == nil)

			return out.Err()
		},
	})
	connectCmd := &cobra.Command{
		Use:   "connect [flags] [-- additional kubectl arguments...]",
		Short: "Connect to a cluster",
		RunE: func(cmd *cobra.Command, args []string) error {
			context, _ := cmd.Flags().GetString("context")
			namespace, _ := cmd.Flags().GetString("namespace")
			managerNs, _ := cmd.Flags().GetString("manager-namespace")
			if err := d.Connect(p, out, data.RAI, context, namespace, managerNs, args); err != nil {
				return err
			}
			return out.Err()
		},
	}
	_ = connectCmd.Flags().StringP(
		"context", "c", "",
		"The Kubernetes context to use. Defaults to the current kubectl context.",
	)
	_ = connectCmd.Flags().StringP(
		"namespace", "n", "",
		"The Kubernetes namespace to use. Defaults to kubectl's default for the context.",
	)
	_ = connectCmd.Flags().StringP(
		"manager-namespace", "m", "ambassador",
		"The Kubernetes namespace in which the Traffic Manager is running.",
	)
	rootCmd.AddCommand(connectCmd)
	rootCmd.AddCommand(&cobra.Command{
		Use:   "disconnect",
		Short: "Disconnect from the connected cluster",
		Args:  cobra.ExactArgs(0),
		RunE: func(_ *cobra.Command, _ []string) error {
			if err := d.Disconnect(p, out); err != nil {
				return err
			}
			return out.Err()
		},
	})
	rootCmd.AddCommand(&cobra.Command{
		Use:   "quit",
		Short: "Tell Edge Control Daemon to quit (for upgrades)",
		Args:  cobra.ExactArgs(0),
		RunE: func(_ *cobra.Command, _ []string) error {
			out.Println("Edge Control Daemon quitting...")
			out.Send("quit", true)
			p.Supervisor().Shutdown()
			return out.Err()
		},
	})

	interceptCmd := &cobra.Command{
		Use: "intercept",
		Long: "Manage deployment intercepts. An intercept arranges for a subset of requests to be " +
			"diverted to the local machine.",
		Short: "Manage deployment intercepts",
	}
	interceptCmd.AddCommand(&cobra.Command{
		Use:     "available",
		Aliases: []string{"avail"},
		Short:   "List deployments available for intercept",
		Args:    cobra.ExactArgs(0),
		RunE: func(_ *cobra.Command, _ []string) error {
			msg := d.interceptMessage()
			if msg != "" {
				out.Println(msg)
				out.Send("intercept", msg)
				return out.Err()
			}
			out.Send("interceptable", len(d.trafficMgr.interceptables))
			switch {
			case len(d.trafficMgr.interceptables) == 0:
				out.Println("No interceptable deployments")
			default:
				out.Printf("Found %d interceptable deployment(s):\n", len(d.trafficMgr.interceptables))
				for idx, deployment := range d.trafficMgr.interceptables {
					fields := strings.SplitN(deployment, "/", 2)

					appName := fields[0]
					appNamespace := d.cluster.namespace

					if len(fields) > 1 {
						appNamespace = fields[0]
						appName = fields[1]
					}

					out.Printf("%4d. %s in namespace %s\n", idx+1, appName, appNamespace)
					out.Send(fmt.Sprintf("interceptable.deployment.%d", idx+1), deployment)
				}
			}
			return out.Err()
		},
	})

	interceptCmd.AddCommand(&cobra.Command{
		Use:   "list",
		Short: "List current intercepts",
		Args:  cobra.ExactArgs(0),
		RunE: func(_ *cobra.Command, _ []string) error {
			if err := d.ListIntercepts(p, out); err != nil {
				return err
			}
			return out.Err()
		},
	})
	interceptCmd.AddCommand(&cobra.Command{
		Use:   "remove",
		Short: "Deactivate and remove an existent intercept",
		Args:  cobra.MinimumNArgs(1),
		RunE: func(_ *cobra.Command, args []string) error {
			name := strings.TrimSpace(args[0])
			if err := d.RemoveIntercept(p, out, name); err != nil {
				return err
			}
			return out.Err()
		},
	})
	intercept := InterceptInfo{}
	interceptAddCmd := &cobra.Command{
		Use:   "add DEPLOYMENT -t [HOST:]PORT -m HEADER=REGEX ...",
		Short: "Add a deployment intercept",
		Args:  cobra.ExactArgs(1),
		RunE: func(_ *cobra.Command, args []string) error {
			intercept.Deployment = args[0]
			if intercept.Name == "" {
				intercept.Name = fmt.Sprintf("cept-%d", time.Now().Unix())
			}

			// if intercept.Namespace == "" {
			// 	intercept.Namespace = "default"
			// }

			if intercept.Prefix == "" {
				intercept.Prefix = "/"
			}

			var host, portStr string
			hp := strings.SplitN(intercept.TargetHost, ":", 2)
			if len(hp) < 2 {
				portStr = hp[0]
			} else {
				host = strings.TrimSpace(hp[0])
				portStr = hp[1]
			}
			if len(host) == 0 {
				host = "127.0.0.1"
			}
			port, err := strconv.Atoi(portStr)
			if err != nil {
				out.Printf("Failed to parse %q as HOST:PORT: %v", intercept.TargetHost, err)
				out.Send("failed", "parse target")
				out.SendExit(1)
				return nil
			}
			intercept.TargetHost = host
			intercept.TargetPort = port
			if err := d.AddIntercept(p, out, &intercept); err != nil {
				return err
			}
			return out.Err()
		},
	}
	interceptAddCmd.Flags().StringVarP(&intercept.Name, "name", "n", "", "a name for this intercept")
	interceptAddCmd.Flags().StringVarP(&intercept.Prefix, "prefix", "p", "", "prefix to intercept (default /)")
	interceptAddCmd.Flags().StringVarP(&intercept.TargetHost, "target", "t", "", "the [HOST:]PORT to forward to")
	_ = interceptAddCmd.MarkFlagRequired("target")
	interceptAddCmd.Flags().StringToStringVarP(&intercept.Patterns, "match", "m", nil, "match expression (HEADER=REGEX)")
	_ = interceptAddCmd.MarkFlagRequired("match")
	interceptAddCmd.Flags().StringVarP(&intercept.Namespace, "namespace", "", "", "Kubernetes namespace in which to create mapping for intercept")

	interceptCmd.AddCommand(interceptAddCmd)
	interceptCG := []CmdGroup{
		CmdGroup{
			GroupName: "Available Commands",
			CmdNames:  []string{"available", "list", "add", "remove"},
		},
	}
	interceptCmd.SetUsageFunc(NewCmdUsage(interceptCmd, interceptCG))
	rootCmd.AddCommand(interceptCmd)

	return rootCmd
}
<commit_msg>Edge Control: Fix typo in pause output<commit_after>package main

import (
	"fmt"
	"net"
	"strconv"
	"strings"
	"time"

	"github.com/spf13/cobra"

	"github.com/datawire/ambassador/pkg/supervisor"
)

func (d *Daemon) handleCommand(p *supervisor.Process, conn net.Conn, data *ClientMessage) error {
	out := NewEmitter(conn)
	rootCmd := d.getRootCommand(p, out, data)
	rootCmd.SetOutput(conn) // FIXME replace with SetOut and SetErr
	rootCmd.PersistentPreRun = func(cmd *cobra.Command, _ []string) {
		if batch, _ := cmd.Flags().GetBool("batch"); batch {
			out.SetKV()
		}
	}
	rootCmd.SetArgs(data.Args[1:])
	err := rootCmd.Execute()
	if err != nil {
		out.SendExit(1)
	}
	return out.Err()
}

func (d *Daemon) getRootCommand(p *supervisor.Process, out *Emitter, data *ClientMessage) *cobra.Command {
	rootCmd := &cobra.Command{
		Use:          "edgectl",
		Short:        "Edge Control",
		SilenceUsage: true, // https://github.com/spf13/cobra/issues/340
	}
	_ = rootCmd.PersistentFlags().Bool("batch", false, "Emit machine-readable output")
	_ = rootCmd.PersistentFlags().MarkHidden("batch")

	rootCmd.AddCommand(&cobra.Command{
		Use:   "version",
		Short: "Show program's version number and exit",
		Args:  cobra.ExactArgs(0),
		RunE: func(_ *cobra.Command, _ []string) error {
			out.Println("Client", data.ClientVersion)
			out.Println("Daemon", displayVersion)
			out.Send("daemon.version", Version)
			out.Send("daemon.apiVersion", apiVersion)
			return out.Err()
		},
	})
	rootCmd.AddCommand(&cobra.Command{
		Use:   "status",
		Short: "Show connectivity status",
		Args:  cobra.ExactArgs(0),
		RunE: func(_ *cobra.Command, _ []string) error {
			if err := d.Status(p, out); err != nil {
				return err
			}
			return out.Err()
		},
	})
	rootCmd.AddCommand(&cobra.Command{
		Use:   "pause",
		Short: "Turn off network overrides (to use a VPN)",
		Args:  cobra.ExactArgs(0),
		RunE: func(_ *cobra.Command, _ []string) error {
			if d.network == nil {
				out.Println("Network overrides are already paused")
				out.Send("paused", true)
				return out.Err()
			}
			if d.cluster != nil {
				out.Println("Edge Control is connected to a cluster.")
				out.Println("See \"edgectl status\" for details.")
				out.Println("Please disconnect before pausing.")
				out.Send("paused", false)
				out.SendExit(1)
				return out.Err()
			}

			if err := d.network.Close(); err != nil {
				p.Logf("pause: %v", err)
				out.Printf("Unexpected error while pausing: %v\n", err)
			}
			d.network = nil

			out.Println("Network overrides paused.")
			out.Println("Use \"edgectl resume\" to reestablish network overrides.")
			out.Send("paused", true)

			return out.Err()
		},
	})
	rootCmd.AddCommand(&cobra.Command{
		Use:     "resume",
		Short:   "Turn network overrides on (after using edgectl pause)",
		Aliases: []string{"unpause"},
		Args:    cobra.ExactArgs(0),
		RunE: func(_ *cobra.Command, _ []string) error {
			if d.network != nil {
				if d.network.IsOkay() {
					out.Println("Network overrides are established (not paused)")
				} else {
					out.Println("Network overrides are being reestablished...")
				}
				out.Send("paused", false)
				return out.Err()
			}

			if err := d.MakeNetOverride(p); err != nil {
				p.Logf("resume: %v", err)
				out.Printf("Unexpected error establishing network overrides: %v", err)
			}
			out.Send("paused", d.network == nil)

			return out.Err()
		},
	})
	connectCmd := &cobra.Command{
		Use:   "connect [flags] [-- additional kubectl arguments...]",
		Short: "Connect to a cluster",
		RunE: func(cmd *cobra.Command, args []string) error {
			context, _ := cmd.Flags().GetString("context")
			namespace, _ := cmd.Flags().GetString("namespace")
			managerNs, _ := cmd.Flags().GetString("manager-namespace")
			if err := d.Connect(p, out, data.RAI, context, namespace, managerNs, args); err != nil {
				return err
			}
			return out.Err()
		},
	}
	_ = connectCmd.Flags().StringP(
		"context", "c", "",
		"The Kubernetes context to use. Defaults to the current kubectl context.",
	)
	_ = connectCmd.Flags().StringP(
		"namespace", "n", "",
		"The Kubernetes namespace to use. Defaults to kubectl's default for the context.",
	)
	_ = connectCmd.Flags().StringP(
		"manager-namespace", "m", "ambassador",
		"The Kubernetes namespace in which the Traffic Manager is running.",
	)
	rootCmd.AddCommand(connectCmd)
	rootCmd.AddCommand(&cobra.Command{
		Use:   "disconnect",
		Short: "Disconnect from the connected cluster",
		Args:  cobra.ExactArgs(0),
		RunE: func(_ *cobra.Command, _ []string) error {
			if err := d.Disconnect(p, out); err != nil {
				return err
			}
			return out.Err()
		},
	})
	rootCmd.AddCommand(&cobra.Command{
		Use:   "quit",
		Short: "Tell Edge Control Daemon to quit (for upgrades)",
		Args:  cobra.ExactArgs(0),
		RunE: func(_ *cobra.Command, _ []string) error {
			out.Println("Edge Control Daemon quitting...")
			out.Send("quit", true)
			p.Supervisor().Shutdown()
			return out.Err()
		},
	})

	interceptCmd := &cobra.Command{
		Use: "intercept",
		Long: "Manage deployment intercepts. An intercept arranges for a subset of requests to be " +
			"diverted to the local machine.",
		Short: "Manage deployment intercepts",
	}
	interceptCmd.AddCommand(&cobra.Command{
		Use:     "available",
		Aliases: []string{"avail"},
		Short:   "List deployments available for intercept",
		Args:    cobra.ExactArgs(0),
		RunE: func(_ *cobra.Command, _ []string) error {
			msg := d.interceptMessage()
			if msg != "" {
				out.Println(msg)
				out.Send("intercept", msg)
				return out.Err()
			}
			out.Send("interceptable", len(d.trafficMgr.interceptables))
			switch {
			case len(d.trafficMgr.interceptables) == 0:
				out.Println("No interceptable deployments")
			default:
				out.Printf("Found %d interceptable deployment(s):\n", len(d.trafficMgr.interceptables))
				for idx, deployment := range d.trafficMgr.interceptables {
					fields := strings.SplitN(deployment, "/", 2)

					appName := fields[0]
					appNamespace := d.cluster.namespace

					if len(fields) > 1 {
						appNamespace = fields[0]
						appName = fields[1]
					}

					out.Printf("%4d. %s in namespace %s\n", idx+1, appName, appNamespace)
					out.Send(fmt.Sprintf("interceptable.deployment.%d", idx+1), deployment)
				}
			}
			return out.Err()
		},
	})

	interceptCmd.AddCommand(&cobra.Command{
		Use:   "list",
		Short: "List current intercepts",
		Args:  cobra.ExactArgs(0),
		RunE: func(_ *cobra.Command, _ []string) error {
			if err := d.ListIntercepts(p, out); err != nil {
				return err
			}
			return out.Err()
		},
	})
	interceptCmd.AddCommand(&cobra.Command{
		Use:   "remove",
		Short: "Deactivate and remove an existent intercept",
		Args:  cobra.MinimumNArgs(1),
		RunE: func(_ *cobra.Command, args []string) error {
			name := strings.TrimSpace(args[0])
			if err := d.RemoveIntercept(p, out, name); err != nil {
				return err
			}
			return out.Err()
		},
	})
	intercept := InterceptInfo{}
	interceptAddCmd := &cobra.Command{
		Use:   "add DEPLOYMENT -t [HOST:]PORT -m HEADER=REGEX ...",
		Short: "Add a deployment intercept",
		Args:  cobra.ExactArgs(1),
		RunE: func(_ *cobra.Command, args []string) error {
			intercept.Deployment = args[0]
			if intercept.Name == "" {
				intercept.Name = fmt.Sprintf("cept-%d", time.Now().Unix())
			}

			// if intercept.Namespace == "" {
			// 	intercept.Namespace = "default"
			// }

			if intercept.Prefix == "" {
				intercept.Prefix = "/"
			}

			var host, portStr string
			hp := strings.SplitN(intercept.TargetHost, ":", 2)
			if len(hp) < 2 {
				portStr = hp[0]
			} else {
				host = strings.TrimSpace(hp[0])
				portStr = hp[1]
			}
			if len(host) == 0 {
				host = "127.0.0.1"
			}
			port, err := strconv.Atoi(portStr)
			if err != nil {
				out.Printf("Failed to parse %q as HOST:PORT: %v", intercept.TargetHost, err)
				out.Send("failed", "parse target")
				out.SendExit(1)
				return nil
			}
			intercept.TargetHost = host
			intercept.TargetPort = port
			if err := d.AddIntercept(p, out, &intercept); err != nil {
				return err
			}
			return out.Err()
		},
	}
	interceptAddCmd.Flags().StringVarP(&intercept.Name, "name", "n", "", "a name for this intercept")
	interceptAddCmd.Flags().StringVarP(&intercept.Prefix, "prefix", "p", "", "prefix to intercept (default /)")
	interceptAddCmd.Flags().StringVarP(&intercept.TargetHost, "target", "t", "", "the [HOST:]PORT to forward to")
	_ = interceptAddCmd.MarkFlagRequired("target")
	interceptAddCmd.Flags().StringToStringVarP(&intercept.Patterns, "match", "m", nil, "match expression (HEADER=REGEX)")
	_ = interceptAddCmd.MarkFlagRequired("match")
	interceptAddCmd.Flags().StringVarP(&intercept.Namespace, "namespace", "", "", "Kubernetes namespace in which to create mapping for intercept")

	interceptCmd.AddCommand(interceptAddCmd)
	interceptCG := []CmdGroup{
		CmdGroup{
			GroupName: "Available Commands",
			CmdNames:  []string{"available", "list", "add", "remove"},
		},
	}
	interceptCmd.SetUsageFunc(NewCmdUsage(interceptCmd, interceptCG))
	rootCmd.AddCommand(interceptCmd)

	return rootCmd
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net/url"
	"os"
	"path"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/codegangsta/cli"
	"github.com/fsouza/go-dockerclient"
	"github.com/remind101/empire"
	"github.com/remind101/empire/server/github"
	"github.com/remind101/pkg/reporter"
	"github.com/remind101/pkg/reporter/hb"
)

const (
	FlagPort        = "port"
	FlagAutoMigrate = "automigrate"

	FlagGithubClient       = "github.client.id"
	FlagGithubClientSecret = "github.client.secret"
	FlagGithubOrg          = "github.organization"
	FlagGithubApiURL       = "github.api.url"

	FlagGithubWebhooksSecret           = "github.webhooks.secret"
	FlagGithubDeploymentsEnvironment   = "github.deployments.environment"
	FlagGithubDeploymentsImageTemplate = "github.deployments.template"
	FlagGithubDeploymentsTugboatURL    = "github.deployments.tugboat.url"

	FlagDBPath = "path"
	FlagDB     = "db"

	FlagDockerSocket = "docker.socket"
	FlagDockerCert   = "docker.cert"
	FlagDockerAuth   = "docker.auth"

	FlagAWSDebug       = "aws.debug"
	FlagECSCluster     = "ecs.cluster"
	FlagECSServiceRole = "ecs.service.role"

	FlagELBSGPrivate = "elb.sg.private"
	FlagELBSGPublic  = "elb.sg.public"

	FlagEC2SubnetsPrivate = "ec2.subnets.private"
	FlagEC2SubnetsPublic  = "ec2.subnets.public"

	FlagRoute53InternalZoneID = "route53.zoneid.internal"

	FlagSecret   = "secret"
	FlagReporter = "reporter"
	FlagRunner   = "runner"
)

// Commands are the subcommands that are available.
var Commands = []cli.Command{
	{
		Name:      "server",
		ShortName: "s",
		Usage:     "Run the empire HTTP api",
		Flags: append([]cli.Flag{
			cli.StringFlag{
				Name:   FlagPort,
				Value:  "8080",
				Usage:  "The port to run the server on",
				EnvVar: "EMPIRE_PORT",
			},
			cli.BoolFlag{
				Name:  FlagAutoMigrate,
				Usage: "Whether to run the migrations at startup or not",
			},
			cli.StringFlag{
				Name:   FlagGithubClient,
				Value:  "",
				Usage:  "The client id for the GitHub OAuth application",
				EnvVar: "EMPIRE_GITHUB_CLIENT_ID",
			},
			cli.StringFlag{
				Name:   FlagGithubClientSecret,
				Value:  "",
				Usage:  "The client secret for the GitHub OAuth application",
				EnvVar: "EMPIRE_GITHUB_CLIENT_SECRET",
			},
			cli.StringFlag{
				Name:   FlagGithubOrg,
				Value:  "",
				Usage:  "The organization to allow access to",
				EnvVar: "EMPIRE_GITHUB_ORGANIZATION",
			},
			cli.StringFlag{
				Name:   FlagGithubApiURL,
				Value:  "",
				Usage:  "The URL to use when talking to GitHub.",
				EnvVar: "EMPIRE_GITHUB_API_URL",
			},
			cli.StringFlag{
				Name:   FlagGithubWebhooksSecret,
				Value:  "",
				Usage:  "Shared secret between GitHub and Empire for signing webhooks.",
				EnvVar: "EMPIRE_GITHUB_WEBHOOKS_SECRET",
			},
			cli.StringFlag{
				Name:   FlagGithubDeploymentsEnvironment,
				Value:  "",
				Usage:  "If provided, only github deployments to the specified environment will be handled.",
				EnvVar: "EMPIRE_GITHUB_DEPLOYMENTS_ENVIRONMENT",
			},
			cli.StringFlag{
				Name:   FlagGithubDeploymentsImageTemplate,
				Value:  github.DefaultTemplate,
				Usage:  "A Go text/template that will be used to determine the docker image to deploy.",
				EnvVar: "EMPIRE_GITHUB_DEPLOYMENTS_IMAGE_TEMPLATE",
			},
			cli.StringFlag{
				Name:   FlagGithubDeploymentsTugboatURL,
				Value:  "",
				Usage:  "If provided, logs from deployments triggered via GitHub deployments will be sent to this tugboat instance.",
				EnvVar: "EMPIRE_TUGBOAT_URL",
			},
		}, append(EmpireFlags, DBFlags...)...),
		Action: runServer,
	},
	{
		Name:   "migrate",
		Usage:  "Migrate the database",
		Flags:  DBFlags,
		Action: runMigrate,
	},
}

var DBFlags = []cli.Flag{
	cli.StringFlag{
		Name:  FlagDBPath,
		Value: "./migrations",
		Usage: "Path to database migrations",
	},
	cli.StringFlag{
		Name:   FlagDB,
		Value:  "postgres://localhost/empire?sslmode=disable",
		Usage:  "SQL connection string for the database",
		EnvVar: "EMPIRE_DATABASE_URL",
	},
}

var EmpireFlags = []cli.Flag{
	cli.StringFlag{
		Name:   FlagDockerSocket,
		Value:  "unix:///var/run/docker.sock",
		Usage:  "The location of the docker api",
		EnvVar: "DOCKER_HOST",
	},
	cli.StringFlag{
		Name:   FlagDockerCert,
		Value:  "",
		Usage:  "If using TLS, a path to a certificate to use",
		EnvVar: "DOCKER_CERT_PATH",
	},
	cli.StringFlag{
		Name:   FlagDockerAuth,
		Value:  path.Join(os.Getenv("HOME"), ".dockercfg"),
		Usage:  "Path to a docker registry auth file (~/.dockercfg)",
		EnvVar: "DOCKER_AUTH_PATH",
	},
	cli.BoolFlag{
		Name:   FlagAWSDebug,
		Usage:  "Enable verbose debug output for AWS integration.",
		EnvVar: "EMPIRE_AWS_DEBUG",
	},
	cli.StringFlag{
		Name:   FlagECSCluster,
		Value:  "default",
		Usage:  "The ECS cluster to create services within",
		EnvVar: "EMPIRE_ECS_CLUSTER",
	},
	cli.StringFlag{
		Name:   FlagECSServiceRole,
		Value:  "ecsServiceRole",
		Usage:  "The IAM Role to use for managing ECS",
		EnvVar: "EMPIRE_ECS_SERVICE_ROLE",
	},
	cli.StringFlag{
		Name:   FlagELBSGPrivate,
		Value:  "",
		Usage:  "The ELB security group to assign private load balancers",
		EnvVar: "EMPIRE_ELB_SG_PRIVATE",
	},
	cli.StringFlag{
		Name:   FlagELBSGPublic,
		Value:  "",
		Usage:  "The ELB security group to assign public load balancers",
		EnvVar: "EMPIRE_ELB_SG_PUBLIC",
	},
	cli.StringSliceFlag{
		Name:   FlagEC2SubnetsPrivate,
		Value:  &cli.StringSlice{},
		Usage:  "The comma separated private subnet ids",
		EnvVar: "EMPIRE_EC2_SUBNETS_PRIVATE",
	},
	cli.StringSliceFlag{
		Name:   FlagEC2SubnetsPublic,
		Value:  &cli.StringSlice{},
		Usage:  "The comma separated public subnet ids",
		EnvVar: "EMPIRE_EC2_SUBNETS_PUBLIC",
	},
	cli.StringFlag{
		Name:   FlagSecret,
		Value:  "<change this>",
		Usage:  "The secret used to sign access tokens",
		EnvVar: "EMPIRE_TOKEN_SECRET",
	},
	cli.StringFlag{
		Name:   FlagReporter,
		Value:  "",
		Usage:  "The error reporter to use. (e.g. hb://api.honeybadger.io?key=<apikey>&environment=production)",
		EnvVar: "EMPIRE_REPORTER",
	},
	cli.StringFlag{
		Name:   FlagRunner,
		Value:  "",
		Usage:  "The location of the container runner api",
		EnvVar: "EMPIRE_RUNNER",
	},
	cli.StringFlag{
		Name:   FlagRoute53InternalZoneID,
		Value:  "",
		Usage:  "The route53 zone ID of the internal 'empire.' zone.",
		EnvVar: "EMPIRE_ROUTE53_INTERNAL_ZONE_ID",
	},
}

func main() {
	app := cli.NewApp()
	app.Name = "empire"
	app.Usage = "Platform as a Binary"
	app.Version = Version
	app.Commands = Commands

	app.Run(os.Args)
}

func newEmpire(c *cli.Context) (*empire.Empire, error) {
	opts := empire.Options{}

	opts.Docker.Socket = c.String(FlagDockerSocket)
	opts.Docker.CertPath = c.String(FlagDockerCert)
	opts.AWSConfig = aws.DefaultConfig
	if c.Bool(FlagAWSDebug) {
		opts.AWSConfig.LogLevel = 1
	}
	opts.ECS.Cluster = c.String(FlagECSCluster)
	opts.ECS.ServiceRole = c.String(FlagECSServiceRole)
	opts.ELB.InternalSecurityGroupID = c.String(FlagELBSGPrivate)
	opts.ELB.ExternalSecurityGroupID = c.String(FlagELBSGPublic)
	opts.ELB.InternalSubnetIDs = c.StringSlice(FlagEC2SubnetsPrivate)
	opts.ELB.ExternalSubnetIDs = c.StringSlice(FlagEC2SubnetsPublic)
	opts.ELB.InternalZoneID = c.String(FlagRoute53InternalZoneID)
	opts.DB = c.String(FlagDB)
	opts.Secret = c.String(FlagSecret)

	auth, err := dockerAuth(c.String(FlagDockerAuth))
	if err != nil {
		return nil, err
	}

	opts.Docker.Auth = auth

	e, err := empire.New(opts)
	if err != nil {
		return e, err
	}

	reporter, err := newReporter(c.String(FlagReporter))
	if err != nil {
		return e, err
	}

	e.Reporter = reporter

	return e, nil
}

func newReporter(u string) (reporter.Reporter, error) {
	if u == "" {
		return empire.DefaultReporter, nil
	}

	uri, err := url.Parse(u)
	if err != nil {
		return nil, err
	}

	switch uri.Scheme {
	case "hb":
		q := uri.Query()
		return newHBReporter(q.Get("key"), q.Get("environment"))
	default:
		panic(fmt.Errorf("unknown reporter: %s", u))
	}
}

func newHBReporter(key, env string) (reporter.Reporter, error) {
	r := hb.NewReporter(key)
	r.Environment = env

	// Append here because `go vet` will complain about unkeyed fields,
	// since it thinks MultiReporter is a struct literal.
	return append(reporter.MultiReporter{}, empire.DefaultReporter, r), nil
}

func dockerAuth(path string) (*docker.AuthConfigurations, error) {
	f, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	return docker.NewAuthConfigurations(f)
}
<commit_msg>Update package main to support new aws-sdk.<commit_after>package main

import (
	"fmt"
	"net/url"
	"os"
	"path"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/codegangsta/cli"
	"github.com/fsouza/go-dockerclient"
	"github.com/remind101/empire"
	"github.com/remind101/empire/server/github"
	"github.com/remind101/pkg/reporter"
	"github.com/remind101/pkg/reporter/hb"
)

const (
	FlagPort        = "port"
	FlagAutoMigrate = "automigrate"

	FlagGithubClient       = "github.client.id"
	FlagGithubClientSecret = "github.client.secret"
	FlagGithubOrg          = "github.organization"
	FlagGithubApiURL       = "github.api.url"

	FlagGithubWebhooksSecret           = "github.webhooks.secret"
	FlagGithubDeploymentsEnvironment   = "github.deployments.environment"
	FlagGithubDeploymentsImageTemplate = "github.deployments.template"
	FlagGithubDeploymentsTugboatURL    = "github.deployments.tugboat.url"

	FlagDBPath = "path"
	FlagDB     = "db"

	FlagDockerSocket = "docker.socket"
	FlagDockerCert   = "docker.cert"
	FlagDockerAuth   = "docker.auth"

	FlagAWSDebug       = "aws.debug"
	FlagECSCluster     = "ecs.cluster"
	FlagECSServiceRole = "ecs.service.role"

	FlagELBSGPrivate = "elb.sg.private"
	FlagELBSGPublic  = "elb.sg.public"

	FlagEC2SubnetsPrivate = "ec2.subnets.private"
	FlagEC2SubnetsPublic  = "ec2.subnets.public"

	FlagRoute53InternalZoneID = "route53.zoneid.internal"

	FlagSecret   = "secret"
	FlagReporter = "reporter"
	FlagRunner   = "runner"
)

// Commands are the subcommands that are available.
var Commands = []cli.Command{
	{
		Name:      "server",
		ShortName: "s",
		Usage:     "Run the empire HTTP api",
		Flags: append([]cli.Flag{
			cli.StringFlag{
				Name:   FlagPort,
				Value:  "8080",
				Usage:  "The port to run the server on",
				EnvVar: "EMPIRE_PORT",
			},
			cli.BoolFlag{
				Name:  FlagAutoMigrate,
				Usage: "Whether to run the migrations at startup or not",
			},
			cli.StringFlag{
				Name:   FlagGithubClient,
				Value:  "",
				Usage:  "The client id for the GitHub OAuth application",
				EnvVar: "EMPIRE_GITHUB_CLIENT_ID",
			},
			cli.StringFlag{
				Name:   FlagGithubClientSecret,
				Value:  "",
				Usage:  "The client secret for the GitHub OAuth application",
				EnvVar: "EMPIRE_GITHUB_CLIENT_SECRET",
			},
			cli.StringFlag{
				Name:   FlagGithubOrg,
				Value:  "",
				Usage:  "The organization to allow access to",
				EnvVar: "EMPIRE_GITHUB_ORGANIZATION",
			},
			cli.StringFlag{
				Name:   FlagGithubApiURL,
				Value:  "",
				Usage:  "The URL to use when talking to GitHub.",
				EnvVar: "EMPIRE_GITHUB_API_URL",
			},
			cli.StringFlag{
				Name:   FlagGithubWebhooksSecret,
				Value:  "",
				Usage:  "Shared secret between GitHub and Empire for signing webhooks.",
				EnvVar: "EMPIRE_GITHUB_WEBHOOKS_SECRET",
			},
			cli.StringFlag{
				Name:   FlagGithubDeploymentsEnvironment,
				Value:  "",
				Usage:  "If provided, only github deployments to the specified environment will be handled.",
				EnvVar: "EMPIRE_GITHUB_DEPLOYMENTS_ENVIRONMENT",
			},
			cli.StringFlag{
				Name:   FlagGithubDeploymentsImageTemplate,
				Value:  github.DefaultTemplate,
				Usage:  "A Go text/template that will be used to determine the docker image to deploy.",
				EnvVar: "EMPIRE_GITHUB_DEPLOYMENTS_IMAGE_TEMPLATE",
			},
			cli.StringFlag{
				Name:   FlagGithubDeploymentsTugboatURL,
				Value:  "",
				Usage:  "If provided, logs from deployments triggered via GitHub deployments will be sent to this tugboat instance.",
				EnvVar: "EMPIRE_TUGBOAT_URL",
			},
		}, append(EmpireFlags, DBFlags...)...),
		Action: runServer,
	},
	{
		Name:   "migrate",
		Usage:  "Migrate the database",
		Flags:  DBFlags,
		Action: runMigrate,
	},
}

var DBFlags = []cli.Flag{
	cli.StringFlag{
		Name:  FlagDBPath,
		Value: "./migrations",
		Usage: "Path to database migrations",
	},
	cli.StringFlag{
		Name:   FlagDB,
		Value:  "postgres://localhost/empire?sslmode=disable",
		Usage:  "SQL connection string for the database",
		EnvVar: "EMPIRE_DATABASE_URL",
	},
}

var EmpireFlags = []cli.Flag{
	cli.StringFlag{
		Name:   FlagDockerSocket,
		Value:  "unix:///var/run/docker.sock",
		Usage:  "The location of the docker api",
		EnvVar: "DOCKER_HOST",
	},
	cli.StringFlag{
		Name:   FlagDockerCert,
		Value:  "",
		Usage:  "If using TLS, a path to a certificate to use",
		EnvVar: "DOCKER_CERT_PATH",
	},
	cli.StringFlag{
		Name:   FlagDockerAuth,
		Value:  path.Join(os.Getenv("HOME"), ".dockercfg"),
		Usage:  "Path to a docker registry auth file (~/.dockercfg)",
		EnvVar: "DOCKER_AUTH_PATH",
	},
	cli.BoolFlag{
		Name:   FlagAWSDebug,
		Usage:  "Enable verbose debug output for AWS integration.",
		EnvVar: "EMPIRE_AWS_DEBUG",
	},
	cli.StringFlag{
		Name:   FlagECSCluster,
		Value:  "default",
		Usage:  "The ECS cluster to create services within",
		EnvVar: "EMPIRE_ECS_CLUSTER",
	},
	cli.StringFlag{
		Name:   FlagECSServiceRole,
		Value:  "ecsServiceRole",
		Usage:  "The IAM Role to use for managing ECS",
		EnvVar: "EMPIRE_ECS_SERVICE_ROLE",
	},
	cli.StringFlag{
		Name:   FlagELBSGPrivate,
		Value:  "",
		Usage:  "The ELB security group to assign private load balancers",
		EnvVar: "EMPIRE_ELB_SG_PRIVATE",
	},
	cli.StringFlag{
		Name:   FlagELBSGPublic,
		Value:  "",
		Usage:  "The ELB security group to assign public load balancers",
		EnvVar: "EMPIRE_ELB_SG_PUBLIC",
	},
	cli.StringSliceFlag{
		Name:   FlagEC2SubnetsPrivate,
		Value:  &cli.StringSlice{},
		Usage:  "The comma separated private subnet ids",
		EnvVar: "EMPIRE_EC2_SUBNETS_PRIVATE",
	},
	cli.StringSliceFlag{
		Name:   FlagEC2SubnetsPublic,
		Value:  &cli.StringSlice{},
		Usage:  "The comma separated public subnet ids",
		EnvVar: "EMPIRE_EC2_SUBNETS_PUBLIC",
	},
	cli.StringFlag{
		Name:   FlagSecret,
		Value:  "<change this>",
		Usage:  "The secret used to sign access tokens",
		EnvVar: "EMPIRE_TOKEN_SECRET",
	},
	cli.StringFlag{
		Name:   FlagReporter,
		Value:  "",
		Usage:  "The error reporter to use. (e.g. hb://api.honeybadger.io?key=<apikey>&environment=production)",
		EnvVar: "EMPIRE_REPORTER",
	},
	cli.StringFlag{
		Name:   FlagRunner,
		Value:  "",
		Usage:  "The location of the container runner api",
		EnvVar: "EMPIRE_RUNNER",
	},
	cli.StringFlag{
		Name:   FlagRoute53InternalZoneID,
		Value:  "",
		Usage:  "The route53 zone ID of the internal 'empire.' zone.",
		EnvVar: "EMPIRE_ROUTE53_INTERNAL_ZONE_ID",
	},
}

func main() {
	app := cli.NewApp()
	app.Name = "empire"
	app.Usage = "Platform as a Binary"
	app.Version = Version
	app.Commands = Commands

	app.Run(os.Args)
}

func newEmpire(c *cli.Context) (*empire.Empire, error) {
	opts := empire.Options{}

	opts.Docker.Socket = c.String(FlagDockerSocket)
	opts.Docker.CertPath = c.String(FlagDockerCert)
	opts.AWSConfig = aws.NewConfig()
	if c.Bool(FlagAWSDebug) {
		opts.AWSConfig.WithLogLevel(1)
	}
	opts.ECS.Cluster = c.String(FlagECSCluster)
	opts.ECS.ServiceRole = c.String(FlagECSServiceRole)
	opts.ELB.InternalSecurityGroupID = c.String(FlagELBSGPrivate)
	opts.ELB.ExternalSecurityGroupID = c.String(FlagELBSGPublic)
	opts.ELB.InternalSubnetIDs = c.StringSlice(FlagEC2SubnetsPrivate)
	opts.ELB.ExternalSubnetIDs = c.StringSlice(FlagEC2SubnetsPublic)
	opts.ELB.InternalZoneID = c.String(FlagRoute53InternalZoneID)
	opts.DB = c.String(FlagDB)
	opts.Secret = c.String(FlagSecret)

	auth, err := dockerAuth(c.String(FlagDockerAuth))
	if err != nil {
		return nil, err
	}

	opts.Docker.Auth = auth

	e, err := empire.New(opts)
	if err != nil {
		return e, err
	}

	reporter, err := newReporter(c.String(FlagReporter))
	if err != nil {
		return e, err
	}

	e.Reporter = reporter

	return e, nil
}

func newReporter(u string) (reporter.Reporter, error) {
	if u == "" {
		return empire.DefaultReporter, nil
	}

	uri, err := url.Parse(u)
	if err != nil {
		return nil, err
	}

	switch uri.Scheme {
	case "hb":
		q := uri.Query()
		return newHBReporter(q.Get("key"), q.Get("environment"))
	default:
		panic(fmt.Errorf("unknown reporter: %s", u))
	}
}

func newHBReporter(key, env string) (reporter.Reporter, error) {
	r := hb.NewReporter(key)
	r.Environment = env

	// Append here because `go vet` will complain about unkeyed fields,
	// since it thinks MultiReporter is a struct literal.
	return append(reporter.MultiReporter{}, empire.DefaultReporter, r), nil
}

func dockerAuth(path string) (*docker.AuthConfigurations, error) {
	f, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	return docker.NewAuthConfigurations(f)
}
<|endoftext|>


<commit_before>// Copyright (c) 2015-2021 MinIO, Inc.
//
// This file is part of MinIO Object Storage stack
//
// 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 <http://www.gnu.org/licenses/>.

package cmd

import (
	"context"
	"fmt"
	"strings"

	"github.com/fatih/color"
	"github.com/minio/cli"
	json "github.com/minio/colorjson"
	"github.com/minio/mc/pkg/probe"
	"github.com/minio/pkg/console"
)

var encryptSetCmd = cli.Command{
	Name:         "set",
	Usage:        "set encryption config",
	Action:       mainEncryptSet,
	OnUsageError: onUsageError,
	Before:       setGlobalsFromContext,
	Flags:        globalFlags,
	CustomHelpTemplate: `NAME:
  {{.HelpName}} - {{.Usage}}

USAGE:
  {{.HelpName}} TARGET

FLAGS:
  {{range .VisibleFlags}}{{.}}
  {{end}}
EXAMPLES:
  1. Enable SSE-S3 auto encryption on bucket "mybucket" for alias "myminio".
     {{.Prompt}} {{.HelpName}} sse-s3 myminio/mybucket

  2. Enable SSE-KMS auto encryption with kms key on bucket "mybucket" for alias "s3".
     {{.Prompt}} {{.HelpName}} sse-kms arn:aws:kms:us-east-1:xxx:key/xxx s3/mybucket
`,
}

// checkEncryptSetSyntax - validate all the passed arguments
func checkEncryptSetSyntax(ctx *cli.Context) {
	if len(ctx.Args()) < 2 || len(ctx.Args()) > 3 {
		showCommandHelpAndExit(ctx, 1) // last argument is exit code
	}
}

type encryptSetMessage struct {
	Op         string `json:"op"`
	Status     string `json:"status"`
	URL        string `json:"url"`
	Encryption struct {
		Algorithm string `json:"algorithm,omitempty"`
		KeyID     string `json:"keyId,omitempty"`
	} `json:"encryption,omitempty"`
}

func (v encryptSetMessage) JSON() string {
	v.Status = "success"
	jsonMessageBytes, e := json.MarshalIndent(v, "", " ")
	fatalIf(probe.NewError(e), "Unable to marshal into JSON.")
	return string(jsonMessageBytes)
}

func (v encryptSetMessage) String() string {
	return console.Colorize("encryptSetMessage", fmt.Sprintf("Auto encryption configuration has been set successfully for %s", v.URL))
}

func mainEncryptSet(cliCtx *cli.Context) error {
	ctx, cancelencryptSet := context.WithCancel(globalContext)
	defer cancelencryptSet()

	console.SetColor("encryptSetMessage", color.New(color.FgGreen))

	checkEncryptSetSyntax(cliCtx)

	// Get the alias parameter from cli
	args := cliCtx.Args()
	aliasedURL := args.Get(len(args) - 1)
	// Create a new Client
	client, err := newClient(aliasedURL)
	fatalIf(err, "Unable to initialize connection.")
	var algorithm, keyID string
	switch len(args) {
	case 3:
		algorithm = strings.ToLower(args[0])
		keyID = args[1]
	case 2:
		algorithm = strings.ToLower(args[0])
	}
	if algorithm != "sse-s3" && algorithm != "sse-kms" {
		fatalIf(probe.NewError(fmt.Errorf("Unknown argument `%s` passed", algorithm)), "Invalid encryption algorithm")
	}
	fatalIf(client.SetEncryption(ctx, algorithm, keyID), "Unable to enable auto encryption")
	msg := encryptSetMessage{
		Op:     cliCtx.Command.Name,
		Status: "success",
		URL:    aliasedURL,
	}
	msg.Encryption.Algorithm = algorithm
	printMsg(msg)
	return nil
}
<commit_msg>encrypt: remove sse-s3 example (#4357)<commit_after>// Copyright (c) 2015-2021 MinIO, Inc.
//
// This file is part of MinIO Object Storage stack
//
// 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 <http://www.gnu.org/licenses/>.

package cmd

import (
	"context"
	"fmt"
	"strings"

	"github.com/fatih/color"
	"github.com/minio/cli"
	json "github.com/minio/colorjson"
	"github.com/minio/mc/pkg/probe"
	"github.com/minio/pkg/console"
)

var encryptSetCmd = cli.Command{
	Name:         "set",
	Usage:        "set encryption config",
	Action:       mainEncryptSet,
	OnUsageError: onUsageError,
	Before:       setGlobalsFromContext,
	Flags:        globalFlags,
	CustomHelpTemplate: `NAME:
  {{.HelpName}} - {{.Usage}}

USAGE:
  {{.HelpName}} <sse-type> [<key-id>] TARGET

FLAGS:
  {{range .VisibleFlags}}{{.}}
  {{end}}
EXAMPLES:
  1. Enable SSE-KMS auto encryption with KMS key on bucket "mybucket" for alias "myminio".
     {{.Prompt}} {{.HelpName}} sse-kms my-minio-key myminio/mybucket

  2. Enable SSE-KMS auto encryption with KMS key on bucket "mybucket" for alias "s3".
     {{.Prompt}} {{.HelpName}} sse-kms arn:aws:kms:us-east-1:xxx:key/xxx s3/mybucket
`,
}

// checkEncryptSetSyntax - validate all the passed arguments
func checkEncryptSetSyntax(ctx *cli.Context) {
	if len(ctx.Args()) < 2 || len(ctx.Args()) > 3 {
		showCommandHelpAndExit(ctx, 1) // last argument is exit code
	}
}

type encryptSetMessage struct {
	Op         string `json:"op"`
	Status     string `json:"status"`
	URL        string `json:"url"`
	Encryption struct {
		Algorithm string `json:"algorithm,omitempty"`
		KeyID     string `json:"keyId,omitempty"`
	} `json:"encryption,omitempty"`
}

func (v encryptSetMessage) JSON() string {
	v.Status = "success"
	jsonMessageBytes, e := json.MarshalIndent(v, "", " ")
	fatalIf(probe.NewError(e), "Unable to marshal into JSON.")
	return string(jsonMessageBytes)
}

func (v encryptSetMessage) String() string {
	return console.Colorize("encryptSetMessage", fmt.Sprintf("Auto encryption configuration has been set successfully for %s", v.URL))
}

func mainEncryptSet(cliCtx *cli.Context) error {
	ctx, cancelencryptSet := context.WithCancel(globalContext)
	defer cancelencryptSet()

	console.SetColor("encryptSetMessage", color.New(color.FgGreen))

	checkEncryptSetSyntax(cliCtx)

	// Get the alias parameter from cli
	args := cliCtx.Args()
	aliasedURL := args.Get(len(args) - 1)
	// Create a new Client
	client, err := newClient(aliasedURL)
	fatalIf(err, "Unable to initialize connection.")
	var algorithm, keyID string
	switch len(args) {
	case 3:
		algorithm = strings.ToLower(args[0])
		keyID = args[1]
	case 2:
		algorithm = strings.ToLower(args[0])
	}
	if algorithm != "sse-s3" && algorithm != "sse-kms" {
		fatalIf(probe.NewError(fmt.Errorf("Unknown argument `%s` passed", algorithm)), "Invalid encryption algorithm")
	}
	fatalIf(client.SetEncryption(ctx, algorithm, keyID), "Unable to enable auto encryption")
	msg := encryptSetMessage{
		Op:     cliCtx.Command.Name,
		Status: "success",
		URL:    aliasedURL,
	}
	msg.Encryption.Algorithm = algorithm
	printMsg(msg)
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"archive/zip"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"

	"github.com/tormoder/fit/cmd/fitgen/internal/profile"
)

const fitPkgImportPath = "github.com/tormoder/fit"

const (
	workbookNameXLS  = "Profile.xls"
	workbookNameXLSX = "Profile.xlsx"
)

func main() {
	l := log.New(os.Stdout, "fitgen:\t", 0)

	fitSrcDir, err := goPackagePath(fitPkgImportPath)
	if err != nil {
		l.Fatalf("can't find fit package root src directory for %q", fitPkgImportPath)
	}
	l.Println("root src directory:", fitSrcDir)

	var (
		messagesOut    = filepath.Join(fitSrcDir, "messages.go")
		typesOut       = filepath.Join(fitSrcDir, "types.go")
		profileOut     = filepath.Join(fitSrcDir, "profile.go")
		stringerPath   = filepath.Join(fitSrcDir, "cmd/stringer/stringer.go")
		typesStringOut = filepath.Join(fitSrcDir, "types_string.go")
	)

	sdkOverride := flag.String(
		"sdk",
		"",
		"provide or override SDK version printed in generated code",
	)
	timestamp := flag.Bool(
		"timestamp",
		false,
		"add generation timestamp to generated code",
	)
	runTests := flag.Bool(
		"test",
		false,
		"run all tests in fit repository after code has been generated",
	)
	runInstall := flag.Bool(
		"install",
		false,
		"run go install before invoking stringer (go/types related, see golang issue #11415)",
	)

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: fitgen [flags] [path to sdk zip, xls or xlsx file]\n")
		flag.PrintDefaults()
	}

	flag.Parse()
	if flag.NArg() != 1 {
		flag.Usage()
		os.Exit(2)
	}

	var (
		inputData []byte
		input     = flag.Arg(0)
		inputExt  = filepath.Ext(input)
	)

	switch inputExt {
	case ".zip":
		inputData, err = readDataFromZIP(input)
	case ".xls", ".xlsx":
		inputData, err = readDataFromXLSX(input)
		if *sdkOverride == "" {
			log.Fatal("-sdk flag required if input is .xls(x)")
		}
	default:
		l.Fatalln("input file must be of type [.zip | .xls | .xlsx], got:", inputExt)
	}
	if err != nil {
		l.Fatal(err)
	}

	var genOptions []profile.GeneratorOption
	genOptions = append(
		genOptions,
		profile.WithGenerationTimestamp(*timestamp),
		profile.WithLogger(l),
	)

	var sdkString string
	if *sdkOverride != "" {
		sdkString = *sdkOverride
	} else {
		sdkString = parseSDKVersionStringFromZipFilePath(input)
	}

	sdkMaj, sdkMin, err := parseMajorAndMinorSDKVersion(sdkString)
	if err != nil {
		l.Fatalln("error parsing sdk version:", err)
	}

	generator, err := profile.NewGenerator(sdkMaj, sdkMin, inputData, genOptions...)
	if err != nil {
		l.Fatal(err)
	}

	fitProfile, err := generator.GenerateProfile()
	if err != nil {
		l.Fatal(err)
	}

	if err = ioutil.WriteFile(typesOut, fitProfile.TypesSource, 0644); err != nil {
		l.Fatalf("typegen: error writing types output file: %v", err)
	}

	if err = ioutil.WriteFile(messagesOut, fitProfile.MessagesSource, 0644); err != nil {
		l.Fatalf("typegen: error writing messages output file: %v", err)
	}

	if err = ioutil.WriteFile(profileOut, fitProfile.ProfileSource, 0644); err != nil {
		l.Fatalf("typegen: error writing profile output file: %v", err)
	}

	if *runInstall {
		l.Println("running go install (for go/types in stringer)")
		err = runGoInstall(fitPkgImportPath)
		if err != nil {
			l.Fatal(err)
		}
	}

	l.Println("running stringer")
	err = runStringerOnTypes(stringerPath, fitSrcDir, typesStringOut, fitProfile.StringerInput)
	if err != nil {
		l.Fatal(err)
	}
	l.Println("stringer: types done")

	logMesgNumVsMessages(fitProfile.MesgNumsWithoutMessage, l)

	if *runTests {
		err = runAllTests(fitPkgImportPath)
		if err != nil {
			l.Fatal(err)
		}
		l.Println("go test: pass")
	}

	l.Println("done")
}

func runGoInstall(pkgDir string) error {
	listCmd := exec.Command("go", "install", pkgDir+"/...")
	output, err := listCmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("go install: fail: %v\n%s", err, output)
	}
	return nil
}

func runStringerOnTypes(stringerPath, fitSrcDir, typesStringOut, fitTypes string) error {
	stringerCmd := exec.Command(
		"go",
		"run",
		stringerPath,
		"-trimprefix",
		"-type", fitTypes,
		"-output",
		typesStringOut,
		fitSrcDir,
	)

	output, err := stringerCmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("stringer: error running on types: %v\n%s", err, output)
	}

	return nil
}

func runAllTests(pkgDir string) error {
	listCmd := exec.Command("go", "list", pkgDir+"/...")
	output, err := listCmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("go list: fail: %v\n%s", err, output)
	}

	splitted := strings.Split(string(output), "\n")
	var goTestArgs []string
	// Command
	goTestArgs = append(goTestArgs, "test")
	// Packages
	for _, s := range splitted {
		if strings.Contains(s, "/vendor/") {
			continue
		}
		goTestArgs = append(goTestArgs, s)
	}

	testCmd := exec.Command("go", goTestArgs...)
	output, err = testCmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("go test: fail: %v\n%s", err, output)
	}

	return nil
}

func logMesgNumVsMessages(msgs []string, l *log.Logger) {
	if len(msgs) == 0 {
		return
	}
	l.Println("mesgnum-vs-msgs: implementation detail below, this may be automated in the future")
	l.Println("mesgnum-vs-msgs: #mesgnum values != #generated messages, diff:", len(msgs))
	l.Println("mesgnum-vs-msgs: remember to verify map in codegen.go for the following message(s):")
	for _, msg := range msgs {
		l.Printf("mesgnum-vs-msgs: ----> mesgnum %q has no corresponding message\n", msg)
	}
}

func goPackagePath(pkg string) (path string, err error) {
	gp := os.Getenv("GOPATH")
	if gp == "" {
		return path, os.ErrNotExist
	}
	for _, p := range filepath.SplitList(gp) {
		dir := filepath.Join(p, "src", filepath.FromSlash(pkg))
		fi, err := os.Stat(dir)
		if os.IsNotExist(err) {
			continue
		}
		if err != nil {
			return "", err
		}
		if !fi.IsDir() {
			continue
		}
		return dir, nil
	}
	return path, os.ErrNotExist
}

func readDataFromZIP(path string) ([]byte, error) {
	r, err := zip.OpenReader(path)
	if err != nil {
		return nil, fmt.Errorf("error opening sdk zip file: %v", err)
	}
	defer r.Close()

	var wfile *zip.File
	for _, f := range r.File {
		if f.Name == workbookNameXLS {
			wfile = f
			break
		}
		if f.Name == workbookNameXLSX {
			wfile = f
			break
		}
	}
	if wfile == nil {
		return nil, fmt.Errorf(
			"no file named %q or %q found in zip archive",
			workbookNameXLS, workbookNameXLSX,
		)
	}

	rc, err := wfile.Open()
	if err != nil {
		return nil, fmt.Errorf("error opening zip archive: %v", err)
	}
	defer rc.Close()

	data, err := ioutil.ReadAll(rc)
	if err != nil {
		return nil, fmt.Errorf("error reading %q from archive: %v", wfile.Name, err)
	}

	return data, nil
}

func readDataFromXLSX(path string) ([]byte, error) {
	return ioutil.ReadFile(path)
}

func parseSDKVersionStringFromZipFilePath(path string) string {
	_, file := filepath.Split(path)
	ver := strings.TrimSuffix(file, ".zip")
	return strings.TrimPrefix(ver, "FitSDKRelease_")
}

func parseMajorAndMinorSDKVersion(sdkString string) (int, int, error) {
	splitted := strings.Split(sdkString, ".")
	if len(splitted) < 2 {
		return 0, 0, fmt.Errorf("could not parse major/minor version from input: %q", sdkString)
	}

	maj, err := strconv.Atoi(splitted[0])
	if err != nil {
		return 0, 0, fmt.Errorf("could not parse major version from input: %q", splitted[0])
	}

	min, err := strconv.Atoi(splitted[1])
	if err != nil {
		return 0, 0, fmt.Errorf("could not parse minor version from input: %q", splitted[1])
	}

	return maj, min, nil
}
<commit_msg>cmd/fitgen: update mesg number vs messages log statement<commit_after>package main

import (
	"archive/zip"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"

	"github.com/tormoder/fit/cmd/fitgen/internal/profile"
)

const fitPkgImportPath = "github.com/tormoder/fit"

const (
	workbookNameXLS  = "Profile.xls"
	workbookNameXLSX = "Profile.xlsx"
)

func main() {
	l := log.New(os.Stdout, "fitgen:\t", 0)

	fitSrcDir, err := goPackagePath(fitPkgImportPath)
	if err != nil {
		l.Fatalf("can't find fit package root src directory for %q", fitPkgImportPath)
	}
	l.Println("root src directory:", fitSrcDir)

	var (
		messagesOut    = filepath.Join(fitSrcDir, "messages.go")
		typesOut       = filepath.Join(fitSrcDir, "types.go")
		profileOut     = filepath.Join(fitSrcDir, "profile.go")
		stringerPath   = filepath.Join(fitSrcDir, "cmd/stringer/stringer.go")
		typesStringOut = filepath.Join(fitSrcDir, "types_string.go")
	)

	sdkOverride := flag.String(
		"sdk",
		"",
		"provide or override SDK version printed in generated code",
	)
	timestamp := flag.Bool(
		"timestamp",
		false,
		"add generation timestamp to generated code",
	)
	runTests := flag.Bool(
		"test",
		false,
		"run all tests in fit repository after code has been generated",
	)
	runInstall := flag.Bool(
		"install",
		false,
		"run go install before invoking stringer (go/types related, see golang issue #11415)",
	)

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: fitgen [flags] [path to sdk zip, xls or xlsx file]\n")
		flag.PrintDefaults()
	}

	flag.Parse()
	if flag.NArg() != 1 {
		flag.Usage()
		os.Exit(2)
	}

	var (
		inputData []byte
		input     = flag.Arg(0)
		inputExt  = filepath.Ext(input)
	)

	switch inputExt {
	case ".zip":
		inputData, err = readDataFromZIP(input)
	case ".xls", ".xlsx":
		inputData, err = readDataFromXLSX(input)
		if *sdkOverride == "" {
			log.Fatal("-sdk flag required if input is .xls(x)")
		}
	default:
		l.Fatalln("input file must be of type [.zip | .xls | .xlsx], got:", inputExt)
	}
	if err != nil {
		l.Fatal(err)
	}

	var genOptions []profile.GeneratorOption
	genOptions = append(
		genOptions,
		profile.WithGenerationTimestamp(*timestamp),
		profile.WithLogger(l),
	)

	var sdkString string
	if *sdkOverride != "" {
		sdkString = *sdkOverride
	} else {
		sdkString = parseSDKVersionStringFromZipFilePath(input)
	}

	sdkMaj, sdkMin, err := parseMajorAndMinorSDKVersion(sdkString)
	if err != nil {
		l.Fatalln("error parsing sdk version:", err)
	}

	generator, err := profile.NewGenerator(sdkMaj, sdkMin, inputData, genOptions...)
	if err != nil {
		l.Fatal(err)
	}

	fitProfile, err := generator.GenerateProfile()
	if err != nil {
		l.Fatal(err)
	}

	if err = ioutil.WriteFile(typesOut, fitProfile.TypesSource, 0644); err != nil {
		l.Fatalf("typegen: error writing types output file: %v", err)
	}

	if err = ioutil.WriteFile(messagesOut, fitProfile.MessagesSource, 0644); err != nil {
		l.Fatalf("typegen: error writing messages output file: %v", err)
	}

	if err = ioutil.WriteFile(profileOut, fitProfile.ProfileSource, 0644); err != nil {
		l.Fatalf("typegen: error writing profile output file: %v", err)
	}

	if *runInstall {
		l.Println("running go install (for go/types in stringer)")
		err = runGoInstall(fitPkgImportPath)
		if err != nil {
			l.Fatal(err)
		}
	}

	l.Println("running stringer")
	err = runStringerOnTypes(stringerPath, fitSrcDir, typesStringOut, fitProfile.StringerInput)
	if err != nil {
		l.Fatal(err)
	}
	l.Println("stringer: types done")

	logMesgNumVsMessages(fitProfile.MesgNumsWithoutMessage, l)

	if *runTests {
		err = runAllTests(fitPkgImportPath)
		if err != nil {
			l.Fatal(err)
		}
		l.Println("go test: pass")
	}

	l.Println("done")
}

func runGoInstall(pkgDir string) error {
	listCmd := exec.Command("go", "install", pkgDir+"/...")
	output, err := listCmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("go install: fail: %v\n%s", err, output)
	}
	return nil
}

func runStringerOnTypes(stringerPath, fitSrcDir, typesStringOut, fitTypes string) error {
	stringerCmd := exec.Command(
		"go",
		"run",
		stringerPath,
		"-trimprefix",
		"-type", fitTypes,
		"-output",
		typesStringOut,
		fitSrcDir,
	)

	output, err := stringerCmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("stringer: error running on types: %v\n%s", err, output)
	}

	return nil
}

func runAllTests(pkgDir string) error {
	listCmd := exec.Command("go", "list", pkgDir+"/...")
	output, err := listCmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("go list: fail: %v\n%s", err, output)
	}

	splitted := strings.Split(string(output), "\n")
	var goTestArgs []string
	// Command
	goTestArgs = append(goTestArgs, "test")
	// Packages
	for _, s := range splitted {
		if strings.Contains(s, "/vendor/") {
			continue
		}
		goTestArgs = append(goTestArgs, s)
	}

	testCmd := exec.Command("go", goTestArgs...)
	output, err = testCmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("go test: fail: %v\n%s", err, output)
	}

	return nil
}

func logMesgNumVsMessages(msgs []string, l *log.Logger) {
	if len(msgs) == 0 {
		return
	}
	l.Println("mesgnum-vs-msgs: implementation detail below, this may be automated in the future")
	l.Println("mesgnum-vs-msgs: #mesgnum values != #generated messages, diff:", len(msgs))
	l.Println("mesgnum-vs-msgs: remember to add/verify map entries for sdk in sdk.go for the following message(s):")
	for _, msg := range msgs {
		l.Printf("mesgnum-vs-msgs: ----> mesgnum %q has no corresponding message\n", msg)
	}
}

func goPackagePath(pkg string) (path string, err error) {
	gp := os.Getenv("GOPATH")
	if gp == "" {
		return path, os.ErrNotExist
	}
	for _, p := range filepath.SplitList(gp) {
		dir := filepath.Join(p, "src", filepath.FromSlash(pkg))
		fi, err := os.Stat(dir)
		if os.IsNotExist(err) {
			continue
		}
		if err != nil {
			return "", err
		}
		if !fi.IsDir() {
			continue
		}
		return dir, nil
	}
	return path, os.ErrNotExist
}

func readDataFromZIP(path string) ([]byte, error) {
	r, err := zip.OpenReader(path)
	if err != nil {
		return nil, fmt.Errorf("error opening sdk zip file: %v", err)
	}
	defer r.Close()

	var wfile *zip.File
	for _, f := range r.File {
		if f.Name == workbookNameXLS {
			wfile = f
			break
		}
		if f.Name == workbookNameXLSX {
			wfile = f
			break
		}
	}
	if wfile == nil {
		return nil, fmt.Errorf(
			"no file named %q or %q found in zip archive",
			workbookNameXLS, workbookNameXLSX,
		)
	}

	rc, err := wfile.Open()
	if err != nil {
		return nil, fmt.Errorf("error opening zip archive: %v", err)
	}
	defer rc.Close()

	data, err := ioutil.ReadAll(rc)
	if err != nil {
		return nil, fmt.Errorf("error reading %q from archive: %v", wfile.Name, err)
	}

	return data, nil
}

func readDataFromXLSX(path string) ([]byte, error) {
	return ioutil.ReadFile(path)
}

func parseSDKVersionStringFromZipFilePath(path string) string {
	_, file := filepath.Split(path)
	ver := strings.TrimSuffix(file, ".zip")
	return strings.TrimPrefix(ver, "FitSDKRelease_")
}

func parseMajorAndMinorSDKVersion(sdkString string) (int, int, error) {
	splitted := strings.Split(sdkString, ".")
	if len(splitted) < 2 {
		return 0, 0, fmt.Errorf("could not parse major/minor version from input: %q", sdkString)
	}

	maj, err := strconv.Atoi(splitted[0])
	if err != nil {
		return 0, 0, fmt.Errorf("could not parse major version from input: %q", splitted[0])
	}

	min, err := strconv.Atoi(splitted[1])
	if err != nil {
		return 0, 0, fmt.Errorf("could not parse minor version from input: %q", splitted[1])
	}

	return maj, min, nil
}
<|endoftext|>


<commit_before>package main

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

	"github.com/constabulary/gb"
	"github.com/constabulary/gb/cmd"
)

func init() {
	registerCommand(GenerateCmd)
}

var GenerateCmd = &cmd.Command{
	Name:      "generate",
	UsageLine: "generate",
	Short:     "generate Go files by processing source",
	Long: `Generate runs commands described by directives within existing files.
Those commands can run any process but the intent is to create or update Go
source files, for instance by running yacc.

See 'go help generate'`,
	Run: func(ctx *gb.Context, args []string) error {
		env := cmd.MergeEnv(os.Environ(), map[string]string{
			"GOPATH": fmt.Sprintf("%s:%s", ctx.Projectdir(), filepath.Join(ctx.Projectdir(), "vendor")),
		})

		args = []string{filepath.Join(ctx.GOROOT, "bin", "go"), "generate"}

		cmd := exec.Cmd{
			Path: args[0],
			Args: args,
			Env:  env,

			Stdin:  os.Stdin,
			Stdout: os.Stdout,
			Stderr: os.Stderr,
		}

		return cmd.Run()
	},
}
<commit_msg>Fix the gb generate to use the arguments it's been given<commit_after>package main

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

	"github.com/constabulary/gb"
	"github.com/constabulary/gb/cmd"
)

func init() {
	registerCommand(GenerateCmd)
}

var GenerateCmd = &cmd.Command{
	Name:      "generate",
	UsageLine: "generate",
	Short:     "generate Go files by processing source",
	Long: `Generate runs commands described by directives within existing files.
Those commands can run any process but the intent is to create or update Go
source files, for instance by running yacc.

See 'go help generate'`,
	Run: func(ctx *gb.Context, args []string) error {
		env := cmd.MergeEnv(os.Environ(), map[string]string{
			"GOPATH": fmt.Sprintf("%s:%s", ctx.Projectdir(), filepath.Join(ctx.Projectdir(), "vendor")),
		})

		args = append([]string{filepath.Join(ctx.GOROOT, "bin", "go"), "generate"}, args...)

		cmd := exec.Cmd{
			Path: args[0],
			Args: args,
			Env:  env,

			Stdin:  os.Stdin,
			Stdout: os.Stdout,
			Stderr: os.Stderr,
		}

		return cmd.Run()
	},
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"fmt"
	"os"
	"strings"
)

type CmdShell struct {
	cmdQueryBase
}

func (c *CmdShell) Execute(args []string) error {
	if err := c.validate(); err != nil {
		return err
	}

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

	fmt.Print(`
           gitQL SHELL
           -----------
You must end your queries with ';'

`)

	s := bufio.NewScanner(os.Stdin)

	s.Split(scanQueries)

	for {
		fmt.Print("!> ")

		if !s.Scan() {
			break
		}

		query := s.Text()

		query = strings.Replace(query, "\n", " ", -1)
		query = strings.TrimSpace(query)

		fmt.Printf("\n--> Executing query: %s\n\n", query)

		schema, rowIter, err := c.executeQuery(query)
		if err != nil {
			c.printError(err)
			continue
		}

		if err := c.printQuery(schema, rowIter, "pretty"); err != nil {
			c.printError(err)
		}
	}

	return s.Err()
}

func (c *CmdShell) printError(err error) {
	fmt.Printf("ERROR: %v\n\n", err)
}

func scanQueries(data []byte, atEOF bool) (int, []byte, error) {
	if atEOF && len(data) == 0 {
		return 0, nil, nil
	}
	if i := bytes.IndexByte(data, ';'); i >= 0 {
		// We have a full newline-terminated line.
		return i + 1, dropCR(data[0:i]), nil
	}
	// If we're at EOF, we have a final, non-terminated line. Return it.
	if atEOF {
		return len(data), dropCR(data), nil
	}
	// Request more data.
	return 0, nil, nil
}

// dropCR drops a terminal \r from the data.
func dropCR(data []byte) []byte {
	if len(data) > 0 && data[len(data)-1] == '\r' {
		return data[0 : len(data)-1]
	}
	return data
}
<commit_msg>cmd: Use readline library. (#98)<commit_after>package main

import (
	"fmt"
	"strings"

	"github.com/chzyer/readline"
)

const (
	initPrompt      = "!> "
	multilinePrompt = "!>>> "
)

type CmdShell struct {
	cmdQueryBase
}

func (c *CmdShell) Execute(args []string) error {
	if err := c.validate(); err != nil {
		return err
	}

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

	rl, err := readline.NewEx(&readline.Config{
		Prompt:                 initPrompt,
		HistoryFile:            "/tmp/gitql-history",
		DisableAutoSaveHistory: true,
	})
	if err != nil {
		return err
	}

	rl.Terminal.Print(fmt.Sprint(`
           gitQL SHELL
           -----------
You must end your queries with ';'

`))

	var cmds []string
	for {
		line, err := rl.Readline()
		if err != nil {
			break
		}
		line = strings.TrimSpace(line)
		if len(line) == 0 {
			continue
		}
		cmds = append(cmds, line)
		if !strings.HasSuffix(line, ";") {
			rl.SetPrompt(multilinePrompt)
			continue
		}

		query := strings.Join(cmds, " ")
		cmds = cmds[:0]
		rl.SetPrompt(initPrompt)
		rl.SaveHistory(query)

		rl.Terminal.Print(fmt.Sprintf("\n--> Executing query: %s\n\n", query))

		schema, rowIter, err := c.executeQuery(query)
		if err != nil {
			rl.Terminal.Print(fmt.Sprintf("ERROR: %v\n\n", err))
			continue
		}

		if err := c.printQuery(schema, rowIter, "pretty"); err != nil {
			rl.Terminal.Print(fmt.Sprintf("ERROR: %v\n\n", err))
			continue
		}
	}

	return rl.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.

// Labels converts comma-separated-value records to PostScript mailing labels.
// The output is formatted for 8½"×11" sheets containing thirty 2⅝"x1" labels each,
// such as the Avery 5160.
//
//	usage: labels [options] [file...]
//
// Converts CSV records to PostScript mailing labels, using the first three fields
// of each input record as the address.
//
// The options are:
//
// 	-f font
// 		Use the named PostScript font (default Times-Roman)
// 	-m regexp
// 		Only use input records matching regexp.
// 		The text being matched is the record with commas separating fields,
// 		with no quotation marks added.
// 	-o outfile
// 		Write labels to outfile (default standard output)
// 	-p size
// 		Use text with the given point size (default 12)
// 	-v vsize
// 		Use lines of text vsize points apart (default 1.2 * text size)
// 	-x regexp
// 		Exclude input records matching regexp.
//
// If the first line of the CSV contains the text "address" (case insensitive),
// it is assumed to be a header for the spreadsheet and is skipped.
//
// Example
//
// Used with googlecsv, labels can take Google spreadsheets as input:
//
//	googlecsv 'Mailing List' | labels -f FournierMT-RegularSC > labels.ps
//
package main

import (
	"bytes"
	"encoding/csv"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"regexp"
	"strings"
)

func usage() {
	fmt.Fprintf(os.Stderr, `usage: labels [options] [file...]

Converts CSV records to PostScript mailing labels, using the first three fields
of each input record as the address.

The options are:

	-f font
		Use the named PostScript font (default Times-Roman)
	-m regexp
		Only use input records matching regexp.
		The text being matched is the record with commas separating fields,
		with no quotation marks added.
	-o outfile
		Write labels to outfile (default standard output)
	-p size
		Use text with the given point size (default 12)
	-v vsize
		Use lines of text vsize points apart (default 1.2 * text size)
	-x regexp
		Exclude input records matching regexp.

If the first line of the CSV contains the text "address" (case insensitive),
it is assumed to be a header for the spreadsheet and is skipped.
`)
	os.Exit(2)
}

var (
	font    = flag.String("f", "Times-Bold", "")
	outfile = flag.String("o", "", "")
	ps      = flag.Int("p", 12, "")
	vs      = flag.Int("v", 0, "")
	match   = flag.String("m", "match", "")
	exclude = flag.String("x", "exclude", "")

	matchRE   *regexp.Regexp
	excludeRE *regexp.Regexp
)

func main() {
	log.SetFlags(0)
	flag.Usage = usage
	flag.Parse()

	var input [][]string
	if flag.NArg() == 0 {
		input = readCSV("standard input", os.Stdin)
	} else {
		for _, file := range flag.Args() {
			f, err := os.Open(file)
			if err != nil {
				log.Fatal(err)
			}
			input = append(input, readCSV(file, f)...)
			f.Close()
		}
	}

	if len(input) > 0 && strings.Contains(strings.ToLower(strings.Join(input[0], ",")), "address") {
		// assume this is a heading line
		input = input[1:]
	}

	var buf bytes.Buffer
	if *vs == 0 {
		*vs = (*ps*12 + 5) / 10
	}
	fmt.Fprintf(&buf, prolog, *font, *ps, *vs)

	nlabel := 0
	for _, line := range input {
		if len(line) == 0 {
			continue
		}
		join := strings.Join(line, ",")
		if matchRE != nil && !matchRE.MatchString(join) ||
			excludeRE != nil && excludeRE.MatchString(join) {
			continue
		}

		mark := "mark"
		for i, field := range line {
			if i >= 3 {
				break
			}
			field = strings.TrimSpace(field)
			if field == "" {
				continue
			}
			field = strings.Replace(field, "(", `\(`, -1)
			field = strings.Replace(field, ")", `\)`, -1)
			fmt.Fprintf(&buf, "%s (%s)", mark, field)
			mark = ""
		}
		if mark == "" {
			nlabel++
			fmt.Fprintf(&buf, " label\n")
		}
	}
	fmt.Fprintf(&buf, "endlabels\n")

	if nlabel == 0 {
		log.Fatal("no labels to create")
	}

	os.Stdout.Write(buf.Bytes())
}

func readCSV(name string, r io.Reader) [][]string {
	rr := csv.NewReader(r)
	rr.FieldsPerRecord = -1
	recs, err := rr.ReadAll()
	if err != nil {
		log.Fatalf("parsing %s: %v", name, err)
	}
	return recs
}

const prolog = `%%!PS-Adobe-2.0

/numlabel 0 def
/%s findfont
/ps %d def
/vs %d def
dup length dict begin
  {1 index /FID ne {def} {pop pop} ifelse} forall
  /Encoding ISOLatin1Encoding def
  currentdict
end
/MyFont exch definefont pop
/MyFont findfont ps scalefont setfont

/inch { 72 mul } bind def

/label {
	numlabel 3 mod 2.75 mul 0.125 add 2.625 2 div add inch
	11 numlabel 3 idiv 1 mul 0.5 add 1 2 div add sub inch
	moveto
	0 counttomark vs mul ps add vs sub -2 div rmoveto
	/max 0 def
	counttomark -1 1 {
		1 sub index stringwidth pop
		dup max gt { /max exch def } { pop } ifelse
	} for
	max 2.625 inch gt { /max 2.625 inch def } if
	max -2 div 0 rmoveto

	counttomark -1 1 {
		pop
		gsave 0 ps rmoveto show grestore
		0 vs rmoveto
	} for
	pop

	/numlabel numlabel 1 add def
	numlabel 30 ge {
		showpage
		/numlabel 0 def
	} if
} def

/endlabels {
	numlabel 0 gt { showpage } if
} def

`
<commit_msg>labels: handle newline in field<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.

// Labels converts comma-separated-value records to PostScript mailing labels.
// The output is formatted for 8½"×11" sheets containing thirty 2⅝"x1" labels each,
// such as the Avery 5160.
//
//	usage: labels [options] [file...]
//
// Converts CSV records to PostScript mailing labels, using the first three fields
// of each input record as the address.
//
// The options are:
//
// 	-f font
// 		Use the named PostScript font (default Times-Roman)
// 	-m regexp
// 		Only use input records matching regexp.
// 		The text being matched is the record with commas separating fields,
// 		with no quotation marks added.
// 	-o outfile
// 		Write labels to outfile (default standard output)
// 	-p size
// 		Use text with the given point size (default 12)
// 	-v vsize
// 		Use lines of text vsize points apart (default 1.2 * text size)
// 	-x regexp
// 		Exclude input records matching regexp.
//
// If the first line of the CSV contains the text "address" (case insensitive),
// it is assumed to be a header for the spreadsheet and is skipped.
//
// Example
//
// Used with googlecsv, labels can take Google spreadsheets as input:
//
//	googlecsv 'Mailing List' | labels -f FournierMT-RegularSC > labels.ps
//
package main

import (
	"bytes"
	"encoding/csv"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"regexp"
	"strings"
)

func usage() {
	fmt.Fprintf(os.Stderr, `usage: labels [options] [file...]

Converts CSV records to PostScript mailing labels, using the first three fields
of each input record as the address.

The options are:

	-f font
		Use the named PostScript font (default Times-Roman)
	-m regexp
		Only use input records matching regexp.
		The text being matched is the record with commas separating fields,
		with no quotation marks added.
	-o outfile
		Write labels to outfile (default standard output)
	-p size
		Use text with the given point size (default 12)
	-v vsize
		Use lines of text vsize points apart (default 1.2 * text size)
	-x regexp
		Exclude input records matching regexp.

If the first line of the CSV contains the text "address" (case insensitive),
it is assumed to be a header for the spreadsheet and is skipped.
`)
	os.Exit(2)
}

var (
	font    = flag.String("f", "Times-Bold", "")
	outfile = flag.String("o", "", "")
	ps      = flag.Int("p", 12, "")
	vs      = flag.Int("v", 0, "")
	match   = flag.String("m", "match", "")
	exclude = flag.String("x", "exclude", "")

	matchRE   *regexp.Regexp
	excludeRE *regexp.Regexp
)

func main() {
	log.SetFlags(0)
	flag.Usage = usage
	flag.Parse()

	var input [][]string
	if flag.NArg() == 0 {
		input = readCSV("standard input", os.Stdin)
	} else {
		for _, file := range flag.Args() {
			f, err := os.Open(file)
			if err != nil {
				log.Fatal(err)
			}
			input = append(input, readCSV(file, f)...)
			f.Close()
		}
	}

	if len(input) > 0 && strings.Contains(strings.ToLower(strings.Join(input[0], ",")), "address") {
		// assume this is a heading line
		input = input[1:]
	}

	var buf bytes.Buffer
	if *vs == 0 {
		*vs = (*ps*12 + 5) / 10
	}
	fmt.Fprintf(&buf, prolog, *font, *ps, *vs)

	nlabel := 0
	for _, line := range input {
		if len(line) == 0 {
			continue
		}
		join := strings.Join(line, ",")
		if matchRE != nil && !matchRE.MatchString(join) ||
			excludeRE != nil && excludeRE.MatchString(join) {
			continue
		}

		mark := "mark"
		for i, field := range line {
			if i >= 3 {
				break
			}
			field = strings.TrimSpace(field)
			if field == "" {
				continue
			}
			field = strings.Replace(field, "(", `\(`, -1)
			field = strings.Replace(field, ")", `\)`, -1)
			for _, f := range strings.Split(field, "\n") {
				f = strings.TrimSpace(f)
				if f == "" {
					continue
				}
				fmt.Fprintf(&buf, "%s (%s)", mark, f)
				mark = ""
			}
		}
		if mark == "" {
			nlabel++
			fmt.Fprintf(&buf, " label\n")
		}
	}
	fmt.Fprintf(&buf, "endlabels\n")

	if nlabel == 0 {
		log.Fatal("no labels to create")
	}

	os.Stdout.Write(buf.Bytes())
}

func readCSV(name string, r io.Reader) [][]string {
	rr := csv.NewReader(r)
	rr.FieldsPerRecord = -1
	recs, err := rr.ReadAll()
	if err != nil {
		log.Fatalf("parsing %s: %v", name, err)
	}
	return recs
}

const prolog = `%%!PS-Adobe-2.0

/numlabel 0 def
/%s findfont
/ps %d def
/vs %d def
dup length dict begin
  {1 index /FID ne {def} {pop pop} ifelse} forall
  /Encoding ISOLatin1Encoding def
  currentdict
end
/MyFont exch definefont pop
/MyFont findfont ps scalefont setfont

/inch { 72 mul } bind def

/label {
	numlabel 3 mod 2.75 mul 0.125 add 2.625 2 div add inch
	11 numlabel 3 idiv 1 mul 0.5 add 1 2 div add sub inch
	moveto
	0 counttomark vs mul ps add vs sub -2 div rmoveto
	/max 0 def
	counttomark -1 1 {
		1 sub index stringwidth pop
		dup max gt { /max exch def } { pop } ifelse
	} for
	max 2.625 inch gt { /max 2.625 inch def } if
	max -2 div 0 rmoveto

	counttomark -1 1 {
		pop
		gsave 0 ps rmoveto show grestore
		0 vs rmoveto
	} for
	pop

	/numlabel numlabel 1 add def
	numlabel 30 ge {
		showpage
		/numlabel 0 def
	} if
} def

/endlabels {
	numlabel 0 gt { showpage } if
} def

`
<|endoftext|>


<commit_before>package cmd

import (
	"fmt"
	"log"

	"github.com/rsteube/carapace"
	"github.com/spf13/cobra"
	gitconfig "github.com/tcnksm/go-gitconfig"
	gitlab "github.com/xanzy/go-gitlab"
	"github.com/zaquestion/lab/internal/action"
	"github.com/zaquestion/lab/internal/git"
	lab "github.com/zaquestion/lab/internal/gitlab"
)

// mrCheckoutConfig holds configuration values for calls to lab mr checkout
type mrCheckoutConfig struct {
	branch string
	track  bool
}

var (
	mrCheckoutCfg mrCheckoutConfig
)

// listCmd represents the list command
var checkoutCmd = &cobra.Command{
	Use:   "checkout",
	Short: "Checkout an open merge request",
	Long:  ``,
	Args:  cobra.ExactArgs(1),
	Run: func(cmd *cobra.Command, args []string) {
		rn, mrID, err := parseArgs(args)
		if err != nil {
			log.Fatal(err)
		}

		mrs, err := lab.MRList(rn, gitlab.ListProjectMergeRequestsOptions{
			IIDs: []int{int(mrID)},
		}, 1)
		if err != nil {
			log.Fatal(err)
		}
		if len(mrs) < 1 {
			fmt.Printf("MR #%d not found\n", mrID)
			return
		}

		mr := mrs[0]
		// If the config does not specify a branch, use the mr source branch name
		if mrCheckoutCfg.branch == "" {
			mrCheckoutCfg.branch = mr.SourceBranch
		}
		// By default, fetch to configured branch
		fetchToRef := mrCheckoutCfg.branch

		// If track, make sure we have a remote for the mr author and then set
		// the fetchToRef to the mr author/sourceBranch
		if mrCheckoutCfg.track {
			// Check if remote already exists
			if _, err := gitconfig.Local("remote." + mr.Author.Username + ".url"); err != nil {
				// Find and create remote
				mrProject, err := lab.GetProject(mr.SourceProjectID)
				if err != nil {
					log.Fatal(err)
				}
				if err := git.RemoteAdd(mr.Author.Username, mrProject.SSHURLToRepo, "."); err != nil {
					log.Fatal(err)
				}
			}
			fetchToRef = fmt.Sprintf("refs/remotes/%s/%s", mr.Author.Username, mr.SourceBranch)
		}

		// https://docs.gitlab.com/ce/user/project/merge_requests/#checkout-merge-requests-locally
		mrRef := fmt.Sprintf("refs/merge-requests/%d/head", mrID)
		fetchRefSpec := fmt.Sprintf("%s:%s", mrRef, fetchToRef)
		if err := git.New("fetch", forkedFromRemote, fetchRefSpec).Run(); err != nil {
			log.Fatal(err)
		}

		if mrCheckoutCfg.track {
			// Create configured branch with tracking from fetchToRef
			// git branch --flags <branchname> [<start-point>]
			if err := git.New("branch", "--track", mrCheckoutCfg.branch, fetchToRef).Run(); err != nil {
				log.Fatal(err)
			}
		}

		// Check out branch
		if err := git.New("checkout", mrCheckoutCfg.branch).Run(); err != nil {
			log.Fatal(err)
		}
	},
}

func init() {
	checkoutCmd.Flags().StringVarP(&mrCheckoutCfg.branch, "branch", "b", "", "checkout merge request with <branch> name")
	checkoutCmd.Flags().BoolVarP(&mrCheckoutCfg.track, "track", "t", false, "set checked out branch to track mr author remote branch, adds remote if needed")
	mrCmd.AddCommand(checkoutCmd)
	carapace.Gen(checkoutCmd).PositionalCompletion(
		carapace.ActionCallback(func(args []string) carapace.Action {
			return action.MergeRequests(mrList).Callback([]string{"origin"})
		}),
	)
}
<commit_msg>mr_checkout: fix usage message<commit_after>package cmd

import (
	"fmt"
	"log"

	"github.com/rsteube/carapace"
	"github.com/spf13/cobra"
	gitconfig "github.com/tcnksm/go-gitconfig"
	gitlab "github.com/xanzy/go-gitlab"
	"github.com/zaquestion/lab/internal/action"
	"github.com/zaquestion/lab/internal/git"
	lab "github.com/zaquestion/lab/internal/gitlab"
)

// mrCheckoutConfig holds configuration values for calls to lab mr checkout
type mrCheckoutConfig struct {
	branch string
	track  bool
}

var (
	mrCheckoutCfg mrCheckoutConfig
)

// listCmd represents the list command
var checkoutCmd = &cobra.Command{
	Use:   "checkout <id>",
	Short: "Checkout an open merge request",
	Long:  ``,
	Args:  cobra.ExactArgs(1),
	Run: func(cmd *cobra.Command, args []string) {
		rn, mrID, err := parseArgs(args)
		if err != nil {
			log.Fatal(err)
		}

		mrs, err := lab.MRList(rn, gitlab.ListProjectMergeRequestsOptions{
			IIDs: []int{int(mrID)},
		}, 1)
		if err != nil {
			log.Fatal(err)
		}
		if len(mrs) < 1 {
			fmt.Printf("MR #%d not found\n", mrID)
			return
		}

		mr := mrs[0]
		// If the config does not specify a branch, use the mr source branch name
		if mrCheckoutCfg.branch == "" {
			mrCheckoutCfg.branch = mr.SourceBranch
		}
		// By default, fetch to configured branch
		fetchToRef := mrCheckoutCfg.branch

		// If track, make sure we have a remote for the mr author and then set
		// the fetchToRef to the mr author/sourceBranch
		if mrCheckoutCfg.track {
			// Check if remote already exists
			if _, err := gitconfig.Local("remote." + mr.Author.Username + ".url"); err != nil {
				// Find and create remote
				mrProject, err := lab.GetProject(mr.SourceProjectID)
				if err != nil {
					log.Fatal(err)
				}
				if err := git.RemoteAdd(mr.Author.Username, mrProject.SSHURLToRepo, "."); err != nil {
					log.Fatal(err)
				}
			}
			fetchToRef = fmt.Sprintf("refs/remotes/%s/%s", mr.Author.Username, mr.SourceBranch)
		}

		// https://docs.gitlab.com/ce/user/project/merge_requests/#checkout-merge-requests-locally
		mrRef := fmt.Sprintf("refs/merge-requests/%d/head", mrID)
		fetchRefSpec := fmt.Sprintf("%s:%s", mrRef, fetchToRef)
		if err := git.New("fetch", forkedFromRemote, fetchRefSpec).Run(); err != nil {
			log.Fatal(err)
		}

		if mrCheckoutCfg.track {
			// Create configured branch with tracking from fetchToRef
			// git branch --flags <branchname> [<start-point>]
			if err := git.New("branch", "--track", mrCheckoutCfg.branch, fetchToRef).Run(); err != nil {
				log.Fatal(err)
			}
		}

		// Check out branch
		if err := git.New("checkout", mrCheckoutCfg.branch).Run(); err != nil {
			log.Fatal(err)
		}
	},
}

func init() {
	checkoutCmd.Flags().StringVarP(&mrCheckoutCfg.branch, "branch", "b", "", "checkout merge request with <branch> name")
	checkoutCmd.Flags().BoolVarP(&mrCheckoutCfg.track, "track", "t", false, "set checked out branch to track mr author remote branch, adds remote if needed")
	mrCmd.AddCommand(checkoutCmd)
	carapace.Gen(checkoutCmd).PositionalCompletion(
		carapace.ActionCallback(func(args []string) carapace.Action {
			return action.MergeRequests(mrList).Callback([]string{"origin"})
		}),
	)
}
<|endoftext|>


<commit_before>package source

import (
	"testing"
)

const (
	EVENTS_COUNT = 92
	THINGS_COUNT = 10

	THING_EVENTS_COUNT = 52
)

func TestThings(t *testing.T) {
	ds := NewMongoDataSource()

	count := ds.GetThingCount()
	if count != THINGS_COUNT {
		t.Errorf("Expected %d, returned %d", THINGS_COUNT, count)
	}

	things := ds.GetThings()
	count = len(things)
	if count != THINGS_COUNT {
		t.Errorf("Expected %d, returned %d", THINGS_COUNT, count)
	}

	count = len(ds.GetThingEvents(0, "nb-wt450-8"))
	if count != THING_EVENTS_COUNT {
		t.Errorf("Expected %d, returned %d", THING_EVENTS_COUNT, count)
	}

	count = len(ds.GetThingEvents(10, "nb-wt450-8"))
	if count != 10 {
		t.Errorf("Expected %d, returned %d", 10, count)
	}

	/*
		func (m *MongoDataSource) PutThing(dev *api.Thing) {
		func (m *MongoDataSource) SaveState(dev *api.Thing, state map[string]interface{}) {
	*/
}

func TestEvents(t *testing.T) {
	ds := NewMongoDataSource()

	events_count := ds.GetEventsCount()
	if events_count != EVENTS_COUNT {
		t.Errorf("Expected %d, returned %d", EVENTS_COUNT, events_count)
	}

	events_count = len(ds.GetEvents(0))
	if events_count != EVENTS_COUNT {
		t.Errorf("Expected %d, returned %d", EVENTS_COUNT, events_count)
	}

	events_count = len(ds.GetEvents(100))
	if events_count != EVENTS_COUNT {
		t.Errorf("Expected %d, returned %d", EVENTS_COUNT, events_count)
	}

	events_count = len(ds.GetEvents(50))
	if events_count != 50 {
		t.Errorf("Expected %d, returned %d", 50, events_count)
	}

	/*
		func (m *MongoDataSource) PutEvent(evt *api.Event) {
	*/
}
<commit_msg>Comment out test case for now.<commit_after>package source

import (
	"testing"
)

const (
	EVENTS_COUNT = 92
	THINGS_COUNT = 10

	THING_EVENTS_COUNT = 52
)

func TestThings(t *testing.T) {
	ds := NewMongoDataSource()

	count := ds.GetThingCount()
	if count != THINGS_COUNT {
		t.Errorf("Expected %d, returned %d", THINGS_COUNT, count)
	}

	things := ds.GetThings()
	count = len(things)
	if count != THINGS_COUNT {
		t.Errorf("Expected %d, returned %d", THINGS_COUNT, count)
	}

	count = len(ds.GetThingEvents(0, "nb-wt450-8"))
	if count != THING_EVENTS_COUNT {
		t.Errorf("Expected %d, returned %d", THING_EVENTS_COUNT, count)
	}

	count = len(ds.GetThingEvents(10, "nb-wt450-8"))
	if count != 10 {
		t.Errorf("Expected %d, returned %d", 10, count)
	}

	/*
		func (m *MongoDataSource) PutThing(dev *api.Thing) {
		func (m *MongoDataSource) SaveState(dev *api.Thing, state map[string]interface{}) {
	*/
}

func TestEvents(t *testing.T) {
	/*

		ds := NewMongoDataSource()

		events_count := ds.GetEventsCount()
		if events_count != EVENTS_COUNT {
			t.Errorf("Expected %d, returned %d", EVENTS_COUNT, events_count)
		}

		events_count = len(ds.GetEvents(0))
		if events_count != EVENTS_COUNT {
			t.Errorf("Expected %d, returned %d", EVENTS_COUNT, events_count)
		}

		events_count = len(ds.GetEvents(100))
		if events_count != EVENTS_COUNT {
			t.Errorf("Expected %d, returned %d", EVENTS_COUNT, events_count)
		}

		events_count = len(ds.GetEvents(50))
		if events_count != 50 {
			t.Errorf("Expected %d, returned %d", 50, events_count)
		}
	*/

	/*
		func (m *MongoDataSource) PutEvent(evt *api.Event) {
	*/
}
<|endoftext|>


<commit_before>package repos

import (
	"log"
	"time"

	"github.com/khades/servbot/models"
	"gopkg.in/mgo.v2/bson"
)

var autoMessageCollectionName = "autoMessages"

func DecrementAutoMessages(channelID *string) {
	channelInfo, error := GetChannelInfo(channelID)
	games := []string{""}
	if error == nil && channelInfo.StreamStatus.Online == true {
		games = append(games, channelInfo.StreamStatus.Game)
	}
	Db.C(autoMessageCollectionName).UpdateAll(bson.M{
		"channelid": *channelID,
		"message":   bson.M{"$ne": ""},
		"$or": bson.D{
			{"game", bson.M{"$in": games}},
			{"game", bson.M{"$exists": false}}}},
		bson.M{"$inc": bson.M{"messagethreshold": -1}})
}

func GetCurrentAutoMessages() (*[]models.AutoMessage, error) {
	//log.Println("AutoMessage: Getting Current AutoMessages")
	var result []models.AutoMessage
	error := Db.C(autoMessageCollectionName).Find(bson.M{
		"message":           bson.M{"$ne": ""},
		"messagethreshold":  bson.M{"$lte": 0},
		"durationthreshold": bson.M{"$lte": time.Now()}}).All(&result)
	log.Printf("AutoMessage: Got %d AutoMessages", len(result))
	//log.Println(error)
	return &result, error
}

func ResetAutoMessageThreshold(autoMessage *models.AutoMessage) {
	log.Printf("AutoMessage: Resetting AutoMessage %s", autoMessage.ID)
	now := time.Now()
	Db.C(autoMessageCollectionName).Update(bson.M{"_id": autoMessage.ID}, bson.M{"$set": bson.M{
		"messagethreshold":  autoMessage.MessageLimit,
		"durationthreshold": now.Add(autoMessage.DurationLimit)}})
}

func GetAutoMessage(id *string, channelID *string) (*models.AutoMessageWithHistory, error) {
	var result models.AutoMessageWithHistory
	objectID := bson.ObjectIdHex(*id)
	error := Db.C(autoMessageCollectionName).Find(bson.M{"_id": objectID, "channelid": *channelID}).One(&result)
	return &result, error
}

func GetAutoMessages(channelID *string) (*[]models.AutoMessage, error) {
	var result []models.AutoMessage
	error := Db.C(autoMessageCollectionName).Find(bson.M{"channelid": *channelID}).All(&result)
	return &result, error
}
func CreateAutoMessage(autoMessageUpdate *models.AutoMessageUpdate) *bson.ObjectId {
	id := bson.NewObjectId()
	now := time.Now()
	var durationLimit = time.Second * time.Duration(autoMessageUpdate.DurationLimit)
	Db.C(autoMessageCollectionName).Insert(
		models.AutoMessageWithHistory{
			AutoMessage: models.AutoMessage{
				ID:                id,
				ChannelID:         autoMessageUpdate.ChannelID,
				Message:           autoMessageUpdate.Message,
				MessageThreshold:  autoMessageUpdate.MessageLimit,
				MessageLimit:      autoMessageUpdate.MessageLimit,
				DurationLimit:     durationLimit,
				DurationThreshold: now.Add(durationLimit)},
			History: []models.AutoMessageHistory{
				models.AutoMessageHistory{
					User:   autoMessageUpdate.User,
					UserID: autoMessageUpdate.UserID,

					Date:          now,
					Message:       autoMessageUpdate.Message,
					MessageLimit:  autoMessageUpdate.MessageLimit,
					DurationLimit: durationLimit}}})
	return &id
}

func UpdateAutoMessage(autoMessageUpdate *models.AutoMessageUpdate) {
	now := time.Now()
	var durationLimit = time.Second * time.Duration(autoMessageUpdate.DurationLimit)
	Db.C(autoMessageCollectionName).Update(
		bson.M{"_id": bson.ObjectIdHex(autoMessageUpdate.ID), "channelid": autoMessageUpdate.ChannelID},
		bson.M{
			"$push": bson.M{
				"history": bson.M{
					"$each": []models.AutoMessageHistory{models.AutoMessageHistory{
						User:   autoMessageUpdate.User,
						UserID: autoMessageUpdate.UserID,
						Game:   autoMessageUpdate.Game,
						Date:          now,
						Message:       autoMessageUpdate.Message,
						MessageLimit:  autoMessageUpdate.MessageLimit,
						DurationLimit: durationLimit}},
					"$sort":  bson.M{"date": -1},
					"$slice": 5}},

			"$set": models.AutoMessage{
				ChannelID:         autoMessageUpdate.ChannelID,
				Message:           autoMessageUpdate.Message,
				MessageThreshold:  autoMessageUpdate.MessageLimit,
				MessageLimit:      autoMessageUpdate.MessageLimit,
				Game:              autoMessageUpdate.Game,
				DurationLimit:     durationLimit,
				DurationThreshold: now.Add(durationLimit)}})

}
<commit_msg>Fix: fixing autodecrement with new automessage system<commit_after>package repos

import (
	"log"
	"time"

	"github.com/khades/servbot/models"
	"gopkg.in/mgo.v2/bson"
)

var autoMessageCollectionName = "autoMessages"

func DecrementAutoMessages(channelID *string) {
	channelInfo, error := GetChannelInfo(channelID)
	games := []string{""}
	if error == nil && channelInfo.StreamStatus.Online == true {
		games = append(games, channelInfo.StreamStatus.Game)
	}
	Db.C(autoMessageCollectionName).UpdateAll(bson.M{
		"channelid": *channelID,
		"message":   bson.M{"$ne": ""},
		"$or": []bson.M{
			bson.M{"game": bson.M{"$in": games}},
			bson.M{"game": bson.M{"$exists": false}}}},
		bson.M{"$inc": bson.M{"messagethreshold": -1}})
}

func GetCurrentAutoMessages() (*[]models.AutoMessage, error) {
	//log.Println("AutoMessage: Getting Current AutoMessages")
	var result []models.AutoMessage
	error := Db.C(autoMessageCollectionName).Find(bson.M{
		"message":           bson.M{"$ne": ""},
		"messagethreshold":  bson.M{"$lte": 0},
		"durationthreshold": bson.M{"$lte": time.Now()}}).All(&result)
	log.Printf("AutoMessage: Got %d AutoMessages", len(result))
	//log.Println(error)
	return &result, error
}

func ResetAutoMessageThreshold(autoMessage *models.AutoMessage) {
	log.Printf("AutoMessage: Resetting AutoMessage %s", autoMessage.ID)
	now := time.Now()
	Db.C(autoMessageCollectionName).Update(bson.M{"_id": autoMessage.ID}, bson.M{"$set": bson.M{
		"messagethreshold":  autoMessage.MessageLimit,
		"durationthreshold": now.Add(autoMessage.DurationLimit)}})
}

func GetAutoMessage(id *string, channelID *string) (*models.AutoMessageWithHistory, error) {
	var result models.AutoMessageWithHistory
	objectID := bson.ObjectIdHex(*id)
	error := Db.C(autoMessageCollectionName).Find(bson.M{"_id": objectID, "channelid": *channelID}).One(&result)
	return &result, error
}

func GetAutoMessages(channelID *string) (*[]models.AutoMessage, error) {
	var result []models.AutoMessage
	error := Db.C(autoMessageCollectionName).Find(bson.M{"channelid": *channelID}).All(&result)
	return &result, error
}
func CreateAutoMessage(autoMessageUpdate *models.AutoMessageUpdate) *bson.ObjectId {
	id := bson.NewObjectId()
	now := time.Now()
	var durationLimit = time.Second * time.Duration(autoMessageUpdate.DurationLimit)
	Db.C(autoMessageCollectionName).Insert(
		models.AutoMessageWithHistory{
			AutoMessage: models.AutoMessage{
				ID:                id,
				ChannelID:         autoMessageUpdate.ChannelID,
				Message:           autoMessageUpdate.Message,
				MessageThreshold:  autoMessageUpdate.MessageLimit,
				MessageLimit:      autoMessageUpdate.MessageLimit,
				DurationLimit:     durationLimit,
				DurationThreshold: now.Add(durationLimit)},
			History: []models.AutoMessageHistory{
				models.AutoMessageHistory{
					User:   autoMessageUpdate.User,
					UserID: autoMessageUpdate.UserID,

					Date:          now,
					Message:       autoMessageUpdate.Message,
					MessageLimit:  autoMessageUpdate.MessageLimit,
					DurationLimit: durationLimit}}})
	return &id
}

func UpdateAutoMessage(autoMessageUpdate *models.AutoMessageUpdate) {
	now := time.Now()
	var durationLimit = time.Second * time.Duration(autoMessageUpdate.DurationLimit)
	Db.C(autoMessageCollectionName).Update(
		bson.M{"_id": bson.ObjectIdHex(autoMessageUpdate.ID), "channelid": autoMessageUpdate.ChannelID},
		bson.M{
			"$push": bson.M{
				"history": bson.M{
					"$each": []models.AutoMessageHistory{models.AutoMessageHistory{
						User:          autoMessageUpdate.User,
						UserID:        autoMessageUpdate.UserID,
						Game:          autoMessageUpdate.Game,
						Date:          now,
						Message:       autoMessageUpdate.Message,
						MessageLimit:  autoMessageUpdate.MessageLimit,
						DurationLimit: durationLimit}},
					"$sort":  bson.M{"date": -1},
					"$slice": 5}},

			"$set": models.AutoMessage{
				ChannelID:         autoMessageUpdate.ChannelID,
				Message:           autoMessageUpdate.Message,
				MessageThreshold:  autoMessageUpdate.MessageLimit,
				MessageLimit:      autoMessageUpdate.MessageLimit,
				Game:              autoMessageUpdate.Game,
				DurationLimit:     durationLimit,
				DurationThreshold: now.Add(durationLimit)}})

}
<|endoftext|>


<commit_before>/*
Copyright 2021 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 version

import (
	"bytes"
	"fmt"
	"net/url"
	"strings"

	"github.com/blang/semver"
	"k8s.io/kops/tests/e2e/pkg/util"
)

// ParseKubernetesVersion will parse the provided k8s version
// Either a semver or marker URL is accepted
func ParseKubernetesVersion(version string) (string, error) {
	if _, err := semver.ParseTolerant(version); err == nil {
		return version, nil
	}
	if u, err := url.Parse(version); err == nil {
		var b bytes.Buffer
		err = util.HTTPGETWithHeaders(version, nil, &b)
		if err != nil {
			return "", err
		}

		// Replace the last part of the version URL path with the contents of the URL's body
		// Example:
		// https://storage.googleapis.com/kubernetes-release-dev/ci/latest.txt -> v1.21.0-beta.1.112+576aa2d2470b28%0A
		// becomes https://storage.googleapis.com/kubernetes-release-dev/ci/v1.21.0-beta.1.112+576aa2d2470b28%0A
		pathParts := strings.Split(u.Path, "/")
		pathParts[len(pathParts)-1] = b.String()
		u.Path = strings.Join(pathParts, "/")
		return strings.TrimSpace(u.String()), nil
	}
	return "", fmt.Errorf("unexpected kubernetes version: %v", version)
}
<commit_msg>Remove trailing newline from kubernetes version marker<commit_after>/*
Copyright 2021 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 version

import (
	"bytes"
	"fmt"
	"net/url"
	"strings"

	"github.com/blang/semver"
	"k8s.io/kops/tests/e2e/pkg/util"
)

// ParseKubernetesVersion will parse the provided k8s version
// Either a semver or marker URL is accepted
func ParseKubernetesVersion(version string) (string, error) {
	if _, err := semver.ParseTolerant(version); err == nil {
		return version, nil
	}
	if u, err := url.Parse(version); err == nil {
		var b bytes.Buffer
		err = util.HTTPGETWithHeaders(version, nil, &b)
		if err != nil {
			return "", err
		}

		// Replace the last part of the version URL path with the contents of the URL's body
		// Example:
		// https://storage.googleapis.com/kubernetes-release-dev/ci/latest.txt -> v1.21.0-beta.1.112+576aa2d2470b28%0A
		// becomes https://storage.googleapis.com/kubernetes-release-dev/ci/v1.21.0-beta.1.112+576aa2d2470b28%0A
		pathParts := strings.Split(u.Path, "/")
		pathParts[len(pathParts)-1] = strings.TrimSpace(b.String())
		u.Path = strings.Join(pathParts, "/")
		return strings.TrimSpace(u.String()), nil
	}
	return "", fmt.Errorf("unexpected kubernetes version: %v", version)
}
<|endoftext|>